What's New in the Entity Framework 4.0

by Tom Dykstra

This tutorial series builds on the Contoso University web application that is created by the Getting Started with the Entity Framework tutorial series. If you didn't complete the earlier tutorials, as a starting point for this tutorial you can download the application that you would have created. You can also download the application that is created by the complete tutorial series. If you have questions about the tutorials, you can post them to the ASP.NET Entity Framework forum.

In the previous tutorial you saw some methods for maximizing the performance of a web application that uses the Entity Framework. This tutorial reviews some of the most important new features in version 4 of the Entity Framework, and it links to resources that provide a more complete introduction to all of the new features. The features highlighted in this tutorial include the following:

  • Foreign-key associations.
  • Executing user-defined SQL commands.
  • Model-first development.
  • POCO support.

In addition, the tutorial will briefly introduce code-first development, a feature that's coming in the next release of the Entity Framework.

To start the tutorial, start Visual Studio and open the Contoso University web application that you were working with in the previous tutorial.

Foreign-Key Associations

Version 3.5 of the Entity Framework included navigation properties, but it didn't include foreign-key properties in the data model. For example, the CourseID and StudentID columns of the StudentGrade table would be omitted from the StudentGrade entity.

Image01

The reason for this approach was that, strictly speaking, foreign keys are a physical implementation detail and don't belong in a conceptual data model. However, as a practical matter, it's often easier to work with entities in code when you have direct access to the foreign keys.

For an example of how foreign keys in the data model can simplify your code, consider how you would have had to code the DepartmentsAdd.aspx page without them. In the Department entity, the Administrator property is a foreign key that corresponds to PersonID in the Person entity. In order to establish the association between a new department and its administrator, all you had to do was set the value for the Administrator property in the ItemInserting event handler of the databound control:

protected void DepartmentsDetailsView_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
    e.Values["Administrator"] = administratorsDropDownList.SelectedValue;
}

Without foreign keys in the data model, you'd handle the Inserting event of the data source control instead of the ItemInserting event of the databound control, in order to get a reference to the entity itself before the entity is added to the entity set. When you have that reference, you establish the association using code like that in the following examples:

departmentEntityToBeInserted.PersonReference.EntityKey = new System.Data.EntityKey("SchoolEntities.Departments", "PersonID", Convert.ToInt32(administratorsDropDownList.SelectedValue));
departmentEntityToBeInserted.Person = context.People.Single(p => p.PersonID == Convert.ToInt32(administratorsDropDownList.SelectedValue));

As you can see in the Entity Framework team's blog post on Foreign Key associations, there are other cases where the difference in code complexity is much greater. To meet the needs of those who prefer to live with implementation details in the conceptual data model for the sake of simpler code, the Entity Framework now gives you the option of including foreign keys in the data model.

In Entity Framework terminology, if you include foreign keys in the data model you're using foreign key associations, and if you exclude foreign keys you're using independent associations.

Executing User-Defined SQL Commands

In earlier versions of the Entity Framework, there was no easy way to create your own SQL commands on the fly and run them. Either the Entity Framework dynamically generated SQL commands for you, or you had to create a stored procedure and import it as a function. Version 4 adds ExecuteStoreQuery and ExecuteStoreCommand methods the ObjectContext class that make it easier for you to pass any query directly to the database.

Suppose Contoso University administrators want to be able to perform bulk changes in the database without having to go through the process of creating a stored procedure and importing it into the data model. Their first request is for a page that lets them change the number of credits for all courses in the database. On the web page, they want to be able to enter a number to use to multiply the value of every Course row's Credits column.

Create a new page that uses the Site.Master master page and name it UpdateCredits.aspx. Then add the following markup to the Content control named Content2:

<h2>Update Credits</h2>
    Enter the number to multiply the current number of credits by: 
    <asp:TextBox ID="CreditsMultiplierTextBox" runat="server"></asp:TextBox>
    <br /><br />
    <asp:Button ID="ExecuteButton" runat="server" Text="Execute" OnClick="ExecuteButton_Click" /><br /><br />
    Rows affected:
    <asp:Label ID="RowsAffectedLabel" runat="server" Text="0" ViewStateMode="Disabled"></asp:Label><br /><br />

This markup creates a TextBox control in which the user can enter the multiplier value, a Button control to click in order to execute the command, and a Label control for indicating the number of rows affected.

Open UpdateCredits.aspx.cs, and add the following using statement and a handler for the button's Click event:

using ContosoUniversity.DAL;
protected void ExecuteButton_Click(object sender, EventArgs e)
{
    using (SchoolEntities context = new SchoolEntities())
    {
        RowsAffectedLabel.Text = context.ExecuteStoreCommand("UPDATE Course SET Credits = Credits * {0}", CreditsMultiplierTextBox.Text).ToString();
    }
}

This code executes the SQL Update command using the value in the text box and uses the label to display the number of rows affected. Before you run the page, run the Courses.aspx page to get a "before" picture of some data.

Image02

Run UpdateCredits.aspx, enter "10" as the multiplier, and then click Execute.

Image03

Run the Courses.aspx page again to see the changed data.

Image04

(If you want to set the number of credits back to their original values, in UpdateCredits.aspx.cs change Credits * {0} to Credits / {0} and re-run the page, entering 10 as the divisor.)

For more information about executing queries that you define in code, see How to: Directly Execute Commands Against the Data Source.

Model-First Development

In these walkthroughs you created the database first and then generated the data model based on the database structure. In the Entity Framework 4 you can start with the data model instead and generate the database based on the data model structure. If you're creating an application for which the database doesn't already exist, the model-first approach enables you to create entities and relationships that make sense conceptually for the application, while not worrying about physical implementation details. (This remains true only through the initial stages of development, however. Eventually the database will be created and will have production data in it, and recreating it from the model will no longer be practical; at that point you'll be back to the database-first approach.)

In this section of the tutorial, you'll create a simple data model and generate the database from it.

In Solution Explorer, right-click the DAL folder and select Add New Item. In the Add New Item dialog box, under Installed Templates select Data and then select the ADO.NET Entity Data Model template. Name the new file AlumniAssociationModel.edmx and click Add.

Image06

This launches the Entity Data Model Wizard. In the Choose Model Contents step, select Empty Model and then click Finish.

Image07

The Entity Data Model Designer opens with a blank design surface. Drag an Entity item from the Toolbox onto the design surface.

Image08

Change the entity name from Entity1 to Alumnus, change the Id property name to AlumnusId, and add a new scalar property named Name. To add new properties you can press Enter after changing the name of the Id column, or right-click the entity and select Add Scalar Property. The default type for new properties is String, which is fine for this simple demonstration, but of course you can change things like data type in the Properties window.

Create another entity the same way and name it Donation. Change the Id property to DonationId and add a scalar property named DateAndAmount.

Image09

To add an association between these two entities, right-click the Alumnus entity, select Add, and then select Association.

Image10

The default values in the Add Association dialog box are what you want (one-to-many, include navigation properties, include foreign keys), so just click OK.

Image11

The designer adds an association line and a foreign-key property.

Image12

Now you're ready to create the database. Right-click the design surface and select Generate Database from Model.

Image13

This launches the Generate Database Wizard. (If you see warnings that indicate that the entities aren't mapped, you can ignore those for the time being.)

In the Choose Your Data Connection step, click New Connection.

Image14

In the Connection Properties dialog box, select the local SQL Server Express instance and name the database AlumniAssociation.

Image15

Click Yes when you're asked if you want to create the database. When the Choose Your Data Connection step is displayed again, click Next.

In the Summary and Settings step, click Finish.

Image18

A .sql file with the data definition language (DDL) commands is created, but the commands haven't been run yet.

Image20

Use a tool such as SQL Server Management Studio to run the script and create the tables, as you might have done when you created the School database for the first tutorial in the Getting Started tutorial series. (Unless you downloaded the database.)

You can now use the AlumniAssociation data model in your web pages the same way you've been using the School model. To try this out, add some data to the tables and create a web page that displays the data.

Using Server Explorer, add the following rows to the Alumnus and Donation tables.

Image21

Create a new web page named Alumni.aspx that uses the Site.Master master page. Add the following markup to the Content control named Content2:

<h2>Alumni</h2>
    <asp:EntityDataSource ID="AlumniEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.AlumniAssociationModelContainer" EnableFlattening="False" 
        EntitySetName="Alumni">
    </asp:EntityDataSource>
    <asp:GridView ID="AlumniGridView" runat="server" 
        DataSourceID="AlumniEntityDataSource" AutoGenerateColumns="False"
        OnRowDataBound="AlumniGridView_RowDataBound"
        DataKeyNames="AlumnusId">
        <Columns>
            <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
            <asp:TemplateField HeaderText="Donations">
                <ItemTemplate>
                    <asp:GridView ID="DonationsGridView" runat="server" AutoGenerateColumns="False">
                        <Columns>
                            <asp:BoundField DataField="DateAndAmount" HeaderText="Date and Amount" />
                        </Columns>
                    </asp:GridView>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

This markup creates nested GridView controls, the outer one to display alumni names and the inner one to display donation dates and amounts.

Open Alumni.aspx.cs. Add a using statement for the data access layer and a handler for the outer GridView control's RowDataBound event:

using ContosoUniversity.DAL; 

// ...

protected void AlumniGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        var alumnus = e.Row.DataItem as Alumnus;
        var donationsGridView = (GridView)e.Row.FindControl("DonationsGridView");
        donationsGridView.DataSource = alumnus.Donations.ToList();
        donationsGridView.DataBind();
    }
}

