January 2015
Volume 30 Number 1
Data Points - Looking Ahead to Entity Framework 7
By Julie Lerman | January 2015
Development of the next version of Entity Framework is well underway. I got my first glimpse of what the EF team was working on at TechEd North America 2014, when Program Manager Rowan Miller talked about the goals for Entity Framework 7 (EF7) and demonstrated some very early bits.
That was five months ago as I’m writing this column, and although EF7 is still an early alpha, it has already come a long way. In this column I want to make you aware of what EF7 will bring to developers, the motivations behind decisions being made about EF7, and what this version means to existing apps that use EF6 or earlier. I’ll also give you a peek at what some of the code will look like.
Open Source, but Now on GitHub
The first thing to know about EF7 is that, like EF6, it’s open source. But rather than being developed on CodePlex, EF7 is on GitHub, along with the rest of the upcoming version of ASP.NET. The URL for EF7 development is github.com/aspnet/EntityFramework. As with EF6, you’ll be able to see the details of EF7 as it evolves. You can explore the source, as well as its progress through branches and commits, follow the discussions, raise issues, fork the source, and submit pull requests for the team to examine and potentially commit to the code base.
EF6 Is Not Going Away Any Time Soon
Don’t worry—you won’t be forced to move to EF7. Think back to ADO.NET DataSets and DataReaders. Much like ASP.NET Web Forms, which are still supported and even benefiting from occasional tweaks, ADO.NET is still part of the Microsoft .NET Framework, even though EF has been the primary data access technology for .NET for many years. Not much has happened to enhance those technologies, but they’re still there, and still supporting a lot of legacy code (mine included). One of the big advantages EF6 has over those other technologies is that it’s open source, so even though the team at Microsoft won’t be making big investments in EF6, the community will still be able to. And the EF team is committed to EF6. They will continue to make tweaks, closely inspect pull requests and update EF6. Even though they’ve been going full-bore on EF7 for a good part of 2014, EF6 was updated. Version 6.1.0 was released in February 2014; 6.1.1 in June 2014; and as I’m writing this article, 6.1.2 is in beta, to be released soon. I was originally concerned, but am no longer worried, about being able to keep older apps going. The only ones I worry about are the earliest apps that used EF with the .NET Framework 3.5, ObjectContext and more. But if you haven’t updated those apps to leverage all of the great improvements to EF over the years, you may not be worrying too much about EF7, anyway. You can also find all of the earlier packages for EF on NuGet, all the way back to EF 4.1.10311.
EF7: The Short List
Here’s the high-level view of what’s exciting in EF7:
- Support for non-relational data stores and even in-memory data for testing.
- Support for machines and devices that don’t use the full .NET Framework. This means you can use EF7 in Windows Phone and Windows Store apps, as well as on Linux and Macintosh machines that are running Mono.
- Support for many features that developers have requested but couldn’t be achieved with the existing code base.
- Continued support for applications that use the full .NET Framework such as Windows Presentation Foundation and other client applications.
- EF7 will be distributed in the same manner as ASP.NET 5 and can be used with ASP.NET 5 apps.
Familiar Coding Surface, New Code Base
Each version of EF has evolved the framework, adding new capabilities and fine-tuning performance and APIs. As I’ve written about before in this column, as well as in an overview article in the December 2013 issue, “Entity Framework 6: The Ninja Edition” (bit.ly/1cwjyCD), the latest version brought EF to a new level, giving the framework many of the features users have been asking for along the way, such as asynchronous database execution, tapping into the query pipeline, customizing Code First conventions and so much more. I drill much further into these features in my Pluralsight course, “Entity Framework 6, Ninja Edition: What’s New in EF6” (bit.ly/PS-EF6).
There were even more features developers sought for EF that Microsoft was eager to implement, but the 10-plus-year-old code base EF is built on—with a continued dependency on ObjectContext and less flexible coding patterns—prevented the team from getting to this next level of capabilities. A difficult decision—which surely many of you have faced with your own legacy software—was made to rebuild Entity Framework from scratch.
EF7 isn’t creating a new framework for data access. Instead, it’s building a new, more sustainable base on which to support not only the features and workflow you’ve depended on for years with EF, but also one that will enable so much more. The team struggled with whether this should be the next EF or a new data access technology. At one point, I even questioned whether it would be “EF Light.” But the core functionality of EF is still there and after a lot of consideration, I agree it makes sense to think of this as the next version of Entity Framework. You can read more about this in the team’s blog post, “EF7 – v1 or v7?” (bit.ly/1EFEdRH).
Shedding Some Legacy Weight, Keeping the Good Parts
Yet there’s also news about EF7 that’s worrisome for some developers. While the most common EF classes, patterns and workflows will remain intact, some of the lesser-used members will be left behind. But please don’t panic; I’ll talk more about this in a bit.
Enabling developers to continue using familiar patterns and even be able to port good amounts of existing code to EF7 was a critical goal. You’ll still use DbContext, DbSet, LINQ queries, SaveChanges and many of the means of interaction that have been part of EF for a long time.
Here’s a DbContext class I defined in EF7:
public class BreweryContext : DbContext {
public DbSet<Brewery> Breweries { get; set; }
public DbSet<Beer> Beers { get; set; }
}
And here’s a simple update in EF7 that’s the same as in EF6. I’m using a synchronous save, but all of the async methods are there, as well:
public void StoreBeers(List<Beer> beers) {
using (var context = new BreweryContext()) {
context.Beers.AddRange(beers);
context.SaveChanges();
}
}
And a simple query:
using (var context = new BreweryContext()) {
return context.Breweries.Where(b=>b.Location.Contains("Vermont"));
}
I’m using the version of EF7 that’s in the packages with version beta2-11616. EF7 isn’t really beta at this time, but the “beta2” is related to a NuGet package-naming decision. By the time this article is published, EF7 will have evolved further, so please consider this a look, not a promise.
I still have a DbContext and define DbSets, just as I’ve always done. OnModelCreating is still there, although I’m not using it here.
EF4.1 introduced the DbContext API, which was much more focused on typical EF usage. Underneath, it still relied on the original ObjectContext that provides database interaction, manages transactions and tracks the state of objects. Since then, DbContext has become the default class to use and you’d dip down to the lower-level APIs if you wanted to do a rare interaction with the ObjectContext. EF7 will shed the obese ObjectContext; only the DbContext will remain. But some of those tasks you’ve relied on the ObjectContext for will still be accessible.
Some of the very complicated mappings that are difficult to support and not commonly used will go away with EF7. The aforementioned blog post says, “For example, you could have an inheritance hierarchy that combined TPH, TPT and TPC mappings, as well as Entity Splitting, all in the same hierarchy.” If you’ve ever attempted to work directly with the MetadataWorkspace API and run away screaming, you know it’s an intricate and complex beast, useful for being able to support this kind of flexibility. But that complexity has prevented the team from being able to support other scenarios for which users have asked. By simplifying the mapping possibilities, the MetadataWorkspace API also became simpler and much more flexible. You can easily get to metadata about your model schema from the DbContext API in EF7, which gives you a low-level capability to perform advanced techniques without having to have the low-level ObjectContext at your disposal.
Dropping EDMX, but Database First Will Continue
Entity Framework currently has two ways to describe a model. One uses an EDMX in the designer; the other involves the classes, a DbContext and mappings that are used by the Code First APIs. If you’re using the EDMX and designer, at run time EF creates an in-memory model from the XML behind the EDMX. If you choose the Code First path, EF creates the same in-memory model by reading the classes, DbContext and mappings you provided. From that point on, EF works the same, regardless of how you describe your model. Note that with the EDMX/Designer workflow, you also get POCO classes and a DbContext to work with in your code. But because the EDMX is there, they aren’t used to create that in-memory model. This is important to understand as you read the next sentences: EF7 will not support the designer-based EDMX model. It will not have the ability to read the EDMX XML at run time to create the in-memory model. It will use only the Code First workflow.
When the team blogged about this, it caused panic among developers. Partly this was due to the fact that many still don’t realize you can reverse-engineer a database to POCO classes, DbContext and mappings. In other words, you can start with a database to get a Code First model. This has been possible since the EF Power Tools Beta was first released in early 2011. It’s supported by the EF6.1 designer and it will definitely be supported for EF7. I’ve said many times that the “Code First” moniker is a little confusing and misleading. It was originally called “Code Only,” but the name was changed to “Code First” to make a nice match with “Database First” and “Model First.”
So you don’t need the designer or an EDMX to start with an existing database.
But what if you have existing EDMX models and don’t want to lose the ability to use a designer? There are third-party designers that support Entity Framework, such as the LLBLGen Pro Designer, which already supports EF Code First (bit.ly/11OLlN2), and the Devart Entity Developer (bit.ly/1yHWbB2). Look for those tools and possibly others to potentially provide designer support for EF7.
There is yet another path to keep in mind: sticking with EF6!
Smaller Footprint, More Devices and OSes
Additionally, Microsoft strove to streamline the distribution of the EF APIs. The NuGet package folder for EF6.1.1 is about 22MB. This includes a 5.5MB assembly for the .NET Framework 4.5 and another in case you’re using .NET Framework 4. With EF7, there are a number of smaller DLLs. You’ll combine only the DLLs necessary to support your workflow. For example, if you’re targeting SQL Server, you’d use a core EntityFramework.dll, a DLL for SQL Server and another with APIs common to relational data stores. If you want to use migrations, that’s a separate assembly you can skip. Otherwise, you may want to create and execute migrations from the Package Manager Console. There’s an API for commands. Using the NuGet package manager, the proper packages will be identified and downloaded via their dependencies, so you won’t have to worry too much about the details.
What this does is minimize the EF7 footprint on the end user’s computer or device, which is especially important on devices. ASP.NET is going this route, as well. Both of these technologies are dropping their reliance on the full .NET Framework. Instead, they’ll distribute only the DLLs necessary for accomplishing the tasks of a given application. This means the already-streamlined version of .NET used by Windows Phone and Windows Store apps will be able to use EF7.
It also means that OSes like OS X and Linux that use Mono rather than the full .NET Framework will also be able to support client-side Entity Framework.
Beyond Relational
When Entity Framework was first introduced, Microsoft had a vision of it being used for a variety of data stores, though the first pass focused on relational databases. Non-relational databases existed at that time, but were not widely used, unlike the NoSQL databases—especially document databases—that are so popular today.
While EF is an Object Relational Mapper (ORM), developers who use it want to be able to use the same constructs to interact with non-relational databases. EF7 will provide a high level of support for this, but keep in mind what high level really means. There are vast differences between relational databases and non-relational databases and EF will not make any attempt to mask those differences. But for basic querying and updates, you’ll be able to use the patterns with which you’re already familiar.
Figure 1 shows code from a sample app that targets Microsoft Azure Table Storage, which is a non-relational document database. The sample comes from EF Program Manager Rowan Miller at github.com/rowanmiller/Demo-EF7. Note that the sample runs against the 11514 version of the EF7 alpha nightly builds.
Figure 1 A DbContext Defined for Working with Azure Table Storage
public class WarrantyContext : DbContext
{
public DbSet<WarrantyInfo> Warranties { get; set; }
protected override void OnConfiguring(DbContextOptions options) {
var connection =
ConfigurationManager.ConnectionStrings["WarrantyConnection"]
.ConnectionString;
options.UseAzureTableStorage(connection);
}
protected override void OnModelCreating(ModelBuilder builder) {
builder.Entity<WarrantyInfo>()
.ForAzureTableStorage()
.PartitionAndRowKey(w => w.BikeModelNo, w => w.BikeSerialNo);
}
}
The OnConfiguring method is new. It’s a way to affect how EF configures the DbContext at run time, somewhat like you can do today with the DbConfiguration class. Notice the builder.UseAzureTableStorage extension method, which exists because I’ve also installed the EntityFramework.AzureTableStorage package into my project.
EF7 uses this pattern for its various providers. Here’s an OnConfiguring method in a DbContext class within a project that targets SQLite:
protected override void OnConfiguring(DbContextOptions builder) {
string dir = ApplicationData.Current.LocalFolder.Path;
string connection = "Filename=" + Path.Combine(dir, "VermontBrewery.db");
builder.UseSQLite(connection);
}
This project has the EntityFramework.SQLite package installed, so now I have the UseSQLite extension method instead.
Back in the WarrantyContext class in Figure 1, you can see the familiar OnModelCreating override for DbContext and in there I’m doing some special mapping. Again, I have methods provided by the EntityFramework.AzureTableStorage NuGet package. I get to pick and choose the packages I want based on the features I need. Azure Table Storage relies on a key-value pair for unique identity and to support table partitioning. In order to retrieve or store data, it’s critical to know what values are to be used for the PartitionKey and the RowKey, so the API provides a method—PartitionAndRowKey—that allows you to map the properties to the appropriate keys. The concept is no different from how you’ve been able to use the fluent API or Data Annotations to specify the property that maps to a relational database’s primary key.
Thanks to this mapping, I can write a familiar LINQ query to retrieve some data:
var warranty = _context.Warranties
.Where(w =>
w.BikeModelNo == modelNo
&& w.BikeSerialNo == serialNo)
.SingleOrDefault();
So you’re seeing a typical LINQ query, but it’s being executed against the Azure Table Storage data store, just as you can do with a relational database today.
This same demo also updates warranty objects; creates and inserts new ones using DbSet.Add; and uses DbContext.SaveChanges to persist everything back to the data store, just as it’s done today with EF6—and has been done throughout the history of EF.
Also interesting to consider is how Entity Framework has always supported a set of canonical features for mapping to relational databases, but left it up to the database providers to specify how those would translate to the database they target. EF7 will have a high-level set of canonical features that can be understood by relational and non-relational data stores. There’s also a lower-level set of features that focus on relational databases, and they’re encapsulated in the EntityFramework.Relational assembly. All of the relational database providers will depend on those and, just like today, their specific handling of database interaction will be housed in their own provider APIs, like the EntityFramework.SQLite I used earlier. You’ll find extension methods in the providers that spin off of an AsRelational method, which is in the Relational API. It’s an extension method of DbContext.
There’s even an in-memory data store provider, which is for unit testing when you want to avoid a database interaction that might be involved in the logic you’re testing. Typically in these scenarios you use fakes or mocking frameworks to impersonate the database interaction.
If you were setting up a test to perform a query or update the database, you’d have some code to instantiate the database, such as:
using (var context = new BreweryContext()) {
// Perform some action against the context
}
You can easily switch to an in-memory store by first installing the entityframework.InMemory package to your test project, defining a DbContextOption for InMemoryStore and then specifying that the context should use that option. Again, this is possible thanks to extension methods provided by this API:
var options = new DbContextOptions().UseInMemoryStore();
using (var context = new BreweryContext(options)){
// Perform some action against the context
}
More Features, More Capabilities, Much More Flexible
You can already see the benefits of the new code base in the flexibility the extension methods provide, and in the ability to affect the Entity Framework pipeline with the OnConfiguring overload. There are extensibility points throughout the new code base, not only for changing EF7, but also for making it simpler for you to plug in your own logic to EF7.
The new core code base gives the EF team a chance to solve some age-old problems. For example, the version I’m using already has support for batch updating, which is the default for relational databases. I’ve played with code that allows me to use my own methods inline in LINQ queries without receiving the dreaded “Entity Framework cannot translate this method into SQL.” Instead, EF and the providers are able to parse out which part of the query will become SQL and which will get run locally on the client. I’m sure there will be protection from and guidance for avoiding some potential performance issues for that particular feature.
The team was able to add the long-requested Unique Foreign Keys capability for models. They’re also looking closely at providing support for table-valued functions and cleaner ways to handle disconnected data, which is something I’ve focused on for many years with Entity Framework. It’s a common problem with disconnected applications—not just when Entity Framework is involved—and it’s not easy to create algorithms that will work consistently in every scenario. So a new approach is needed, for sure.
There’s a lot more to get excited about with EF7. I highly recommend a close look at the posts on the ADO.NET Team Blog at blogs.msdn.com/adonet. In addition to the post I linked to earlier, Rowan Miller wrote in-depth about the decision to drop designer support in EF7; see “EF7 - What Does ‘Code First Only’ Really Mean” at bit.ly/1sLM3Ur. Keep an eye on that blog, as well as the GitHub project. The wiki on GitHub (bit.ly/1viwqXu) has links to how to access the nightly builds; how to download, compile and debug the source code; some walk-throughs and the design meeting notes. The team is eager for your feedback and is excited to receive pull requests.
A Decision Not Taken Lightly
It’s important to me to write about EF7 to help allay some fears about such a big change and that some of the existing EF features that might be integral to your applications will not make it into EF7. These fears are not unfounded and the team is not taking them lightly, nor am I. But understanding that EF6 will not go away and will continue to evolve with contributions from the community is critical. If you want to take advantage of the forward movement, you’ll have some tough choices to make. Upgrading big applications will not be easy and you should weigh the options carefully. Perhaps you can break up your application, rewriting only some portions to benefit from EF7.
Again, as I’m writing this column, EF7 is still in its early stages, and I’m not sure how far along it will be by the time you read this. But the current available source and NuGet packages are there to explore, experiment with and provide feedback. Bear in mind that the team may not always keep all of the provider APIs (such as Redis, SQLite and others) up-to-date as they evolve the core API. According to the post at bit.ly/1ykagF0, “EF7 - Priorities, Focus and Initial Release,” the first release of EF7 will focus on compatibility with ASP.NET 5. Subsequent releases will add more features. Still, even though EF7 is not yet stable enough to begin building applications with, there’s definitely enough there to let you start planning ahead.
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.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 and see her Pluralsight courses at juliel.me/PS-Videos.
Thanks to the following Microsoft technical expert for reviewing this article: Rowan Miller
This is based on an alpha version of Entity Framework 7. All information is subject to change.