最完整EF Core入门指南:从零开始掌握.NET ORM

最完整EF Core入门指南:从零开始掌握.NET ORM

【免费下载链接】efcore efcore: 是 .NET 平台上一个开源的对象关系映射(ORM)框架,用于操作关系型数据库。适合开发者使用 .NET 进行数据库操作,简化数据访问和持久化过程。 【免费下载链接】efcore 项目地址: https://gitcode.com/GitHub_Trending/ef/efcore

引言

还在为繁琐的数据库操作而烦恼?还在手动编写SQL语句处理数据持久化?Entity Framework Core(EF Core)作为.NET平台最强大的对象关系映射(ORM)框架,将彻底改变你的开发体验。本文将带你从零开始,全面掌握EF Core的核心概念、使用技巧和最佳实践。

读完本文,你将获得:

  • ✅ EF Core核心概念与架构理解
  • ✅ 数据库上下文(DbContext)配置与使用
  • ✅ 实体模型定义与关系映射
  • ✅ LINQ查询与数据操作完整指南
  • ✅ 迁移管理与数据库版本控制
  • ✅ 性能优化与高级特性
  • ✅ 实战项目示例与最佳实践

1. EF Core概述与核心概念

1.1 什么是EF Core?

Entity Framework Core是微软开发的轻量级、可扩展、开源的对象关系映射器(ORM),它允许.NET开发者使用.NET对象来处理数据库,无需关注底层数据库细节。

mermaid

1.2 EF Core核心组件

组件描述作用
DbContext数据库会话管理数据库连接、跟踪变更、执行查询
DbSet 实体集合表示数据库中的表
Model Builder模型配置定义实体映射关系
Migration数据库迁移管理数据库架构变更

2. 环境准备与安装

2.1 安装EF Core

# 安装EF Core核心包
dotnet add package Microsoft.EntityFrameworkCore

# 安装SQL Server提供程序
dotnet add package Microsoft.EntityFrameworkCore.SqlServer

# 安装SQLite提供程序  
dotnet add package Microsoft.EntityFrameworkCore.Sqlite

# 安装工具包(用于迁移)
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.Tools

2.2 项目配置

确保在.csproj文件中包含正确的目标框架:

<PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

3. 创建第一个DbContext

3.1 定义实体模型

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    public int Rating { get; set; }
    
    // 导航属性 - 一对多关系
    public List<Post> Posts { get; set; } = new List<Post>();
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public DateTime CreatedDate { get; set; }
    
    // 外键属性
    public int BlogId { get; set; }
    
    // 导航属性 - 多对一关系
    public Blog Blog { get; set; }
}

3.2 创建DbContext

using Microsoft.EntityFrameworkCore;

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

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // 配置SQL Server连接字符串
        optionsBuilder.UseSqlServer(
            "Server=(localdb)\\mssqllocaldb;Database=BloggingDb;Trusted_Connection=true;");
            
        // 或者配置SQLite连接
        // optionsBuilder.UseSqlite("Data Source=blogging.db");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // 配置模型关系
        modelBuilder.Entity<Blog>()
            .HasMany(b => b.Posts)
            .WithOne(p => p.Blog)
            .HasForeignKey(p => p.BlogId);
    }
}

4. 数据库迁移管理

4.1 创建初始迁移

# 创建迁移
dotnet ef migrations add InitialCreate

# 应用迁移到数据库
dotnet ef database update

4.2 迁移文件结构

mermaid

4.3 常见迁移命令

命令描述示例
Add Migration创建新迁移dotnet ef migrations Add AddRatingToBlog
Remove Migration删除最新迁移dotnet ef migrations Remove
Update Database应用迁移dotnet ef database update
Script Migration生成SQL脚本dotnet ef migrations script

5. 数据操作CRUD

5.1 创建数据(Create)

using var context = new BloggingContext();

// 添加新博客
var blog = new Blog { Url = "https://example.com", Rating = 5 };
context.Blogs.Add(blog);

// 添加带关联帖子的博客
var blogWithPosts = new Blog
{
    Url = "https://techblog.com",
    Rating = 4,
    Posts = new List<Post>
    {
        new Post { Title = "EF Core入门", Content = "..." },
        new Post { Title = "高级查询技巧", Content = "..." }
    }
};
context.Blogs.Add(blogWithPosts);

// 保存更改
context.SaveChanges();

5.2 查询数据(Read)

// 基本查询
var blogs = context.Blogs.ToList();

// 条件查询
var highRatedBlogs = context.Blogs
    .Where(b => b.Rating > 3)
    .ToList();

// 包含关联数据(Eager Loading)
var blogsWithPosts = context.Blogs
    .Include(b => b.Posts)
    .Where(b => b.Rating > 3)
    .ToList();

// 投影查询
var blogTitles = context.Blogs
    .Select(b => new { b.Url, PostCount = b.Posts.Count })
    .ToList();

5.3 更新数据(Update)

// 查询并修改
var blog = context.Blogs.First();
blog.Rating = 5;
context.SaveChanges();

// 批量更新
context.Blogs
    .Where(b => b.Rating < 3)
    .ExecuteUpdate(b => b.SetProperty(p => p.Rating, p => p.Rating + 1));

5.4 删除数据(Delete)

// 删除单个实体
var blog = context.Blogs.First();
context.Blogs.Remove(blog);
context.SaveChanges();

// 批量删除
context.Blogs
    .Where(b => b.Rating < 2)
    .ExecuteDelete();

6. 高级查询技巧

6.1 LINQ查询示例

// 复杂查询
var recentPosts = context.Posts
    .Where(p => p.CreatedDate > DateTime.Now.AddDays(-7))
    .OrderByDescending(p => p.CreatedDate)
    .Select(p => new 
    {
        p.Title,
        BlogUrl = p.Blog.Url,
        DaysAgo = EF.Functions.DateDiffDay(p.CreatedDate, DateTime.Now)
    })
    .ToList();

// 分组查询
var postsByBlog = context.Posts
    .GroupBy(p => p.Blog.Url)
    .Select(g => new
    {
        BlogUrl = g.Key,
        PostCount = g.Count(),
        AverageRating = g.Average(p => p.Blog.Rating)
    })
    .ToList();

6.2 原始SQL查询

// 执行原始SQL
var blogs = context.Blogs
    .FromSqlRaw("SELECT * FROM Blogs WHERE Rating > {0}", 3)
    .ToList();

// 存储过程调用
var result = context.Blogs
    .FromSqlRaw("EXEC GetTopRatedBlogs @minRating={0}", 4)
    .ToList();

7. 模型配置与关系

7.1 数据注解配置

public class Blog
{
    [Key]
    public int BlogId { get; set; }
    
    [Required]
    [MaxLength(500)]
    public string Url { get; set; }
    
    [Range(1, 5)]
    public int Rating { get; set; }
    
    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DateTime CreatedDate { get; set; }
}

7.2 Fluent API配置

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>(entity =>
    {
        entity.HasKey(b => b.BlogId);
        entity.Property(b => b.Url)
            .IsRequired()
            .HasMaxLength(500);
        entity.Property(b => b.Rating)
            .HasDefaultValue(3);
        entity.HasIndex(b => b.Url)
            .IsUnique();
    });
    
    modelBuilder.Entity<Post>(entity =>
    {
        entity.HasOne(p => p.Blog)
            .WithMany(b => b.Posts)
            .HasForeignKey(p => p.BlogId)
            .OnDelete(DeleteBehavior.Cascade);
    });
}

7.3 关系类型配置

mermaid

8. 性能优化策略

8.1 查询性能优化

// 使用AsNoTracking避免变更跟踪
var blogs = context.Blogs
    .AsNoTracking()
    .Where(b => b.Rating > 3)
    .ToList();

// 分页查询
var pagedBlogs = context.Blogs
    .OrderBy(b => b.BlogId)
    .Skip(20)
    .Take(10)
    .ToList();

// 只选择需要的字段
var blogInfo = context.Blogs
    .Select(b => new { b.BlogId, b.Url })
    .ToList();

8.2 批量操作优化

