.NET Core ORM框架用法简述
一、主流.NET Core ORM框架概述
在.NET Core生态系统中,主流的ORM(Object-Relational Mapping)框架包括:
- Entity Framework Core (EF Core) - 微软官方推出的ORM框架
- Dapper - 轻量级微ORM
- Npgsql.EntityFrameworkCore.PostgreSQL - PostgreSQL专用EF Core提供程序
- Pomelo.EntityFrameworkCore.MySql - MySQL专用EF Core提供程序
- LINQ to DB - 高性能ORM
本文重点介绍最常用的EF Core和Dapper。
二、Entity Framework Core (EF Core) 使用指南
1. 安装与配置
安装NuGet包:
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer # SQL Server提供程序
# 或其他数据库提供程序DbContext配置:
public class AppDbContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Order> Orders { get; set; }
    
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=.;Database=MyApp;Trusted_Connection=True;");
    }
}依赖注入配置(推荐):
// Startup.cs或Program.cs
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));2. 数据模型定义
实体类:
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime BirthDate { get; set; }
    
    // 导航属性
    public ICollection<Order> Orders { get; set; }
}
public class Order
{
    public int Id { get; set; }
    public decimal Amount { get; set; }
    public DateTime OrderDate { get; set; }
    
    // 外键和导航属性
    public int UserId { get; set; }
    public User User { get; set; }
}Fluent API配置:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>()
        .Property(u => u.Name)
        .IsRequired()
        .HasMaxLength(50);
        
    modelBuilder.Entity<Order>()
        .HasOne(o => o.User)
        .WithMany(u => u.Orders)
        .HasForeignKey(o => o.UserId);
}3. CRUD操作
添加数据:
using (var context = new AppDbContext())
{
    var user = new User { Name = "张三", BirthDate = new DateTime(1990, 1, 1) };
    context.Users.Add(user);
    context.SaveChanges();
}查询数据:
// 简单查询
var users = context.Users.ToList();
// 条件查询
var activeUsers = context.Users
    .Where(u => u.Name.Contains("张"))
    .OrderBy(u => u.BirthDate)
    .ToList();
// 投影查询
var userNames = context.Users
    .Select(u => new { u.Id, u.Name })
    .ToList();更新数据:
using (var context = new AppDbContext())
{
    var user = context.Users.Find(1);
    if (user != null)
    {
        user.Name = "李四";
        context.SaveChanges();
    }
}删除数据:
using (var context = new AppDbContext())
{
    var user = context.Users.Find(1);
    if (user != null)
    {
        context.Users.Remove(user);
        context.SaveChanges();
    }
}4. 高级功能
异步操作:
var user = await context.Users.FindAsync(1);
var users = await context.Users.Where(u => u.Name.Contains("张")).ToListAsync();事务处理:
using (var transaction = await context.Database.BeginTransactionAsync())
{
    try
    {
        // 执行多个操作
        await context.SaveChangesAsync();
        await transaction.CommitAsync();
    }
    catch
    {
        await transaction.RollbackAsync();
        throw;
    }
}迁移管理:
# 添加迁移
dotnet ef migrations add InitialCreate
# 更新数据库
dotnet ef database update
# 回滚迁移
dotnet ef database update PreviousMigration三、Dapper使用指南
1. 安装与配置
安装NuGet包:
dotnet add package Dapper
dotnet add package System.Data.SqlClient # SQL Server提供程序基本使用:
using var connection = new SqlConnection("Server=.;Database=MyApp;Trusted_Connection=True;");
connection.Open();2. CRUD操作
查询数据:
var users = connection.Query<User>("SELECT * FROM Users WHERE Name LIKE @Name", 
    new { Name = "%张%" });
var user = connection.QueryFirstOrDefault<User>("SELECT * FROM Users WHERE Id = @Id", 
    new { Id = 1 });插入数据:
var id = connection.QuerySingle<int>(
    "INSERT INTO Users (Name, BirthDate) VALUES (@Name, @BirthDate); SELECT SCOPE_IDENTITY();",
    new { Name = "张三", BirthDate = DateTime.Now });更新数据:
var affectedRows = connection.Execute(
    "UPDATE Users SET Name = @Name WHERE Id = @Id",
    new { Name = "李四", Id = 1 });删除数据:
var deletedRows = connection.Execute("DELETE FROM Users WHERE Id = @Id", new { Id = 1 });3. 高级功能
存储过程调用:
var users = connection.Query<User>("dbo.GetUsersByAgeRange", 
    new { MinAge = 18, MaxAge = 30 },
    commandType: CommandType.StoredProcedure);多结果集处理:
using (var multi = connection.QueryMultiple(
    "SELECT * FROM Users; SELECT * FROM Orders", 
    commandType: CommandType.Text))
{
    var users = multi.Read<User>().ToList();
    var orders = multi.Read<Order>().ToList();
}动态参数:
var sql = "SELECT * FROM Users WHERE 1=1";
var parameters = new DynamicParameters();
if (!string.IsNullOrEmpty(name))
{
    sql += " AND Name = @Name";
    parameters.Add("Name", name);
}
if (minAge.HasValue)
{
    sql += " AND Age >= @MinAge";
    parameters.Add("MinAge", minAge.Value);
}
var users = connection.Query<User>(sql, parameters);四、EF Core与Dapper对比
| 特性 | EF Core | Dapper | 
|---|---|---|
| 性能 | 中等(有ORM开销) | 高(接近原生SQL) | 
| 学习曲线 | 较陡峭(需理解LINQ、EF概念) | 平缓(SQL知识即可) | 
| 功能丰富度 | 高(迁移、跟踪、变更检测等) | 低(仅数据访问) | 
| 适用场景 | 复杂业务、快速开发 | 高性能需求、复杂SQL | 
| 异步支持 | 原生支持 | 需手动实现 | 
| 事务管理 | 内置支持 | 需手动实现 | 
| 缓存 | 一级缓存 | 无内置缓存 | 
五、选择建议
- 选择EF Core当: - 需要快速开发CRUD应用
- 团队熟悉ORM概念
- 需要数据库迁移功能
- 项目需要频繁变更数据模型
 
