Introducing the Entity Framework

Welcome to this installment of the .NET Nuts & Bolts column. A few the recent .NET Nuts & Bolts columns have been about LINQ. Articles such as an Introduction to Language Integrated Query (LINQ), LINQ to XML, and LINQ to SQL have explained what LINQ is and how to use it with XML and SQL. This article introduces yet another flavor—LINQ to Entities, which is a part of the Entity Framework.

Introduction to the Entity Framework

The Entity Framework is a new part of ADO.NET that allows you to build your applications against conceptual data models. It provides a greater level of abstraction and supports code that is independent of any particular relational database. It provides an Entity Data Model (EDM) for defining data at the database and conceptual level and mapping between the two. It includes a nice set of tools that can be used to generate the EDM and corresponding objects that represent the database. This eliminates much of the required boilerplate data access code, and makes it a snap to create data-centric applications.

Generating the Entity Data Model

You'll find the simplicity of generating Entity Data Models a pleasant surprise. And it's even more pleasant when you discover how simple it is to keep the model synchronized with the database. The examples in this article use the Northwind sample database in SQL Server. First, create a new Console application to use in this example. Next, add an EDM object to the project (see Step 1, below). It is possible to use the EDM Generator command prompt utility, but given that I'm a fan of GUIs and simplicity, I prefer to use the integrated set of Entity Data Model tools released with Visual Studio 2008 Service Pack 1. Here are the steps:

  1. Right-click the project in Solution Explorer, elect to add a new item, choose "ADO.NET Entity Data Model" as the new item type, and name it NorthwindModel.edmx. This initiates the Entity Data Model Wizard in Visual Studio, where you can generate the model from a database or create an empty model (see Figure 1).
  2. In the next wizard step, choose your data connection. For this example, I established a new connection to the Northwind database on my local SQL Server instance (see Figure 2). I tested the connection, verified that it was working, and then allowed it to save the connection setting in the app.config file.


  3. The final step in the wizard is to choose which database objects you want to include in your model (see Figure 3). For this example, I chose the entire Tables tree, and then clicked Finish to generate the model.


Completing the wizard resulted in Visual Studio displaying a design surface with a model similar to the one in Figure 4 (I rearranged some of the shapes so that the entire model fit on the screen).

The integrated wizard in Visual Studio 2008 makes the process straightforward. I have used other third-party components that follow the same process to establish a model that can connect to Oracle or some other database provider as well.

Introducing the Entity Framework

Working with the Entity Data Model

Now that you have a generated Entity Data Model, I'll show you some of the ways that you can work with it.

Changing the Model

One powerful aspect of the Entity Framework is the abstraction it provides between the physical database and the conceptual model that represents it. You can put that to the test straightaway by making some changes to the conceptual model.

On the design surface, find the Customers object, click on the Phone attribute and view its properties in the Properties window. Change the name from Phone to PrimaryPhone. You can click the Mapping Details tab to see that the database column for Phone is now mapped to a conceptual model of PrimaryPhone (see Figure 5). This ability to rename items in the conceptual model is quite handy when you find yourself dealing with a data source that has annoyances such as different names for the same column across tables, employs underscores, or uses other naming conventions you find to be goofy or cumbersome. You can alter your conceptual model to apply whatever names you choose. You can also control getter and setter accessibility.

Querying Against the Model

LINQ to Entities truly begins to shine when it comes to querying the model. You will find that the syntax looks much like that of LINQ to SQL—there are different objects involved, and different behaviors at times, but otherwise, it's much the same. The following example code queries the Customers table for customers where they city of record is London. This is almost identical to the code used in the LINQ to SQL article with the exception of the object that provides the context.

using (NorthwindEntities context = new NorthwindEntities())
{
var results = 
   from customers in context.Customers
   where customers.City == "London"
   orderby customers.CompanyName
   select customers;
foreach (var customer in results)
{
  Console.WriteLine("Company: {0}, 
    contact: {1}, primary phone: {2}", 
    customer.CompanyName, 
    customer.ContactName, 
    customer.PrimaryPhone);
}
// Pause to see the output
Console.ReadLine();
}

The preceding code is a very simple example, so it produces only very simple output.

Adding, Updating, or Deleting Against the Model

Adding, updating, and deleting data items is straightforward as long as the underlying table question does not have modeled relationships. You just create an object, set its properties, and use the entity model to persist it to the database. Or, you can update an existing object or indicate that you want it to be removed. The following sample code depicts the process for adding a new category, updating what was added, and then removing it.

// Add a new category
Categories category = new Categories();
category.CategoryName = "Test Category";
category.Description = 
   "This is a test created using entities.";
