September 2012

Volume 27 Number 09

Data Points - Moving Existing Projects to EF 5

By Julie Lerman | September 2012

Julie LermanAmong changes to the Microsoft .NET Framework 4.5 are a number of modifications and improvements to the core Entity Framework APIs. Most notable is the new way in which Entity Framework caches your LINQ to Entities queries automatically, removing the performance cost of translating a query into SQL when it’s used repeatedly. This feature is referred to as Auto-Compiled Queries, and you can read more about it and other performance improvements in the team’s blog post, “Sneak Preview: Entity Framework 5 Performance Improvements,” at bit.ly/zlx21L. A bonus of this feature is that it’s controlled by the Entity Framework API within the .NET Framework 4.5, so even .NET 4 applications using Entity Framework will benefit “for free” when run on machines with.NET 4.5 installed.

Other useful new features built into the core API require some coding on your part, including support for enums, spatial data types and table-valued functions. The Visual Studio 2012 Entity Data Model (EDM) designer has some new features as well, including the ability to create different views of the model.

I do most of my EF-related coding these days using the DbContext API, which is provided, along with Code First features, separately from the .NET Framework. These features are Microsoft’s way of more fluidly and frequently enhancing Entity Framework, and they’re contained in a single library named EntityFramework.dll, which you can install into your projects via NuGet.

To take advantage of enum support and other features added to EF in the .NET Framework 4.5, you’ll need the compatible version of EntityFramework.dll, EF 5. The first release of this package has the version number 5.

I have lots of applications that use EF 4.3.1. This version includes the migration support introduced in EF 4.3, plus a few minor tweaks that were added shortly after. In this column I’ll show you how to move an application that’s using EF 4.3.1 to EF 5 to take advantage of the new enum support in .NET 4.5. These steps also apply to projects that are using EF 4.1, 4.2 or 4.3.

I’ll start with a simple demo-ware solution that has a project for the DomainClasses, another for the DataLayer and one that’s a console application, as shown in Figure 1.

The Existing Solution That Uses EF 4.3.1
Figure 1 The Existing Solution That Uses EF 4.3.1

This solution was built in Visual Studio 2010 using the .NET Framework 4 and the EF 4.3.1 version of EntityFramework.dll.

The DomainClasses project has two classes stuffed into a single file, shown in Figure 2, using a popular theme for sample code: Twitter. The classes are Tweeter and Tweet.

Figure 2 The Original Domain Classes

using System.ComponentModel.DataAnnotations;
namespace DataPointsDemo.DomainClasses
{
  public class Tweeter
  {
    public Tweeter()
    {
      Tweets = new List<Tweet>();
    }
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
    [MaxLength(10),Column("ExperienceCode")]
    public string Experience { get; set; }
    [MaxLength(30), MinLength(5)]
    public string UserName { get; set; }
    [RegularExpression(@"(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3})")]
    public string Email { get; set; }
    public string Bio { get; set; }
    public DateTime CreateDate { get; set; }
    public byte[] Avatar { get; set; }
    public ICollection<Tweet> Tweets { get; set; }
    public string AliasPlusName
    { get { return Name + "(" + UserName + ")"; } }
  }
  public class Tweet
  {
    public int Id { get; set; }
    public DateTime CreateDate { get; set; }
    public string Content { get; set; }
    [Range(1, 5),Column("RatingCode")]
    public int Rating { get; set; }
    public Tweeter Alias { get; set; }
    public int AliasId { get; set; }
  }
}

This project uses Data Annotations not only to add validations (such as RegularExpression) but also to define some of the configuration—MaxLength, MinLength and Column. The last, Column, specifies the column name in the database table to which the fields Experience and Rating map.

All three projects reference EntityFramework.dll (version 4.3.1). Typically, I keep the EntityFramework.dll and any database knowledge out of my domain classes, but I’ve chosen to include it in this example for demonstrative purposes. The MaxLength, MinLength and Column attributes are in the same namespace as the validations (System.ComponentModel.DataAnnotations), but they’re part of the EntityFramework assembly.

Also notable in the domain classes is the fact that I have two properties that beg to use enums: Tweeter.Experience, which leans on a string for its value, and Tweet.Rating, which uses a numeric value. It’s up to the developer coding against these classes to ensure that the users have the proper values available to them. Why no enums? Because the core Entity Framework API in the .NET Framework 4 doesn’t support enums. But because this was the most-requested feature for Entity Framework and is now part of the .NET Framework 4.5 (and supported by Code First in EF 5), I can use it. So let’s update the solution.

Although I’ve opened my solution in Visual Studio 2012 RC, it’s still targeting .NET 4. The first thing I must do is target my three projects to .NET 4.5, which I can do in the Properties window of each project (see Figure 3). You have to do this one at a time, so if you have a lot of projects you might want to use a script to run against the project files directly.

