EF6 vs EF Core - Key Differences

Overview

Entity Framework 6 (EF6) and Entity Framework Core (EF Core) are both ORMs from Microsoft, but they have significant differences in architecture, features, and capabilities.

Key Differences

FeatureEF6EF Core
Platform.NET Framework onlyCross-platform (.NET Core, .NET 5+)
PerformanceGoodBetter (optimized)
SizeLarger footprintLightweight
LINQ ProviderComplexSimplified, rewritten
Database ProvidersLimitedExtensible, many providers
Lazy LoadingEnabled by defaultOpt-in, requires proxy
GroupBy TranslationLimitedFull support
Batch OperationsNot supportedSupported
Global Query FiltersNot availableAvailable
Shadow PropertiesNot availableAvailable
Owned EntitiesComplex typesFirst-class support

Platform Support

EF6

// Windows only, .NET Framework
// Requires full .NET Framework
public class MyContext : DbContext
{
    // EF6 code
}

EF Core

// Cross-platform: Windows, Linux, macOS
// Works with .NET Core, .NET 5+, .NET Framework
public class MyContext : DbContext
{
    // EF Core code - runs anywhere
}

Performance Improvements

Query Performance

// EF Core generates more efficient SQL
var result = context.Products
    .Where(p => p.Price > 100)
    .OrderBy(p => p.Name)
    .Take(10)
    .ToList();

// EF Core: Better query translation and execution
// EF6: May generate less optimal SQL in complex scenarios

Batch Operations

// EF Core - Batch updates/deletes
context.Products
    .Where(p => p.IsDiscontinued)
    .ExecuteDelete();

context.Products
    .Where(p => p.CategoryId == 5)
    .ExecuteUpdate(p => p.SetProperty(x => x.Price, x => x.Price * 0.9m));

// EF6 - Not supported, requires manual implementation

Feature Comparison

1. Lazy Loading

EF6:

// Enabled by default
public class Blog
{
    public virtual ICollection<Post> Posts { get; set; }
}

var blog = context.Blogs.Find(1);
var posts = blog.Posts; // Automatically loaded

EF Core:

// Requires explicit configuration
services.AddDbContext<MyContext>(options =>
    options.UseLazyLoadingProxies());

public class Blog
{
    public virtual ICollection<Post> Posts { get; set; }
}

2. Global Query Filters

EF Core Only:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>()
        .HasQueryFilter(p => !p.IsDeleted);
}

// Automatically applied to all queries
var products = context.Products.ToList(); // Only non-deleted

3. Shadow Properties

EF Core Only:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>()
        .Property<DateTime>("LastModified");
}

// Access shadow properties
context.Entry(product).Property("LastModified").CurrentValue = DateTime.Now;

4. Owned Entities

EF6 (Complex Types):

[ComplexType]
public class Address
{
    public string Street { get; set; }
    public string City { get; set; }
}

EF Core (Owned Entities):

public class Customer
{
    public int Id { get; set; }
    public Address ShippingAddress { get; set; }
    public Address BillingAddress { get; set; }
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Customer>().OwnsOne(c => c.ShippingAddress);
    modelBuilder.Entity<Customer>().OwnsOne(c => c.BillingAddress);
}

Migration Differences

EF6

# Package Manager Console
Enable-Migrations
Add-Migration InitialCreate
Update-Database

EF Core

# .NET CLI
dotnet ef migrations add InitialCreate
dotnet ef database update

# Package Manager Console
Add-Migration InitialCreate
Update-Database

LINQ Query Translation

GroupBy Support

EF6:

// Limited GroupBy translation
var query = context.Orders
    .GroupBy(o => o.CustomerId)
    .Select(g => new { CustomerId = g.Key, Count = g.Count() });
// May not translate to SQL in complex scenarios

EF Core:

// Full GroupBy support
var query = context.Orders
    .GroupBy(o => o.CustomerId)
    .Select(g => new 
    { 
        CustomerId = g.Key, 
        Count = g.Count(),
        TotalAmount = g.Sum(o => o.Amount),
        AvgAmount = g.Average(o => o.Amount)
    });
// Translates to efficient SQL

Database Provider Ecosystem

EF6

  • SQL Server
  • MySQL (limited)
  • PostgreSQL (community)
  • Oracle (limited)

EF Core

  • SQL Server
  • PostgreSQL (Npgsql)
  • MySQL (Pomelo, Official)
  • SQLite
  • Cosmos DB
  • In-Memory
  • Oracle
  • Many community providers

Configuration API

EF6

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>()
        .HasKey(p => p.Id);
    
    modelBuilder.Entity<Product>()
        .Property(p => p.Name)
        .IsRequired()
        .HasMaxLength(100);
}

EF Core

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>(entity =>
    {
        entity.HasKey(p => p.Id);
        
        entity.Property(p => p.Name)
            .IsRequired()
            .HasMaxLength(100);
    });
}

When to Use Each

Use EF6 When:

  • Working with legacy .NET Framework applications
  • Need features not yet in EF Core (rare now)
  • Existing large codebase using EF6
  • Team expertise is in EF6

Use EF Core When:

  • Starting new projects
  • Need cross-platform support
  • Want better performance
  • Need modern features (global filters, owned entities)
  • Building microservices
  • Using .NET 5+ or .NET Core

Migration Path

From EF6 to EF Core

// 1. Update packages
// Remove: EntityFramework
// Add: Microsoft.EntityFrameworkCore.SqlServer

// 2. Update DbContext
// EF6
public class MyContext : DbContext
{
    public MyContext() : base("name=MyConnection") { }
}

// EF Core
public class MyContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder options)
    {
        options.UseSqlServer(connectionString);
    }
}

// 3. Update configurations
// EF6: DbModelBuilder
// EF Core: ModelBuilder

// 4. Handle breaking changes
// - Lazy loading configuration
// - Complex types → Owned entities
// - Update LINQ queries if needed

Performance Benchmarks

// Typical performance improvements in EF Core:
// - Query execution: 20-50% faster
// - SaveChanges: 10-30% faster
// - Memory usage: 30-40% lower
// - Startup time: 50-70% faster

// Example: Bulk insert
// EF6: ~1000 records/second
// EF Core: ~2000-3000 records/second

Feature Parity Status

Features in Both

  • Code First, Database First
  • Migrations
  • LINQ queries
  • Change tracking
  • Relationships (1:1, 1:N, N:N)
  • Inheritance (TPH, TPT)
  • Stored procedures
  • Raw SQL queries

EF Core Exclusive

  • Global query filters
  • Shadow properties
  • Owned entity types
  • Table splitting
  • Keyless entity types
  • Compiled queries
  • Batch operations
  • Better GroupBy support
  • Cosmos DB provider

EF6 Exclusive (Legacy)

  • Automatic migrations (removed in EF Core)
  • EDMX designer support
  • ObjectContext API

Interview Tips

  • Explain platform differences: EF6 is .NET Framework only, EF Core is cross-platform
  • Discuss performance: EF Core is generally faster and more efficient
  • Mention new features: Global filters, shadow properties, owned entities
  • Show migration knowledge: How to move from EF6 to EF Core
  • Explain use cases: When to choose each version
  • Discuss LINQ improvements: Better query translation in EF Core
  • Mention provider ecosystem: EF Core has more database providers

Summary

EF Core is the modern, cross-platform successor to EF6, offering better performance, smaller footprint, and new features like global query filters and owned entities. While EF6 remains supported for .NET Framework applications, EF Core is recommended for all new development and provides a clear migration path for existing applications.

Test Your Knowledge

Take a quick quiz to test your understanding of this topic.

Test Your Efcore Knowledge

Ready to put your skills to the test? Take our interactive Efcore quiz and get instant feedback on your answers.