Entity Framework (EF) 深度解析

在这里插入图片描述


在这里插入图片描述

第一部分:Entity Framework 基础概念与架构

1.1 Entity Framework 简介

Entity Framework (EF) 是微软为.NET应用程序开发提供的一个开源对象关系映射(O/RM)框架。作为ADO.NET的增强版本,它使开发人员能够以面向对象的方式处理数据,而无需过多关注底层数据库结构。

1.1.1 EF的发展历程
  • EF 3.5 (2008年): 首个版本,随.NET Framework 3.5 SP1发布
  • EF 4.0 (2010年): 引入模型优先开发、延迟加载等关键功能
  • EF 4.1 (2011年): 推出DbContext API和Code First方法
  • EF 5.0 (2012年): 性能优化,支持枚举类型
  • EF 6.x (2013-2015): 独立发展,增加异步操作、拦截器等
  • EF Core 1.0 (2016年): 完全重写,跨平台支持
  • EF Core 最新版本: 持续演进,功能不断增强
1.1.2 EF的核心价值
  1. 提高开发效率:减少约30-40%的数据访问层代码量
  2. 降低技术门槛:无需精通SQL即可实现复杂数据操作
  3. 增强可维护性:强类型模型减少运行时错误
  4. 数据库无关性:支持多种数据库系统迁移

1.2 EF架构设计

1.2.1 整体架构分层
[应用程序层]
    |
[LINQ查询]
    |
[Entity Framework]
    |       |
[概念模型]  [存储模型]
    |       |
[映射层]
    |
[ADO.NET数据提供程序]
    |
[数据库]
1.2.2 核心组件详解
  1. EDM (Entity Data Model)

    • CSDL (Conceptual Schema Definition Language): 概念层定义
    • SSDL (Storage Schema Definition Language): 存储层定义
    • MSL (Mapping Specification Language): 映射规范
  2. DbContext

    • 工作单元和仓库模式的实现
    • 包含的主要属性:
      • DbSet: 实体集合
      • ChangeTracker: 变更跟踪器
      • Configuration: 配置选项
  3. LINQ提供程序

    • 将LINQ查询转换为SQL语句
    • 支持查询语法和方法语法

第二部分:EF开发模式详解

2.1 Database First开发模式

Database First是从现有数据库生成模型的方法,适合已有成熟数据库结构的项目。

2.1.1 实施步骤
  1. 在Visual Studio中添加"ADO.NET实体数据模型"
  2. 选择"从数据库生成"
  3. 配置数据库连接
  4. 选择要包含的表、视图和存储过程
  5. 完成模型生成
2.1.2 优缺点分析

优点

  • 快速对接现有数据库
  • 可视化设计器便于理解数据结构
  • 自动生成实体类和上下文

缺点

  • 模型更新需重新生成
  • 自定义逻辑需扩展部分类
  • 与数据库耦合度较高

2.2 Model First开发模式

Model First允许先设计概念模型,再生成数据库结构。

2.2.1 工作流程
  1. 在EDM设计器中创建实体和关系
  2. 设置实体属性和关联
  3. 生成数据库脚本
  4. 执行脚本创建物理数据库
2.2.2 最佳实践
  • 合理使用继承策略(TPH, TPT, TPC)
  • 正确配置导航属性
  • 优化生成的DDL脚本

2.3 Code First开发模式

Code First是目前最流行的EF开发方式,完全通过代码定义模型。

2.3.1 基础实现
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

public class StoreContext : DbContext
{
    public DbSet<Product> Products { get; set; }
}
2.3.2 配置方式
  1. 数据注解

    [Table("tbl_Products")]
    public class Product
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ProductId { get; set; }
        
        [Required]
        [MaxLength(100)]
        public string Name { get; set; }
    }
    
  2. Fluent API

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>()
            .ToTable("tbl_Products")
            .HasKey(p => p.ProductId);
            
        modelBuilder.Entity<Product>()
            .Property(p => p.Name)
            .IsRequired()
            .HasMaxLength(100);
    }
    
2.3.3 迁移机制
  1. 启用迁移:

    Enable-Migrations
    
  2. 创建迁移:

    Add-Migration InitialCreate
    
  3. 更新数据库:

    Update-Database
    

第三部分:EF核心功能深入解析

3.1 查询数据

3.1.1 基本查询操作
// 获取所有产品
var products = context.Products.ToList();

// 条件查询
var expensiveProducts = context.Products
    .Where(p => p.Price > 100)
    .OrderBy(p => p.Name)
    .ToList();
3.1.2 加载相关数据
  1. 预先加载(Eager Loading)

    var orders = context.Orders
        .Include(o => o.Customer)
        .Include(o => o.OrderDetails)
        .ThenInclude(od => od.Product)
        .ToList();
    
  2. 显式加载(Explicit Loading)

    var order = context.Orders.Find(1);
    context.Entry(order)
        .Collection(o => o.OrderDetails)
        .Load();
    
  3. 延迟加载(Lazy Loading)

    • 需安装Microsoft.EntityFrameworkCore.Proxies包
    • 配置:
      protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
      {
          optionsBuilder.UseLazyLoadingProxies();
      }
      
