在.NET Core生态系统中,主流的ORM(Object-Relational Mapping)框架包括:
本文重点介绍最常用的EF Core和Dapper。
安装NuGet包:
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer # SQL Server提供程序
# 或其他数据库提供程序
DbContext配置:
public class AppDbContext : DbContext
{
public DbSet Users { get; set; }
public DbSet Orders { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=.;Database=MyApp;Trusted_Connection=True;");
}
}
依赖注入配置(推荐):
// Startup.cs或Program.cs
builder.Services.AddDbContext(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
实体类:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime BirthDate { get; set; }
// 导航属性
public ICollection 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()
.Property(u => u.Name)
.IsRequired()
.HasMaxLength(50);
modelBuilder.Entity()
.HasOne(o => o.User)
.WithMany(u => u.Orders)
.HasForeignKey(o => o.UserId);
}
添加数据:
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();
}
}
异步操作:
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
安装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();
查询数据:
var users = connection.Query("SELECT * FROM Users WHERE Name LIKE @Name",
new { Name = "%张%" });
var user = connection.QueryFirstOrDefault("SELECT * FROM Users WHERE Id = @Id",
new { Id = 1 });
插入数据:
var id = connection.QuerySingle(
"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 });
存储过程调用:
var users = connection.Query("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().ToList();
var orders = multi.Read().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(sql, parameters);
特性 | EF Core | Dapper |
---|---|---|
性能 | 中等(有ORM开销) | 高(接近原生SQL) |
学习曲线 | 较陡峭(需理解LINQ、EF概念) | 平缓(SQL知识即可) |
功能丰富度 | 高(迁移、跟踪、变更检测等) | 低(仅数据访问) |
适用场景 | 复杂业务、快速开发 | 高性能需求、复杂SQL |
异步支持 | 原生支持 | 需手动实现 |
事务管理 | 内置支持 | 需手动实现 |
缓存 | 一级缓存 | 无内置缓存 |
选择EF Core当:
选择Dapper当:
合理使用延迟加载:
// 禁用延迟加载(推荐)
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();
使用参数化查询:
// 安全的方式
connection.Query("SELECT * FROM Users WHERE Name = @Name", new { Name = userInput });
// 避免拼接SQL字符串(有SQL注入风险)
// connection.Query($"SELECT * FROM Users WHERE Name = '{userInput}'");
连接管理:
// 使用using确保连接释放
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
// 执行操作
}
存储过程调用:
var result = connection.QueryFirstOrDefault(
"dbo.GetUserCountByRole",
new { RoleId = roleId },
commandType: CommandType.StoredProcedure);
启用查询缓存:
services.AddDbContext(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();
使用ExecuteScalar代替QueryFirstOrDefault:
// 获取单个值
var count = connection.ExecuteScalar("SELECT COUNT(*) FROM Users");
使用动态类型:
// 当不需要强类型时
var result = connection.Query("SELECT * FROM Users").FirstOrDefault();
连接池配置:
// 在连接字符串中配置
"Server=.;Database=MyApp;User Id=user;Password=pass;Max Pool Size=100;"
N+1查询问题:
Include
或ThenInclude
预加载Select
投影查询性能下降:
AsNoTracking
)迁移冲突:
dotnet ef migrations remove
回滚SQL注入风险:
连接泄漏:
using
语句结果映射错误:
Query
时确保T有默认构造函数EF Core Power Tools:
Entity Framework Core Profiler:
Dapper.Contrib:
connection.Insert(user);
connection.Update(user);
Dapper.FluentMap:
FluentMapper.Initialize(config =>
{
config.AddMap(new UserMap());
});
DapperQueryBuilder:
var query = connection.QueryBuilder($"SELECT * FROM Users WHERE 1=1");
if (name != null) query.Where("Name = @Name", new { Name = name });
var users = query.Query();
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 GetActiveUsers()
{
// 使用Dapper执行复杂查询
return _dapperConnection.Query("SELECT * FROM Users WHERE IsActive = 1");
}
}
通过合理选择ORM框架并遵循最佳实践,可以显著提高.NET Core应用程序的开发效率和性能表现。