using (NorthwindEntities context = new NorthwindEntities())
{
   context.AddToCategories(category);
   context.SaveChanges();
}
using (NorthwindEntities context = new NorthwindEntities())
{
   // Find the category we just added and update it
   var result1 = (
      from c in context.Categories
      where c.CategoryName == "Test Category"
      select c).FirstOrDefault();
   if (result1 != null)
   {
      result1.Description = 
         "This is a test updated using entities.";
      context.SaveChanges();
   }
   // Find the category we just updated and remove it
   var result2 = (
      from c in context.Categories
      where c.CategoryName == "Test Category"
      select c).FirstOrDefault();
   if (result2 != null)
   {
      context.DeleteObject(result2);
      context.SaveChanges();
   }
}

Dealing with Relationships in the Model

As you've seen, common actions such as adding or updating modeled items can be straightforward, but complexities can arise when the model contains relationships. In such cases, the model will attempt to add related objects to the database as well. For example, the Northwind database (and the model) contain a relationship between Orders and Customers. Creating a new order and adding it to the database also adds a related customer record, which is great—as long as the customer does not already exist. But if the customer does exist, you need to set up the relationships on your object using an EntityKey object and the appropriate XReference property that represents the relationship between the entities. The following example shows a portion of the code you would need to save an order for an existing customer.

Orders orders = new Orders();
orders.OrderDate = DateTime.Now;
orders.ShipName = "Mr. John Doe";
orders.ShipAddress = "123 Some Place";
orders.ShipCity = "Any Town";
...
orders.CustomersReference.EntityKey = new 
   System.Data.EntityKey("NorthwindEntities.Customers", 
   "CustomerID", customerId);
...
using (NorthwindEntities context = new NorthwindEntities())
{
   context.AddToOrders(orders);
   context.SaveChanges();
}

Other Data Access Technologies Compared

It can certainly be confusing when you have to make choices between multiple data access technologies, so it's worth taking the space for a brief comparison of the Entity Framework and LINQ to Entities and other Microsoft data access technologies.

Compared to LINQ to SQL

After learning about the Entity Framework and LINQ to Entities, it's only natural to think about their similarities with LINQ to SQL. It begs the question: Which of these technologies should you use? And of course, the answer is that it's not a matter of one being better than the other, but more a matter of which one is right for any given situation. I have come across a few tips from various blogs and conversational sources that I'll pass along for your consideration:

  • LINQ to SQL is good when you are targeting SQL Server and you have a 1:1 relationship between your model and the database.
  • LINQ to Entities is fashioned after Object Relational Mapping (ORM) solutions where you may have an object structure that's very different from the structure of the actual database.
  • LINQ to Entities is good for situations where your database is not SQL Server.

Compared to ADO.NET Data Services

ADO.NET Data Services is an additional ADO.NET technology introduced nearly at the same time as LINQ to Entities. However, once you dive in to ADO.NET Data Services you will discover that it serves a different purpose than the Entity Framework and LINQ to Entities. ADO.NET Data Services exposes URL-based interfaces for accessing data in the database. ADO.NET Data Services simply builds on other data access technologies, including LINQ to Entities, to generate a REST-style APIs. ADO.NET Data Services are a great tool when building a rich Internet application that employs Silverlight or client-side JavaScript frameworks to fetch data.

Summing Up

This article presented some Entity Framework basics and some brief examples of LINQ to Entities in action, including common data operations such as add, update, and delete. It also showed an example of how you handle entity references. Finally, you saw a brief comparison between the Entity Framework and LINQ to SQL and ADO.NET Data Services to round out the relationship to other ADO.NET based data access technologies.

The topic of the next column is yet to be determined. If you have something in particular that you would like to see explained here let me know.



About the Author

Mark Strawmyer

Mark Strawmyer is a Senior Architect of .NET applications for large and mid-size organizations. He specializes in architecture, design and development of Microsoft-based solutions. Mark was honored to be named a Microsoft MVP for application development with C# for the fifth year in a row. You can reach Mark at mark.strawmyer@crowehorwath.com.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • With the average hard drive now averaging one terabyte in size, the fallout from the explosion of user-created data has become an overwhelming volume of potential evidence that law-enforcement and corporate investigators spend countless hours examining. Join Us and SANS' Rob Lee for our 45-minute webinar, A Triage and Collection Strategy for Time-Sensitive Investigations, will demonstrate how to: Identify the folders and files that often contain key insights Reduce the time spent sifting through content by …

Most Popular Programming Stories

More for Developers

RSS Feeds