- 选择Dapper当: - 需要极致性能
- 执行复杂SQL查询
- 已有成熟的SQL知识
- 项目以读为主,写操作较少
 
六、最佳实践
EF Core最佳实践
- 合理使用延迟加载: - // 禁用延迟加载(推荐) protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseLazyLoadingProxies(false); }
- 批量操作优化: - // 使用AddRange代替多个Add context.Users.AddRange(usersList); // 对于大量数据,考虑分批处理 foreach (var batch in usersList.Batch(500)) { context.Users.AddRange(batch); context.SaveChanges(); }
- 避免N+1查询: - // 不好的做法(会导致N+1) var users = context.Users.ToList(); foreach (var user in users) { var orders = context.Orders.Where(o => o.UserId == user.Id).ToList(); } // 好的做法(预加载) var users = context.Users.Include(u => u.Orders).ToList();
Dapper最佳实践
- 使用参数化查询: - // 安全的方式 connection.Query<User>("SELECT * FROM Users WHERE Name = @Name", new { Name = userInput }); // 避免拼接SQL字符串(有SQL注入风险) // connection.Query<User>($"SELECT * FROM Users WHERE Name = '{userInput}'");
- 连接管理: - // 使用using确保连接释放 using (var connection = new SqlConnection(connectionString)) { connection.Open(); // 执行操作 }
- 存储过程调用: - var result = connection.QueryFirstOrDefault<int>( "dbo.GetUserCountByRole", new { RoleId = roleId }, commandType: CommandType.StoredProcedure);
七、性能优化技巧
EF Core性能优化
- 启用查询缓存: - services.AddDbContext<AppDbContext>(options => options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) .UseSqlServer(connectionString));
- 使用AsNoTracking: - // 只读场景使用 var users = context.Users.AsNoTracking().ToList();
- 投影查询: - // 只查询需要的字段 var userDtos = context.Users .Select(u => new UserDto { Id = u.Id, Name = u.Name }) .ToList();
Dapper性能优化
- 使用ExecuteScalar代替QueryFirstOrDefault: - // 获取单个值 var count = connection.ExecuteScalar<int>("SELECT COUNT(*) FROM Users");
- 使用动态类型: - // 当不需要强类型时 var result = connection.Query("SELECT * FROM Users").FirstOrDefault();
- 连接池配置: - // 在连接字符串中配置 "Server=.;Database=MyApp;User Id=user;Password=pass;Max Pool Size=100;"
八、常见问题解决
EF Core常见问题
- N+1查询问题: - 使用Include或ThenInclude预加载
- 使用Select投影查询
 
- 使用
- 性能下降: - 检查生成的SQL(使用日志)
- 考虑禁用变更跟踪(AsNoTracking)
- 优化数据库索引
 
- 迁移冲突: - 使用dotnet ef migrations remove回滚
- 手动合并迁移文件
 
- 使用
Dapper常见问题
- SQL注入风险: - 始终使用参数化查询
- 避免字符串拼接SQL
 
- 连接泄漏: - 确保使用using语句
- 实现IDisposable模式管理连接
 
- 确保使用
- 结果映射错误: - 检查列名与属性名匹配
- 使用Query<T>时确保T有默认构造函数
 
九、工具与扩展
EF Core工具
- EF Core Power Tools: - 可视化查看数据库模型
- 快速生成实体类
- 执行数据库比较
 
- Entity Framework Core Profiler: - 分析EF Core生成的SQL
- 性能监控
 
Dapper扩展
- Dapper.Contrib: - 添加简单的CRUD扩展方法
 - connection.Insert(user); connection.Update(user);
- Dapper.FluentMap: - 配置实体到表的映射
 - FluentMapper.Initialize(config => { config.AddMap(new UserMap()); });
- DapperQueryBuilder: - 构建安全动态SQL
 - var query = connection.QueryBuilder($"SELECT * FROM Users WHERE 1=1"); if (name != null) query.Where("Name = @Name", new { Name = name }); var users = query.Query<User>();
十、总结与建议
- EF Core适合: - 快速开发的企业应用
- 需要数据库迁移的项目
- 团队熟悉ORM的情况
 
- Dapper适合: - 高性能要求的微服务
- 复杂SQL查询场景
- 已有成熟SQL知识的项目
 
- 混合使用策略: - 主框架使用EF Core
- 性能关键部分使用Dapper
 - // 在EF Core项目中使用Dapper public class UserRepository : IUserRepository { private readonly AppDbContext _context; private readonly IDbConnection _dapperConnection; public UserRepository(AppDbContext context, IDbConnection dapperConnection) { _context = context; _dapperConnection = dapperConnection; } public User GetById(int id) { // 使用EF Core return _context.Users.Find(id); } public IEnumerable<User> GetActiveUsers() { // 使用Dapper执行复杂查询 return _dapperConnection.Query<User>("SELECT * FROM Users WHERE IsActive = 1"); } }
通过合理选择ORM框架并遵循最佳实践,可以显著提高.NET Core应用程序的开发效率和性能表现。