主题
EF Core 入门指南
Entity Framework Core (EF Core) 是微软官方提供的对象关系映射 (ORM) 框架,用于简化 .NET 应用程序与数据库的交互。它支持多种数据库,包括 SQL Server、MySQL、PostgreSQL、SQLite 等。
1. 安装 EF Core
1.1 安装核心包
在项目中安装 EF Core 核心包和相应的数据库提供程序:
bash
# 安装 EF Core 核心包
dotnet add package Microsoft.EntityFrameworkCore
# 安装 SQL Server 提供程序
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
# 安装 MySQL 提供程序(如果使用 MySQL)
dotnet add package Pomelo.EntityFrameworkCore.MySql
# 安装工具包(用于迁移)
dotnet add package Microsoft.EntityFrameworkCore.Design2. 创建数据模型
2.1 定义实体类
csharp
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class Product
{
[Key]
public int ProductId { get; set; }
[Required]
[StringLength(100)]
public string Name { get; set; }
[Column(TypeName = "decimal(18,2)")]
public decimal Price { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.Now;
}
public class Category
{
[Key]
public int CategoryId { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
// 导航属性 - 一对多关系
public ICollection<Product> Products { get; set; }
}3. 创建数据上下文
3.1 定义 DbContext
csharp
using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{}
// DbSet 属性 - 对应数据库表
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
// 配置模型关系(可选)
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 配置 Category 和 Product 的一对多关系
modelBuilder.Entity<Category>()
.HasMany(c => c.Products)
.WithOne()
.HasForeignKey("CategoryId");
// 其他配置...
}
}4. 配置 EF Core
4.1 在 Program.cs 中配置
csharp
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// 配置数据库连接字符串
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
// 注册 DbContext
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(connectionString));
var app = builder.Build();
// ...4.2 在 appsettings.json 中配置连接字符串
json
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MyDatabase;Trusted_Connection=True;"
}
}5. 数据库迁移
5.1 创建迁移
bash
dotnet ef migrations add InitialCreate5.2 应用迁移
bash
dotnet ef database update5.3 移除迁移
bash
dotnet ef migrations remove6. 基本 CRUD 操作
6.1 插入数据
csharp
using var context = new AppDbContext();
// 创建新分类
var category = new Category { Name = "电子产品" };
context.Categories.Add(category);
// 创建新产品
var product = new Product
{
Name = "智能手机",
Price = 2999.99M,
Description = "高性能智能手机",
IsActive = true
};
context.Products.Add(product);
// 保存更改
await context.SaveChangesAsync();6.2 查询数据
csharp
using var context = new AppDbContext();
// 查询所有产品
var allProducts = await context.Products.ToListAsync();
// 条件查询
var activeProducts = await context.Products
.Where(p => p.IsActive && p.Price > 1000)
.ToListAsync();
// 包含关联数据(Eager Loading)
var productsWithCategories = await context.Products
.Include(p => p.Category)
.ToListAsync();
// 分页查询
var page = 1;
var pageSize = 10;
var pagedProducts = await context.Products
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync();6.3 更新数据
csharp
using var context = new AppDbContext();
// 查找产品
var product = await context.Products.FindAsync(1);
if (product != null)
{
// 更新属性
product.Price = 2799.99M;
product.IsActive = false;
// 保存更改
await context.SaveChangesAsync();
}6.4 删除数据
csharp
using var context = new AppDbContext();
// 查找产品
var product = await context.Products.FindAsync(1);
if (product != null)
{
// 删除产品
context.Products.Remove(product);
// 保存更改
await context.SaveChangesAsync();
}7. 查询优化
7.1 延迟加载(Lazy Loading)
bash
# 安装延迟加载包
dotnet add package Microsoft.EntityFrameworkCore.Proxiescsharp
// 在配置中启用延迟加载
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(connectionString)
.UseLazyLoadingProxies());7.2 显式加载(Explicit Loading)
csharp
using var context = new AppDbContext();
var product = await context.Products.FindAsync(1);
// 显式加载分类
await context.Entry(product).Reference(p => p.Category).LoadAsync();
// 显式加载集合
await context.Entry(category).Collection(c => c.Products).LoadAsync();7.3 投影查询
csharp
// 只查询需要的字段
var productSummaries = await context.Products
.Select(p => new
{
p.ProductId,
p.Name,
p.Price
})
.ToListAsync();8. 高级特性
8.1 事务管理
csharp
using var context = new AppDbContext();
using var transaction = await context.Database.BeginTransactionAsync();
try
{
// 执行多个操作
context.Products.Add(newProduct);
context.Categories.Add(newCategory);
await context.SaveChangesAsync();
await transaction.CommitAsync();
}
catch (Exception)
{
await transaction.RollbackAsync();
throw;
}8.2 原生 SQL 查询
csharp
// 执行原生 SQL 查询
var products = await context.Products
.FromSqlRaw("SELECT * FROM Products WHERE Price > {0}", 1000)
.ToListAsync();
// 执行非查询 SQL
await context.Database.ExecuteSqlRawAsync("UPDATE Products SET IsActive = 0 WHERE CreatedAt < {0}", DateTime.Now.AddYears(-1));9. 最佳实践
- 使用依赖注入:在 ASP.NET Core 应用中,始终通过依赖注入使用 DbContext
- ** DbContext 是轻量级的**:每个请求创建一个新的 DbContext 实例
- 使用异步方法:优先使用 Async 版本的方法(如 SaveChangesAsync)
- 合理使用加载策略:
- Eager Loading:使用 Include 预加载所需的关联数据
- Lazy Loading:谨慎使用,避免 N+1 查询问题
- Explicit Loading:仅在必要时加载关联数据
- 使用投影:只查询需要的字段,减少数据传输
- 批量操作:对于大量数据操作,考虑使用 AddRange/RemoveRange
- 迁移管理:使用迁移管理数据库架构变更
- 性能监控:使用 EF Core Profiler 等工具监控查询性能