This code databinds the inner GridView control using the Donations navigation property of the current row's Alumnus entity.

Run the page.

Image22

(Note: This page is included in the downloadable project, but to make it work you must create the database in your local SQL Server Express instance; the database isn't included as an .mdf file in the App_Data folder.)

For more information about using the model-first feature of the Entity Framework, see Model-First in the Entity Framework 4.

POCO Support

When you use domain-driven design methodology, you design data classes that represent data and behavior that's relevant to the business domain. These classes should be independent of any specific technology used to store (persist) the data; in other words, they should be persistence ignorant. Persistence ignorance can also make a class easier to unit test because the unit test project can use whatever persistence technology is most convenient for testing. Earlier versions of the Entity Framework offered limited support for persistence ignorance because entity classes had to inherit from the EntityObject class and thus included a great deal of Entity Framework-specific functionality.

The Entity Framework 4 introduces the ability to use entity classes that don't inherit from the EntityObject class and therefore are persistence ignorant. In the context of the Entity Framework, classes like this are typically called plain-old CLR objects (POCO, or POCOs). You can write POCO classes manually, or you can automatically generate them based on an existing data model using Text Template Transformation Toolkit (T4) templates provided by the Entity Framework.

For more information about using POCOs in the Entity Framework, see the following resources:

Code-First Development

POCO support in the Entity Framework 4 still requires that you create a data model and link your entity classes to the data model. The next release of the Entity Framework will include a feature called code-first development. This feature enables you to use the Entity Framework with your own POCO classes without needing to use either the data model designer or a data model XML file. (Therefore, this option has also been called code-only; code-first and code-only both refer to the same Entity Framework feature.)

For more information about using the code-first approach to development, see the following resources:

In addition, a new MVC Code-First tutorial that builds an application similar to the Contoso University application is projected to be published in the spring of 2011 at https://asp.net/entity-framework/tutorials

More Information

This completes the overview to what's new in the Entity Framework and this Continuing with the Entity Framework tutorial series. For more information about new features in the Entity Framework 4 that aren't covered here, see the following resources: