【C#数据库编程终极指南】用Entity Framework Core 7征服ORM!——从代码优先到多数据库迁移的深度实战

  1. EF Core核心架构:从DbContext到LINQ查询的底层实现
  2. 三种开发模式:Database First/Code First/Model First实战
  3. 性能优化:延迟加载、分页查询、NoTracking技巧
  4. 分布式事务:跨数据库事务的实现与异常处理
  5. 多数据库支持:SQL Server/MySQL/PostgreSQL无缝切换

一、EF Core核心架构与DbContext

1.1 DbContext的底层魔法

/// <summary>  
/// 博客系统数据库上下文  
/// </summary>  
public class BloggingContext : DbContext  
{  
    public DbSet<Blog> Blogs { get; set; }  
    public DbSet<Post> Posts { get; set; }  

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)  
    {  
        // 配置多数据库支持  
        optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=Blogging;Trusted_Connection=True;");  
        // optionsBuilder.UseMySql("Server=localhost;Database=Blogging;User=root;Password=123456;",  
        //     new MySqlServerVersion(new Version(8, 0, 21)));  
    }  

    protected override void OnModelCreating(ModelBuilder modelBuilder)  
    {  
        // 配置主键策略  
        modelBuilder.Entity<Post>()  
            .Property(p => p.PostId)  
            .ValueGeneratedOnAdd();  

        // 配置关系映射  
        modelBuilder.Entity<Post>()  
            .HasOne(p => p.Blog)  
            .WithMany(b => b.Posts)  
            .HasForeignKey(p => p.BlogId);  
    }  
}  

1.2 EF Core的生命周期管理

/// <summary>  
/// 依赖注入式DbContext管理  
/// </summary>  
public class Startup  
{  
    public void ConfigureServices(IServiceCollection services)  
    {  
        // 使用设计时上下文工厂  
        services.AddDbContext<BloggingContext>(  
            options => options.UseSqlServer(Configuration.GetConnectionString("Default")));  

        // 注册分布式事务  
        services.AddDistributedSqlServerCache(options =>  
        {  
            options.ConnectionString = Configuration.GetConnectionString("Default");  
        });  
    }  
}  

二、EF Core开发模式实战

2.1 Database First模式

步骤1:逆向工程生成模型
dotnet ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;"  
Microsoft.EntityFrameworkCore.SqlServer --context BloggingContext  
步骤2:自动生成的实体类
[Table("Blogs")]  
public partial class Blog  
{  
    public int BlogId { get; set; }  
    public string Url { get; set; }  

    [InverseProperty("Blog")]  
    public virtual ICollection<Post> Posts { get; set; }  
}  

2.2 Code First模式

步骤1:定义实体类
/// <summary>  
/// 博客实体(含自定义映射)  
/// </summary>  
public class Blog  
{  
    [Key]  
    public int BlogId { get; set; }  

    [Required, MaxLength(255)]  
    public string Url { get; set; }  

    [ForeignKey("User")]  
    public int OwnerId { get; set; }  

    public virtual User Owner { get; set; }  
}  
步骤2:迁移与更新数据库
dotnet ef migrations add InitialCreate  
dotnet ef database update  

2.3 Model First模式(EF6特性)

// 通过EDMX文件设计模型  
// 右键生成SQL脚本后执行  
public partial class BlogModel : DbContext  
{  
    public BlogModel() : base("name=BlogModel") { }  
    public virtual DbSet<Blog> Blogs { get; set; }  
}  

三、高级查询与性能优化

3.1 LINQ查询的黑科技

public class BlogService  
{  
    private readonly BloggingContext _context;  

    public BlogService(BloggingContext context)  
    {  
        _context = context;  
    }  

    // 使用投影查询减少数据传输  
    public IEnumerable<PostSummary> GetPostSummaries()  
    {  
        return _context.Posts  
            .Where(p => p.Published)  
            .Select(p => new PostSummary  
            {  
                Id = p.PostId,  
                Title = p.Title,  
                Author = p.Blog.Owner.Name, // 跨实体查询  
                Views = p.ViewCount  
            })  
            .ToList();  
    }  

