With Entity Framework (EF) 6 being released recently (October 2013) there have been a couple of major changes in how the project is run and how it's served to the community.

Firstly, the EF code base has been fully extracted from the .NET Framework. Thereby enabling the EF team to work to a release schedule that's more appropriate to their product and enabling them to get fixes/updates to the community in a shorter time.

Secondly, the EF team have now moved to an open source development model (see entityframework.codeplex.com). Now we're able to have greater visibility on the project, and even contribute changes/updates to the code base (though this is strictly managed)!

Now I've gone over the more "physical" changes to EF, I'll list some of the new features included in the version 6 release:

Async Support

The async support included in the new version of EF uses the Await/Async pattern and extension methods around most of the query/command based operations. For example, SingleOrDefaultAsync, ToListAsync, CountAsync. With SaveChangesAsync being added to the DbContext class and FindAsync added to the DbSet class.

As an example I've created a basic console app. The following code is for a synchronous call to EF:

static void Main(string[] args)
{
    Console.WriteLine("Started: " + DateTime.Now.ToString("f"));

    // Create orders, save changes and then list the created orders
    var orders = CreateOrders();
    ListOrders(orders);

    Console.WriteLine("Ended: " + DateTime.Now.ToString("f"));
    Console.WriteLine("Press any key to exit....");
    Console.Read();
}

private static void ListOrders(List<Order> orders)
{
    foreach (var order in orders)
    {
        Console.WriteLine(String.Format("Order Id: {0} [{1}]", order.Id, order.TotalPrice));

        foreach (var product in order.Products)
        {
            Console.WriteLine(String.Format("Product: {0} - {1} - {2}", product.Id, product.Name, product.Price.ToString("$0.00")));
        }

        Console.WriteLine(String.Format("TOTAL PRICE: {0}", order.TotalPrice.ToString("$0.00")));

        Console.WriteLine("");
    }
}

private static List<Order> CreateOrders()
{
    using (var context = new TestDbContext())
    {
        // Create some products
        context.Products.Add(new Product { Name = "Apple", Price = 12.30M });
        context.Products.Add(new Product { Name = "Orange", Price = 3.89M });
        context.Products.Add(new Product { Name = "Pear", Price = 5.2M });
        context.Products.Add(new Product { Name = "Strawberry", Price = 1.50M });
        context.Products.Add(new Product { Name = "Cherry", Price = 31.99M });

        // Create some orders
        context.Orders.Add(new Order
        {
            Created = DateTime.Now,
            Products = context.Products.Where(i => (new List<int> { 1, 2, 3 }).Contains(i.Id)).ToList()
        });

        context.Orders.Add(new Order
        {
            Created = DateTime.Now,
            Products = context.Products.Where(i => (new List<int> { 3, 4, 5 }).Contains(i.Id)).ToList()
        });

        context.SaveChanges();

        return context.Orders.Include("Products").ToList();
    }
}

As you can see the above code creates some objects, saves the changes to a local SQL Server DB and then returns the list of created orders (with associated orders).

To make this asyncronous we make the following changes. First, we add the async/await keywords to the call to ListOrders:

private static async Task<List<Order>> CreateOrders()
{
    using (var context = new TestDbContext())
    {
        // Create some products
        ...

        // Create some orders
        ...

        await context.SaveChangesAsync();

        return context.Orders.Include("Products").ToList();
    }
}

Then we change how we display the list of orders in the main method:

static void Main(string[] args)
{
    Console.WriteLine("Started: " + DateTime.Now.ToString("f"));

    var orders = CreateOrders();

    // Wait for CreateOrders to complete then call ListOrders.
    orders.ContinueWith(i => ListOrders(i.Result));

    Console.WriteLine("Ended: " + DateTime.Now.ToString("f"));
    Console.WriteLine("Press any key to exit....");
    Console.Read();
}

Custom Code Conventions

Custom code conventions allow you to define your own configuration conventions within your EF model.

For example, suppose you have a convention that every database table has a field named "Id", and that this field is always the primary key on the table? Previously, we had to add a convention for each entity. Now we could make a change as follows:

modelBuilder.Properties<int>()
    .Where(p => p.Name == "Id")
    .Configure(p => p.IsKey());

Connection Resiliency

All applications that connect to a database can be susceptible to connection breaks due to back-end or network failures. Though this isn't a serious problem when working in a LAN-based environment because these failures are very rare. However, with the advent of cloud computing and cloud based databases (such as Windows Azure SQL Database) and connections over less reliable networks we're now at a greater risk of connection issues.

Connection resiliency attempts to fix this potential issue by providing the ability for EF to automatically retry commands that fail due to connection issues.

Connection resiliency is implemented in EF using an implementation of the IDbExecutionStrategy interface. The available impementations of this include:

  • SqlAzureExecutionStrategy
  • DefaultExecutionStrategy
  • DefaultSqlExecutionStrategy

Each execution strategy implementation is configured to operate appropriately for the desired environment. For example, the SqlAzureExecutionStrategy will retry on exceptions that are transient (e.g. connection failures).

Execution strategy implementations can be enabled using the SetExecutionStrategy of the DbConfiguration class.

AddRange and RemoveRange

The AddRange and RemoveRange methods are included in EF6 to improve the performance of adding or removing collections of entities. The performance increase is achieved through EF only calling DetectChanges once for each AddRange or RemoveRange operation, instead of after every call to the Add or Remove method as in previous version of EF.

Interception

This new feature allows us to intercept queries and commands , so that we can see the generated SQL that's about to be passed to a database and the results that have been returned.

Interception is available through the DbConfiguration class and can be enabled as follows:

public class TestDbConfiguration : DbConfiguration
{
    public TestDbConfiguration()
    {
        DbInterception.Add(new TestDbContextInterceptorLogging());
    }
}

In the above example, I created a logging interceptor to output the SQL generated for each EF call.


For more information please refer to the new home of EF (entityframework.codeplex.com/). There's also a great article by Julie Lerman that I highly recommend (msdn.microsoft.com/en-us/magazine/dn532202.aspx).