跳转到内容

C Sharp EF 代码优先(Code First)

来自代码酷

C# EF 代码优先(Code First)[编辑 | 编辑源代码]

Entity Framework (EF) 代码优先(Code First)是微软推出的一种面向对象的数据库开发方法,允许开发者通过定义C#类来创建数据库结构,而无需手动编写SQL脚本或使用数据库设计工具。它属于ORM(对象关系映射)技术的一部分,适用于需要快速开发、灵活调整数据模型的场景。

核心概念[编辑 | 编辑源代码]

代码优先方法的核心思想是:

  • 开发者首先编写领域模型(POCO类)
  • EF根据这些类自动生成数据库架构
  • 支持数据库迁移(Migrations)来同步模型变更

与传统方法的对比[编辑 | 编辑源代码]

ADO.NET / 数据库优先 EF 代码优先
先编写C#类
自动生成SQL
修改类后运行迁移命令

基础实现步骤[编辑 | 编辑源代码]

以下是实现EF代码优先的基本流程:

1. 安装NuGet包[编辑 | 编辑源代码]

Install-Package EntityFramework

2. 创建领域模型[编辑 | 编辑源代码]

public class Blog 
{
    public int BlogId { get; set; }
    public string Name { get; set; }
    // 导航属性
    public virtual ICollection<Post> Posts { get; set; }
}

public class Post 
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    // 外键
    public int BlogId { get; set; }
    // 导航属性
    public virtual Blog Blog { get; set; }
}

3. 创建DbContext[编辑 | 编辑源代码]

public class BlogContext : DbContext 
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
}

4. 配置连接字符串[编辑 | 编辑源代码]

在App.config或Web.config中添加:

<connectionStrings>
    <add name="BlogContext" 
         connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=BlogDB;Integrated Security=True" 
         providerName="System.Data.SqlClient"/>
</connectionStrings>

数据库迁移[编辑 | 编辑源代码]

代码优先的强大功能之一是支持数据库架构的版本控制:

启用迁移[编辑 | 编辑源代码]

Enable-Migrations

创建迁移[编辑 | 编辑源代码]

Add-Migration InitialCreate

更新数据库[编辑 | 编辑源代码]

Update-Database

高级配置[编辑 | 编辑源代码]

数据注解[编辑 | 编辑源代码]

可以通过特性配置模型:

[Table("BlogArticles")]
public class Blog 
{
    [Key]
    public int PrimaryKey { get; set; }
    
    [Required]
    [MaxLength(100)]
    public string Name { get; set; }
}

Fluent API[编辑 | 编辑源代码]

在DbContext中重写OnModelCreating方法:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Name)
        .IsRequired()
        .HasMaxLength(100);
}

实际应用案例[编辑 | 编辑源代码]

场景:开发一个简单的博客系统

模型定义[编辑 | 编辑源代码]

public class Author
{
    public int AuthorId { get; set; }
    public string Name { get; set; }
    public ICollection<Blog> Blogs { get; set; }
}

// 扩展之前的Blog类
public class Blog 
{
    //...其他属性
    public int AuthorId { get; set; }
    public Author Author { get; set; }
}

数据库查询示例[编辑 | 编辑源代码]

using (var context = new BlogContext())
{
    // 添加数据
    var author = new Author { Name = "张三" };
    context.Authors.Add(author);
    
    var blog = new Blog { 
        Name = "EF教程", 
        Author = author 
    };
    context.Blogs.Add(blog);
    
    context.SaveChanges();
    
    // 查询数据
    var blogsWithAuthors = context.Blogs
        .Include(b => b.Author)
        .ToList();
}

性能优化[编辑 | 编辑源代码]

  • 延迟加载:使用virtual关键字标记导航属性
  • 预先加载:使用Include方法
  • 批量操作:使用AddRange/RemoveRange

批量插入示例[编辑 | 编辑源代码]

var blogs = new List<Blog>();
for (int i = 0; i < 1000; i++) 
{
    blogs.Add(new Blog { Name = $"Blog {i}" });
}
context.Blogs.AddRange(blogs);
context.SaveChanges();

架构图[编辑 | 编辑源代码]

classDiagram class Blog { +int BlogId +string Name +ICollection<Post> Posts } class Post { +int PostId +string Title +string Content +int BlogId +Blog Blog } Blog "1" --> "*" Post

数学表示[编辑 | 编辑源代码]

关系模型可以表示为: R(Blog)=(BlogId,Name,...) R(Post)=(PostId,Title,Content,BlogId,...) 外键约束: BlogIdPostBlogIdBlog

常见问题[编辑 | 编辑源代码]

Q: 如何处理现有数据库? A: 使用逆向工程工具"EF Power Tools"或Scaffold-DbContext命令

Q: 如何执行原始SQL? A: 使用DbContext.Database.SqlQuery方法

Q: 并发冲突如何解决? A: 使用[ConcurrencyCheck]特性或配置RowVersion

最佳实践[编辑 | 编辑源代码]

  • 保持POCO类简单
  • 将配置分离到单独的类
  • 使用仓储模式抽象DbContext
  • 为频繁查询添加适当的索引

总结[编辑 | 编辑源代码]

EF代码优先提供了一种高效的数据库开发方式,特别适合:

  • 快速原型开发
  • 领域驱动设计(DDD)项目
  • 需要频繁修改数据模型的场景

通过合理使用迁移、配置和优化技术,可以构建出既灵活又高性能的数据访问层。