    // 分页查询优化  
    public PagedList<Post> GetPosts(int pageNumber, int pageSize)  
    {  
        return new PagedList<Post>(  
            _context.Posts  
                .OrderByDescending(p => p.CreatedOn)  
                .Skip((pageNumber - 1) * pageSize)  
                .Take(pageSize),  
            pageNumber,  
            pageSize);  
    }  
}  

3.2 NoTracking与延迟加载

// 禁用变化跟踪(读取场景)  
public List<Post> GetPopularPosts()  
{  
    return _context.Posts  
        .AsNoTracking() // 关键优化点  
        .Where(p => p.Views > 1000)  
        .ToList();  
}  

// 显式加载(避免N+1查询)  
public void LoadPostDetails(int postId)  
{  
    var post = _context.Posts  
        .Include(p => p.Blog)  
        .ThenInclude(b => b.Owner)  
        .FirstOrDefault(p => p.PostId == postId);  

    // 显式加载评论  
    _context.Entry(post).Collection(p => p.Comments).Load();  
}  

四、分布式事务与复杂场景

4.1 跨数据库事务(使用TransactionScope)

public class OrderService  
{  
    private readonly BloggingContext _blogContext;  
    private readonly SalesContext _salesContext;  

    public void PlaceOrder(int blogId, decimal amount)  
    {  
        using (var scope = new TransactionScope(TransactionScopeOption.Required,  
            new TransactionOptions { IsolationLevel = IsolationLevel.Serializable }))  
        {  
            try  
            {  
                // 更新博客积分  
                var blog = _blogContext.Blogs.Find(blogId);  
                blog.Credits += 100;  

                // 插入销售记录  
                _salesContext.Orders.Add(new Order { BlogId = blogId, Amount = amount });  

                _blogContext.SaveChanges();  
                _salesContext.SaveChanges();  

                scope.Complete();  
            }  
            catch (Exception ex)  
            {  
                // 事务自动回滚  
                throw new TransactionException("订单处理失败", ex);  
            }  
        }  
    }  
}  

4.2 数据库迁移的版本控制

// 在DbContext中配置迁移历史表  
protected override void OnModelCreating(ModelBuilder modelBuilder)  
{  
    modelBuilder.HasAnnotation(  
        "ProductVersion",  
        "7.0.0"); // 强制指定EF版本  
}  

// 自定义迁移脚本  
public partial class AddAuditColumns : Migration  
{  
    protected override void Up(MigrationBuilder migrationBuilder)  
    {  
        migrationBuilder.AddColumn<DateTime>(  
            name: "CreatedAt",  
            table: "Posts",  
            type: "datetime2",  
            nullable: false,  
            defaultValueSql: "GETDATE()");  

        migrationBuilder.CreateIndex(  
            name: "IX_Posts_BlogId",  
            table: "Posts",  
            column: "BlogId");  
    }  
}  

5.2 最佳实践清单

  1. 分页优化:使用AsNoTracking()Skip/Take
  2. 事务边界:将业务逻辑单元包装在TransactionScope
  3. 延迟加载:通过virtual关键字启用,但需谨慎使用以避免N+1问题
  4. 多数据库支持:通过UseXxx()方法实现,注意SQL方言差异
  5. 性能监控:使用EF Core Profiler分析查询执行计划

六、EF Core是数据库开发的“瑞士军刀”

通过本文的20+代码示例深度技术解析,开发者可以:

  1. 架构设计:选择适合项目的开发模式(Database First/Code First)
  2. 性能调优:通过NoTracking、分页、索引优化查询速度
  3. 事务管理:实现分布式事务和跨数据库操作
  4. 迁移管理:使用EF Core CLI进行版本控制
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值