Changing a .NET Framework 4 Project to .NET Framework 4.5
Figure 3 Changing a .NET Framework 4 Project to .NET Framework 4.5

It’s important to do this step before updating to EF 5. I learned this the hard way and will explain shortly why this is.

Once the projects are targeting the .NET Framework 4.5, you can upgrade to EF 5. Because multiple projects use this assembly, you’ll want to manage the packages for the entire solution rather than updating one project at a time. Manage NuGet Packages is available from the solution’s context menu in Solution Explorer. This will open up the package manager UI. On the left, select Updates. In the middle pane, if you have a current version of the package manager, you’ll see a dropdown box with the options Stable Only and Include Prerelease. If, like me, you’re doing this prior to the full release of.NET 4.5 and EF 5, you’ll need to select Include Prerelease. In my particular solution, EntityFramework is the only package that needs updating so that’s what’s showing up, as you can see in Figure 4. If you’re a fan of working in the package manager console, you can type in “Install-Package EntityFramework –prerelease,” but you’d have to do this separately for each project.

Finding the Entity Framework 5 Prerelease Update
Figure 4 Finding the Entity Framework 5 Prerelease Update

From the wizard, once you trigger the package update, NuGet will ask you which projects to update. Even though all three of my projects use Entity Framework 4.3.1, I’m only going to update the ConsoleApplication and DataLayer, so I’ll deselect DomainClasses. You can watch the status box as it tells you what steps it’s taking. When the update is complete, just close the package manager.

One Package, Two DLLs

Updating to EF 5 affected the two projects in a few ways. First, it replaced the 4.3.1 version of EntityFramework.dll with 5. You should verify this in all of the projects you update. This demonstrates why it’s important to switch to the .NET Framework 4.5 prior to executing the package-update step. The EF 5 package contains two DLLs. One is version 5, which contains all of the DbContext API and Code First features and is compatible with .NET 4.5. The other file is version 4.4. This is the one that remains compatible with .NET 4. By including this DLL in the package, the team avoided the need to maintain two separate NuGet packages for you to worry about. After EF 5 releases, you’ll install the same EF 5 package whenever you want DbContext or Code First support. The package will take care of making sure you have the correct version installed in your project—whether the project is .NET 4 or .NET 4.5.

The first time I did this update, I hadn’t upgraded my projects to .NET 4.5 before the EF update. I couldn’t get the new features to work and was very confused. Then I noticed that the version of EntityFramework.dll was 4.4, which made me more confused. Eventually, I browsed to the package files in the solution and saw that I had two packages, and understood my mistake.

The EF 5 update also modified the app.config file in the Console project and created an app.config file in the DataLayer project. Because my original solution let Code First use its default behavior for automatically detecting the relevant database, I had no connection string or connection factory information in the config file. EF 5 installation added the following section into the <entityFramework> section of the file:

<defaultConnectionFactory
  type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
  <parameters>
    <parameter
       value="Data Source=(localdb)\v11; Integrated Security=True;
              MultipleActiveResultSets=True" />
  </parameters>
</defaultConnectionFactory>

Additionally, it updated app.config’s reference to the EF assembly to reflect the new version number.

Projects that have no config file will get a new app.config with the EF 5 default configuration. That’s why the DataLayer project has an app.config after the update. But I don’t need a config file in that project, so I’ll just delete that file.

What About the DomainClasses Project?

When updating, I skipped the project with the domain classes. The only reason I needed the EntityFramework.dll in the previous version of my solution was to have access to the Data Annotations that were specific to EF. Those have now been moved to the .NET Framework 4.5 assembly, System.ComponentModel.DataAnnotations.dll, to join the other data annotations. So I no longer need to reference EF from that project. In fact, I can now uninstall the EntityFramework reference from that project. Rather than using the package manager UI, I prefer to open up the package manager console window, ensure that I’m targeting the DomainClasses project and then type “uninstall-package entityframework” to remove the package from that project.

There’s one more step, however. Opening the file with the classes reveals a compiler warning for the three data annotations I’m focused on. Originally, they were in the System.ComponentModel.DataAnnotations namespace as part of EntityFramework.dll. But in the .NET assembly where they now live, they’ve moved to a sub-namespace. So I need to add one more using statement to the top of the code file:

using System.ComponentModel.DataAnnotations.Schema;

With this, the compiler is happy and so am I, because I’ve removed the dependency on Entity Framework in classes that have nothing to do with data access. I still have a personal aversion to putting the attributes that define database schema in my domain classes and generally lean toward Entity Framework fluent API configurations for these tasks. However, in a small project, I find the data annotations to be convenient and quick to use.

Crossing Versions