3.1.3 原生SQL查询
var products = context.Products
    .FromSqlRaw("SELECT * FROM Products WHERE Price > {0}", 50)
    .ToList();

3.2 保存数据

3.2.1 基本操作
// 添加
var newProduct = new Product { Name = "New Product", Price = 99.99m };
context.Products.Add(newProduct);

// 更新
var product = context.Products.Find(1);
product.Price = 109.99m;

// 删除
var productToDelete = context.Products.Find(2);
context.Products.Remove(productToDelete);

// 保存
context.SaveChanges();
3.2.2 事务管理
  1. 默认事务

    using (var transaction = context.Database.BeginTransaction())
    {
        try
        {
            // 操作1
            // 操作2
            context.SaveChanges();
            transaction.Commit();
        }
        catch
        {
            transaction.Rollback();
        }
    }
    
  2. 跨上下文事务

    using (var scope = new TransactionScope())
    {
        // 上下文1操作
        // 上下文2操作
        scope.Complete();
    }
    

3.3 性能优化

3.3.1 查询优化技巧
  1. 选择性加载字段

    var productNames = context.Products
        .Select(p => new { p.Id, p.Name })
        .ToList();
    
  2. 批量操作

    // EF Core 5.0+ 支持
    context.Products.AddRange(productsList);
    await context.SaveChangesAsync();
    
  3. 禁用变更跟踪

    var products = context.Products
        .AsNoTracking()
        .ToList();
    
3.3.2 高级优化策略
  1. 编译查询

    private static readonly Func<MyContext, int, Product> _productById =
        EF.CompileQuery((MyContext db, int id) =>
            db.Products.FirstOrDefault(p => p.Id == id));
    
  2. 批处理语句

    • EF Core默认将多个操作合并为单个批处理
    • 可配置批处理大小:
      optionsBuilder.UseSqlServer(
          connectionString,
          options => options.MaxBatchSize(100));
      

第四部分:EF高级主题

4.1 复杂类型和值转换

4.1.1 复杂类型(Owned Entities)
modelBuilder.Entity<Order>().OwnsOne(
    o => o.ShippingAddress,
    sa =>
    {
        sa.Property(p => p.Street).HasColumnName("ShippingStreet");
        sa.Property(p => p.City).HasColumnName("ShippingCity");
    });
4.1.2 值转换器
modelBuilder.Entity<Product>()
    .Property(p => p.Price)
    .HasConversion(
        v => v.ToString(),
        v => decimal.Parse(v));

4.2 拦截器和事件

4.2.1 拦截器示例
public class MyInterceptor : DbCommandInterceptor
{
    public override InterceptionResult<DbDataReader> ReaderExecuting(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult<DbDataReader> result)
    {
        // 修改或记录命令
        return result;
    }
}
4.2.2 事件处理
context.SavingChanges += (sender, args) =>
{
    var entries = context.ChangeTracker.Entries();
    foreach (var entry in entries)
    {
        // 预处理实体
    }
};

4.3 多租户实现

modelBuilder.Entity<Product>().HasQueryFilter(p => p.TenantId == _tenantId);

第五部分:EF Core 特有功能

5.1 全局查询过滤器

modelBuilder.Entity<Blog>().HasQueryFilter(b => !b.IsDeleted);

5.2 表拆分

modelBuilder.Entity<Order>(eb =>
{
    eb.ToTable("Orders");
    eb.Property(o => o.Status).HasColumnName("Status");
    eb.OwnsOne(o => o.Details, odb =>
    {
        odb.ToTable("OrderDetails");
        odb.Property(od => od.Notes).HasColumnName("Notes");
    });
});

5.3 并发控制

modelBuilder.Entity<Person>()
    .Property(p => p.LastName)
    .IsConcurrencyToken();

第六部分:EF最佳实践

6.1 架构设计建议

  1. 分层架构

    • 表现层
    • 应用层
    • 领域层
    • 基础设施层(包含EF实现)
  2. 仓储模式实现

    public interface IRepository<T> where T : class
    {
        IQueryable<T> GetAll();
        Task<T> GetByIdAsync(int id);
        void Add(T entity);
        void Update(T entity);
        void Delete(T entity);
    }
    

6.2 性能调优指南

  1. 连接池配置

    services.AddDbContextPool<MyContext>(options => 
        options.UseSqlServer(connectionString), poolSize: 128);
    
  2. 批处理优化

    • 合理设置SaveChanges批处理大小
    • 考虑使用BulkExtensions进行大规模操作

6.3 安全注意事项

  1. SQL注入防护

    • 始终使用参数化查询
    • 避免直接拼接SQL字符串
  2. 敏感数据保护

    • 加密存储敏感字段
    • 实现数据访问审计

第七部分:EF与其他技术集成

7.1 与ASP.NET Core集成

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<MyContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("Default")));
    
    services.AddControllers();
}

7.2 DDD实现模式

public class Order : IAggregateRoot
{
    private readonly List<OrderItem> _items = new List<OrderItem>();
    
    public IReadOnlyCollection<OrderItem> Items => _items.AsReadOnly();
    
    public void AddItem(Product product, int quantity)
    {
        // 领域逻辑
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百锦再@新空间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值