Skip to content

EF Core 是什么 ​

Entity Framework Core 是 .NET 平台的现代化对象关系映射(ORM)框架

📖 核心概念 ​

什么是 ORM? ​

ORM(Object-Relational Mapping) 是一种编程技术,用于在面向对象编程语言和关系数据库之间建立映射关系。它允许开发者:

  • 使用面向对象的方式操作数据库
  • 无需编写大量 SQL 代码
  • 自动处理数据类型转换
  • 提供数据库抽象层
┌─────────────────────────────────────┐
│     应用程序(C# 对象)              │
│                                     │
│  var user = new User                │
│  {                                  │
│      Name = "张三",                 │
│      Email = "zhang@example.com"    │
│  };                                 │
└──────────────┬──────────────────────┘
               │ ORM 自动映射
               ▼
┌─────────────────────────────────────┐
│     数据库(关系表)                  │
│                                     │
│  INSERT INTO Users                  │
│  (Name, Email)                      │
│  VALUES ('张三', 'zhang@...')       │
└─────────────────────────────────────┘

EF Core 的定义 ​

Entity Framework Core 是微软开发的轻量级、可扩展、开源的 ORM 框架,具有以下特点:

✅ 跨平台:支持 Windows、Linux、macOS
✅ 多数据库:SQL Server、PostgreSQL、MySQL、SQLite、Cosmos DB 等
✅ LINQ 支持:使用强类型 LINQ 查询
✅ 变更跟踪:自动检测实体状态变化
✅ 迁移系统:代码优先的数据库版本控制
✅ 异步编程:完整的 async/await 支持


🏗️ 架构定位 ​

EF Core 在技术栈中的位置 ​

┌──────────────────────────────────────┐
│      表现层(ASP.NET Core MVC)      │
└──────────────┬───────────────────────┘
               │
┌──────────────▼───────────────────────┐
│      业务逻辑层(Services)           │
└──────────────┬───────────────────────┘
               │
┌──────────────▼───────────────────────┐
│   数据访问层(EF Core + DbContext)   │  ← EF Core 的位置
└──────────────┬───────────────────────┘
               │
┌──────────────▼───────────────────────┐
│      数据库(SQL Server 等)          │
└──────────────────────────────────────┘

与传统 ADO.NET 对比 ​

特性ADO.NETEF Core
抽象级别低级(直接操作 SQL)高级(面向对象)
开发效率低(手写 SQL)高(LINQ 查询)
性能最优(无开销)良好(有少量开销)
类型安全弱(字符串拼接)强(编译时检查)
数据库移植性差(SQL 方言)好(自动适配)
学习曲线陡峭平缓

示例对比:

csharp
// ❌ ADO.NET:繁琐且容易出错
using (var connection = new SqlConnection(connectionString))
{
    await connection.OpenAsync();
    using (var command = new SqlCommand(
        "SELECT Id, Name, Email FROM Users WHERE Age > @age", connection))
    {
        command.Parameters.AddWithValue("@age", 18);
        using (var reader = await command.ExecuteReaderAsync())
        {
            var users = new List<User>();
            while (await reader.ReadAsync())
            {
                users.Add(new User
                {
                    Id = reader.GetInt32(0),
                    Name = reader.GetString(1),
                    Email = reader.GetString(2)
                });
            }
            return users;
        }
    }
}

// ✅ EF Core:简洁且类型安全
var users = await context.Users
    .Where(u => u.Age > 18)
    .Select(u => new { u.Id, u.Name, u.Email })
    .ToListAsync();

🎯 适用场景 ​

✅ 适合使用 EF Core 的场景 ​

  1. 企业级应用

    • ERP 系统
    • CRM 系统
    • OA 办公系统
  2. Web 应用

    • ASP.NET Core Web API
    • Blazor 应用
    • MVC/Razor Pages
  3. 快速原型开发

    • MVP 产品
    • 创业项目
    • 内部工具
  4. 复杂业务逻辑

    • 需要事务支持
    • 复杂的领域模型
    • DDD 架构

⚠️ 谨慎使用 EF Core 的场景 ​

  1. 高性能要求

    • 高频交易系统
    • 实时数据处理
    • 游戏服务器
  2. 简单 CRUD

    • 小型工具应用
    • 一次性脚本
  3. 非关系型数据

    • 文档数据库
    • 键值存储
    • 图数据库

💡 混合方案 ​

在实际项目中,可以结合使用:

csharp
// 大部分操作使用 EF Core
var orders = await context.Orders
    .Include(o => o.Items)
    .Where(o => o.CustomerId == customerId)
    .ToListAsync();

// 高性能要求的使用原生 SQL
var result = await context.Database
    .SqlQueryRaw<OrderSummary>(
        "EXEC GetOrderSummary @CustomerId", 
        new SqlParameter("@CustomerId", customerId))
    .ToListAsync();

🔑 核心组件 ​

1. DbContext ​

DbContext 是 EF Core 的核心类,表示与数据库的会话。

csharp
public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) 
        : base(options) { }

    // DbSet 表示数据库中的表
    public DbSet<Product> Products => Set<Product>();
    public DbSet<Category> Categories => Set<Category>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // 配置实体映射
        modelBuilder.Entity<Product>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.Name).HasMaxLength(100);
        });
    }
}

职责:

  • 管理数据库连接
  • 跟踪实体状态
  • 生成并执行 SQL
  • 处理事务

2. DbSet<T> ​

DbSet<T> 表示数据库中某个实体类型的集合(对应一张表)。

csharp
// 查询
var products = await context.Products.ToListAsync();

// 添加
context.Products.Add(newProduct);
await context.SaveChangesAsync();

// 更新
product.Price = 99.99m;
await context.SaveChangesAsync();

// 删除
context.Products.Remove(product);
await context.SaveChangesAsync();

3. 实体(Entity) ​

实体是映射到数据库表的 C# 类。

csharp
public class Product
{
    public int Id { get; set; }              // 主键
    public string Name { get; set; }         // 产品名称
    public decimal Price { get; set; }       // 价格
    public int CategoryId { get; set; }      // 外键
    
    // 导航属性
    public Category Category { get; set; }
}

4. LINQ 查询提供器 ​

将 LINQ 表达式翻译为 SQL 查询。

csharp
// C# LINQ
var expensiveProducts = await context.Products
    .Where(p => p.Price > 100)
    .OrderByDescending(p => p.Price)
    .Take(10)
    .ToListAsync();

// 翻译为 SQL
// SELECT TOP 10 * FROM Products 
// WHERE Price > 100 
// ORDER BY Price DESC

🌟 主要优势 ​

1. 提高开发效率 ​

  • 减少样板代码:无需手写 CRUD SQL
  • 智能提示:IDE 提供完整的 IntelliSense
  • 编译时检查:早发现错误
csharp
// 编译时就能发现错误
var users = await context.Users
    .Where(u => u.Age > 18)  // 如果 Age 不存在,编译失败
    .ToListAsync();

2. 数据库无关性 ​

轻松切换数据库提供程序:

csharp
// SQL Server
options.UseSqlServer(connectionString);

// PostgreSQL
options.UseNpgsql(connectionString);

// MySQL
options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));

// SQLite
options.UseSqlite(connectionString);

3. 强大的迁移系统 ​

bash
# 代码变更自动生成迁移
dotnet ef migrations add AddUserEmail

# 一键应用迁移
dotnet ef database update

4. 内置性能优化 ​

  • 变更跟踪:只更新修改的字段
  • 延迟加载:按需加载关联数据
  • 缓存机制:复用查询计划

⚠️ 注意事项 ​

1. 学习曲线 ​

虽然比传统 ADO.NET 简单,但仍需掌握:

  • LINQ 语法
  • 实体关系映射
  • 性能优化技巧
  • 迁移管理

2. 性能开销 ​

EF Core 引入了一些开销:

  • 对象映射
  • 变更跟踪
  • SQL 生成

解决方案:

  • 使用 AsNoTracking() 进行只读查询
  • 避免 N+1 查询问题
  • 合理使用索引

3. 复杂查询限制 ​

某些复杂 SQL 难以用 LINQ 表达:

  • 递归查询
  • 窗口函数
  • 复杂的子查询

解决方案:使用原始 SQL

csharp
var result = await context.Database
    .SqlQueryRaw<MyDto>("EXEC ComplexProcedure @param", param)
    .ToListAsync();

📊 EF Core vs EF 6 对比 ​

特性EF CoreEF 6
平台跨平台仅 Windows
性能更优一般
新功能持续更新维护模式
数据库支持多种数据库主要 SQL Server
批量操作✅ 原生支持❌ 需第三方库
JSON 列✅ 支持❌ 不支持
推荐度⭐⭐⭐⭐⭐⭐⭐

建议:新项目一律使用 EF Core,旧项目考虑迁移。


🚀 快速体验 ​

5 分钟上手示例 ​

1. 创建项目 ​

bash
dotnet new console -n EfCoreDemo
cd EfCoreDemo
dotnet add package Microsoft.EntityFrameworkCore.SqlServer

2. 定义实体 ​

csharp
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

3. 创建 DbContext ​

csharp
public class AppDbContext : DbContext
{
    public DbSet<Product> Products => Set<Product>();

    protected override void OnConfiguring(DbContextOptionsBuilder options)
    {
        options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=DemoDb");
    }
}

4. 使用 ​

csharp
using var context = new AppDbContext();

// 创建数据库
await context.Database.EnsureCreatedAsync();

// 添加数据
context.Products.Add(new Product { Name = "Laptop", Price = 999.99m });
await context.SaveChangesAsync();

// 查询数据
var products = await context.Products.ToListAsync();
foreach (var product in products)
{
    Console.WriteLine($"{product.Name}: ${product.Price}");
}

📚 延伸阅读 ​


💡 小结 ​

EF Core 是什么?

  • 现代化的 .NET ORM 框架
  • 跨平台、高性能、易扩展

为什么要学 EF Core?

  • 提高开发效率 50%+
  • 企业级项目的标准选择
  • .NET 生态的核心技能

下一步做什么?

  1. 完成 快速入门 章节
  2. 构建第一个完整项目
  3. 深入理解 核心概念

提示:理论只是开始,动手实践才是关键!

基于 MIT 许可发布