// 使用批量操作
context.BulkInsert(blogs);
context.BulkUpdate(blogs);
context.BulkDelete(blogs);

// 或者使用ExecuteUpdate/ExecuteDelete
context.Blogs
    .Where(b => b.Rating < 3)
    .ExecuteUpdate(b => b.SetProperty(p => p.Rating, 3));

9. 实战:完整示例项目

9.1 项目结构

BloggingApp/
├── Models/
│   ├── Blog.cs
│   ├── Post.cs
│   └── Comment.cs
├── Data/
│   └── BloggingContext.cs
├── Services/
│   └── BlogService.cs
└── Program.cs

9.2 服务层实现

public class BlogService
{
    private readonly BloggingContext _context;

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

    public async Task<Blog> CreateBlogAsync(string url, int rating)
    {
        var blog = new Blog { Url = url, Rating = rating };
        _context.Blogs.Add(blog);
        await _context.SaveChangesAsync();
        return blog;
    }

    public async Task<List<Blog>> GetTopRatedBlogsAsync(int count)
    {
        return await _context.Blogs
            .Where(b => b.Rating >= 4)
            .OrderByDescending(b => b.Rating)
            .Take(count)
            .Include(b => b.Posts)
            .AsNoTracking()
            .ToListAsync();
    }
}

9.3 依赖注入配置

// Program.cs
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDbContext<BloggingContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddScoped<BlogService>();

var app = builder.Build();

10. 常见问题与解决方案

10.1 性能问题排查

问题现象可能原因解决方案
查询缓慢N+1查询问题使用Include预加载关联数据
内存占用高变更跟踪过多使用AsNoTracking()
保存缓慢大量单条操作使用批量操作

10.2 并发处理

public class Blog
{
    [Timestamp]
    public byte[] RowVersion { get; set; }
}

// 处理并发冲突
try
{
    await context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException ex)
{
    foreach (var entry in ex.Entries)
    {
        var databaseValues = await entry.GetDatabaseValuesAsync();
        var currentValues = entry.CurrentValues;
        
        // 处理冲突逻辑
        foreach (var property in currentValues.Properties)
        {
            var databaseValue = databaseValues[property];
            var currentValue = currentValues[property];
            
            // 选择保留哪个值
            currentValues[property] = databaseValue;
        }
        
        await entry.RefreshAsync(RefreshMode.StoreWins);
    }
}

11. 最佳实践总结

11.1 开发阶段建议

  1. 使用Code First:从领域模型开始,让EF Core生成数据库
  2. 频繁创建迁移:每次模型变更都创建新的迁移
  3. 编写集成测试:确保数据库操作的正确性
  4. 使用配置分离:将连接字符串放在配置文件中

11.2 生产环境建议

  1. 启用日志记录:监控SQL查询性能
  2. 使用连接池:优化数据库连接管理
  3. 定期清理迁移:删除不再需要的旧迁移
  4. 备份迁移历史:确保可以回滚到任何版本

11.3 性能优化清单

  •  使用AsNoTracking()减少内存占用
  •  使用Include()避免N+1查询
  •  使用批量操作减少数据库往返
  •  创建适当的索引优化查询性能
  •  监控生成的SQL语句

结语

EF Core作为.NET生态系统中最重要的数据访问技术,掌握了它就掌握了现代.NET开发的钥匙。从简单的CRUD操作到复杂的企业级应用,EF Core都能提供强大的支持。通过本文的全面学习,相信你已经具备了使用EF Core进行实际项目开发的能力。

记住,良好的数据访问层设计是应用程序成功的关键。继续探索EF Core的高级特性,如全局查询过滤器、值转换器、拦截器等,让你的数据访问层更加健壮和高效。

开始你的EF Core之旅吧,让数据访问变得简单而优雅!

【免费下载链接】efcore efcore: 是 .NET 平台上一个开源的对象关系映射(ORM)框架,用于操作关系型数据库。适合开发者使用 .NET 进行数据库操作,简化数据访问和持久化过程。 【免费下载链接】efcore 项目地址: https://gitcode.com/GitHub_Trending/ef/efcore

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

抵扣说明:

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

余额充值