static void

Entity Framework Code First Optimization

Optimizations for EF Code First, especially at startup.

NGen

EF 6+ is released by Nuget, and so not NGened. Optimizing the 5Mb dll is an easy fix (run as Admin, this is 64bit).

%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen install EntityFramework.dll

No Migrations / Hard-code ManifestToken

The migrations code is easy in development, but startup will be slow in production. See Rowan Miller on the CF database calls. As he explains, the database version is generally know too, so you can eliminate all the calls with this DbConfiguration:

using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.SqlClient;
 
namespace Data
{
    /// <summary>
    /// DbConfiguration
    /// </summary>
    public class CustomConfiguration : DbConfiguration
    {
        public CustomConfiguration()
        {
            SetDatabaseInitializer<CustomContext>(null);
            SetManifestTokenResolver(new CustomManifestTokenResolver());
        }
 
        internal class CustomManifestTokenResolver : IManifestTokenResolver
        {
            private readonly IManifestTokenResolver _defaultResolver = new DefaultManifestTokenResolver();
 
            public string ResolveManifestToken(DbConnection connection)
            {
                var sqlConn = connection as SqlConnection;
                //for SQLServer, 2008 or 2012
                return sqlConn != null ? "2012" : _defaultResolver.ResolveManifestToken(connection);
            }
        }
    }
}

If the DbConfiguration is not in the same assembly as the DbContext, add
<entityFramework codeConfigurationType="Data.CustomConfiguration, Data">
or...

[DbConfigurationType(typeof(CustomConfiguration))]
public class CustomContext : DbContext

Transient SQL errors

In EF 6.1, this only exists for Azure errors in the DbConfiguration:

SetExecutionStrategy("System.Data.SqlClient", () => new System.Data.Entity.SqlServer.SqlAzureExecutionStrategy());

There is no in-the-box support for non-Azure errors (like deadlocks).

Lazy loading

Can be good or bad...

Project queries (use DTOs)

dbSet.AsNoTracking() creates entities without change tracking (or context.dbSet.MergeOption = MergeOption.NoTracking; )

Otherwise, consider using query projection into a DTO (with Linq .Select). Don't load what you don't need.

For maximum efficiency, use rawSql, via the DbContext.Database or Dapper:

var products = context.Database.SqlQuery<Product>(
    "select * from Products where Price>@p0", 2);

EntityFramework.Extended

The nuget package EntityFramework.Extended (github) includes batch updates and deletes, .Future() and .FromCache() (uses memory cache or provider).

Multi-tenant DbContext

Generally simpler, smaller models are much more efficient. If you don't use migrations (use a Database null initializer) you can have true multi-tenant DbContexts. Since EF 6.1, we can have multiple DbContexts per database. In the migration configuration, there is a ContextKey which is by default the FQN of the DbContext.

Then when creating the migration specify which you are using.

enable-migrations -contextTypeName:OrderContext -MigrationsDirectory:OrderMigrations
enable-migrations -contextTypeName:productContext -MigrationsDirectory:ProductMigrations
add-migration -configuration:Data.OrderMigrations.Configuration "Initial"
add-migration -configuration:Data.ProductMigrations.Configuration "Initial"
update-database -configuration:Data.OrderMigrations.Configuration

Other