The EF team has covered the possibility of your installing EF 4.3.x into a project that targets the .NET Framework 4.5. If you do this (whether intentionally or accidentally), a text file will be presented in the IDE that lists known issues with using EF 4.x in a .NET 4.5 project and recommends installing EF 5. Once EF 5 becomes stable and is the default package, the likelihood of developers making this mistake should disappear.

Switching to Enums, Yay!

With all of this in place I can modify my domain classes to get rid of the ugly workaround and use enums for the Rating and Experience properties. Here are the two new enums, and take note that I specified values for one but not the other so you can see how EF handles both scenarios:

public enum TweetRating
{
  Suxorz = 0,
  WorksForMe = 1,
  WatchOutAPlusK = 2
}
public enum TwitterExperience
{
  Newbie, BeenAround, Ninja
}

With the enums in place, I can modify the properties as follows:

[Column("ExperienceCode")]
public TwitterExperience Experience { get; set; }
[Column("RatingCode")]
public TweetRating Rating { get; set; }

Notice that I no longer need the attributes to specify the property range or length. More important, be aware that I’m making this change without regard for possible existing data in my demonstration database. If you want to make a change like this to an application that’s in production, you’ll need to prepare in advance for the data change. I’m completely altering the meaning of Experience in the database and I’ve also randomly changed the tweet rating range from 1-5 to 0-2.

After using Code First migrations to update the database, the Tweeter.ExperienceCode column has been changed from an nvarchar data type to an int. Both C# and Visual Basic will interpret the enum as an integer by default and will begin the enumeration with 0. Therefore, Code First will map the enum values to an int data type in the database. You can specify the enum to be a different type (within the bounds of C# and Visual Basic enums) and Code First will honor that. For example, defining an enum as long will result in properties that map to a bigint data type. But by default you’ll always get an integer starting with 0. In my example, in the database, Newbie will be represented by 0, BeenAround by 1 and Ninja by 2. If you think there’s any chance that in the future you might want to remove any of the enum members, reorder them or add new ones other than at the end, you should assign explicit values to them as I did in the TweetRating enum. That makes it easier to change the enum without changing any of those values accidentally. Don’t forget that the database will store only the numeric value, so if you do end up changing the value in the enum, that will effectively change the meaning of your data ... which is almost always, as C# guru Jon Skeet says, “a Bad Thing.”

Figure 5 shows code that creates a new Tweeter instance along with a Tweet, both using the enums. After saving this data, the database shows the value of the ExperienceCode equal to 1 and Rating equal to 2.

Figure 5 Creating a New Graph of a Tweeter and a Tweet

var alias = new Tweeter
  {
    Name = "Julie",
    UserName = "Julie",
    Bio = "Mom of Giantpuppy",
    CreateDate = DateTime.Now,
    Experience = TwitterExperience.BeenAround,
    Tweets = new List<Tweet>{new Tweet
               {
                 Content = "Oh how I love that Giantpuppy",
                 CreateDate = DateTime.Now,
                 Rating = TweetRating.WatchOutAPlusK
               }}
  };

You can use the enums in queries, and Entity Framework will take care of transforming the enum to the int value in the SQL and transforming the returned int values back to the enum values. For example, here’s a LINQ query that uses an enum in the Where predicate:

context.Tweeters.Where(t => t.Experience == 
  TwitterExperience.Ninja)

In the resulting T-SQL, the Where predicate value is 2.

Smoother Move to EF 5

I’m already hearing developers express an eagerness to port their existing Entity Framework solutions to EF 5 in order to benefit from the support for enums and spatial data. Getting those projects from EF 4 to EF 5 may not be rocket science, but there were enough bumps in the road that I found the transition a bit annoying the first few times. I hope this column makes it easier for you to make the move.

I like the fact that the single NuGet package for Code First and DbContext support provides compatible DLLs for both .NET 4 and .NET 4.5. Even if I’m using an EDMX, I still start all new projects with DbContext, and therefore 100 percent of my projects now rely on the Entity Framework NuGet package.

Remember that EF 4 apps running on computers with the .NET Framework 4.5 installed will benefit from the performance improvements, so even if you don’t get to move to Visual Studio 2012 quite yet, your users can still feel some of the love of the improvements to the Entity Framework core in the .NET Framework 4.5.


Julie Lerman is a Microsoft MVP, .NET mentor and consultant who lives in the hills of Vermont. You can find her presenting on data access and other Microsoft .NET topics at user groups and conferences around the world. She blogs at thedatafarm.com/blog and is the author of “Programming Entity Framework” (2010) as well as a Code First edition (2011) and a DbContext edition (2012), all from O’Reilly Media. Follow her on Twitter at twitter.com/julielerman.

Thanks to the following technical expert for reviewing this article: Arthur Vickers