Appearance
安装与配置 EF Core
完整的 NuGet 包安装、依赖注入和数据库配置指南
📦 安装 EF Core
1. 安装 .NET SDK
首先确保安装了 .NET 8/9/10 SDK:
bash
# 检查版本
dotnet --version
# 应显示: 8.0.x, 9.0.x 或 10.0.x2. 创建项目
bash
# 创建 Web API 项目
dotnet new webapi -n EfCoreDemo
cd EfCoreDemo
# 或创建控制台项目
dotnet new console -n EfCoreDemo
cd EfCoreDemo3. 安装 NuGet 包
基础包(必需)
bash
# SQL Server
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
# PostgreSQL
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
# MySQL
dotnet add package Pomelo.EntityFrameworkCore.MySql
# SQLite
dotnet add package Microsoft.EntityFrameworkCore.Sqlite工具包(开发时必需)
bash
# EF Core CLI 工具
dotnet add package Microsoft.EntityFrameworkCore.Tools
# 设计时支持
dotnet add package Microsoft.EntityFrameworkCore.Design可选包
bash
# 性能分析
dotnet add package MiniProfiler.EntityFrameworkCore
# 批量操作(第三方)
dotnet add package EFCore.BulkExtensions
# 二级缓存(第三方)
dotnet add package EFCoreSecondLevelCacheInterceptor4. 验证安装
bash
# 查看已安装的包
dotnet list package
# 应看到类似输出:
# Microsoft.EntityFrameworkCore.SqlServer 8.0.0
# Microsoft.EntityFrameworkCore.Tools 8.0.0🔧 配置 EF Core
方法一:依赖注入(推荐 - Web 应用)
Program.cs 配置
csharp
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// 添加 DbContext
builder.Services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection"),
sqlOptions =>
{
// 启用重试策略(弹性连接)
sqlOptions.EnableRetryOnFailure(
maxRetryCount: 3,
maxRetryDelay: TimeSpan.FromSeconds(10),
errorNumbersToAdd: null);
// 命令超时(秒)
sqlOptions.CommandTimeout(30);
// 启用敏感数据日志(仅开发环境)
if (builder.Environment.IsDevelopment())
{
sqlOptions.EnableSensitiveDataLogging();
}
});
// 启用详细日志
if (builder.Environment.IsDevelopment())
{
options.LogTo(
Console.WriteLine,
new[] { DbLoggerCategory.Database.Command.Name },
LogLevel.Information);
}
});
var app = builder.Build();appsettings.json 配置
json
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=MyAppDb;Trusted_Connection=True;TrustServerCertificate=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.EntityFrameworkCore": "Information"
}
}
}方法二:DbContext 内部配置(控制台应用)
csharp
public class AppDbContext : DbContext
{
public DbSet<Product> Products => Set<Product>();
public DbSet<Category> Categories => Set<Category>();
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(
"Server=localhost;Database=MyAppDb;Trusted_Connection=True;",
options =>
{
options.EnableRetryOnFailure();
});
// 开发环境启用日志
#if DEBUG
optionsBuilder.LogTo(Console.WriteLine, LogLevel.Information);
optionsBuilder.EnableSensitiveDataLogging();
#endif
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 实体配置
modelBuilder.Entity<Product>(entity =>
{
entity.HasKey(e => e.Id);
entity.Property(e => e.Name).HasMaxLength(100);
});
}
}使用:
csharp
using var context = new AppDbContext();
var products = await context.Products.ToListAsync();方法三:工厂模式(Blazor / 后台服务)
csharp
// Program.cs
builder.Services.AddDbContextFactory<AppDbContext>(options =>
{
options.UseSqlServer(connectionString);
});
// 服务中使用
public class ProductService
{
private readonly IDbContextFactory<AppDbContext> _factory;
public ProductService(IDbContextFactory<AppDbContext> factory)
{
_factory = factory;
}
public async Task<List<Product>> GetProductsAsync()
{
await using var context = _factory.CreateDbContext();
return await context.Products.ToListAsync();
}
}适用场景:
- Blazor Server 应用
- 后台工作者
- 需要手动控制生命周期的场景
🗄️ 数据库连接字符串配置
SQL Server
Windows 身份验证
json
"Server=localhost;Database=MyAppDb;Trusted_Connection=True;TrustServerCertificate=True;"SQL Server 身份验证
json
"Server=localhost;Database=MyAppDb;User Id=sa;Password=YourPassword;TrustServerCertificate=True;"LocalDB(开发环境)
json
"Server=(localdb)\\mssqllocaldb;Database=MyAppDb;Trusted_Connection=True;"Azure SQL Database
json
"Server=tcp:yourserver.database.windows.net,1433;Initial Catalog=MyAppDb;Persist Security Info=False;User ID=admin;Password=yourpassword;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"PostgreSQL
json
"Host=localhost;Port=5432;Database=MyAppDb;Username=postgres;Password=yourpassword"高级配置:
json
"Host=localhost;Database=MyAppDb;Username=postgres;Password=pass;Pooling=true;Min Pool Size=0;Max Pool Size=100;Timeout=30"MySQL
json
"Server=localhost;Port=3306;Database=MyAppDb;Uid=root;Pwd=yourpassword;"SQLite
json
"DataSource=mydb.db"内存数据库(测试):
json
"DataSource=:memory:"⚙️ 高级配置选项
1. 查询跟踪行为
csharp
builder.Services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(connectionString);
// 默认所有查询都无追踪(适合只读场景多的应用)
options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
});2. 敏感数据日志
csharp
// ⚠️ 仅开发环境启用
if (environment.IsDevelopment())
{
options.EnableSensitiveDataLogging();
options.EnableDetailedErrors();
}输出示例:
Executed DbCommand (12ms) [Parameters=[@__id_0='1' (DbType = Int32)],
CommandType='Text', CommandTimeout='30']
SELECT [p].[Id], [p].[Name], [p].[Price]
FROM [Products] AS [p]
WHERE [p].[Id] = @__id_03. 慢查询阈值
csharp
options.LogTo(
Console.WriteLine,
new[] { DbLoggerCategory.Database.Command.Name },
LogLevel.Warning,
new LoggerExternalScopeProvider(),
TimeSpan.FromMilliseconds(1000) // 超过 1 秒的查询才记录
);4. DbContext 池化
csharp
// 提高高并发场景性能
builder.Services.AddDbContextPool<AppDbContext>(
options => options.UseSqlServer(connectionString),
poolSize: 128 // 池大小,默认 128
);性能提升:10-30%(高并发场景)
注意事项:
- ⚠️ 不能在
OnConfiguring中使用外部依赖 - ⚠️ 不适合使用实例状态的上下文
5. 拦截器(Interceptors)
csharp
// 自定义拦截器
public class QueryTagInterceptor : DbCommandInterceptor
{
public override InterceptionResult<DbDataReader> ReaderExecuting(
DbCommand command,
CommandEventData eventData,
InterceptionResult<DbDataReader> result)
{
// 为每个查询添加注释
command.CommandText = $"/* App: MyApp */ {command.CommandText}";
return base.ReaderExecuting(command, eventData, result);
}
}
// 注册拦截器
options.AddInterceptors(new QueryTagInterceptor());🌍 多数据库配置
根据环境切换数据库
csharp
var environment = builder.Environment.EnvironmentName;
if (environment == "Development")
{
options.UseSqlServer(builder.Configuration.GetConnectionString("DevDb"));
}
else if (environment == "Production")
{
options.UseSqlServer(builder.Configuration.GetConnectionString("ProdDb"),
sqlOptions =>
{
sqlOptions.EnableRetryOnFailure();
});
}支持多种数据库类型
csharp
public static class DbContextOptionsExtensions
{
public static DbContextOptionsBuilder ConfigureDatabase(
this DbContextOptionsBuilder options,
IConfiguration configuration)
{
var dbType = configuration["Database:Type"];
var connectionString = configuration["Database:ConnectionString"];
switch (dbType?.ToLower())
{
case "sqlserver":
options.UseSqlServer(connectionString);
break;
case "postgresql":
options.UseNpgsql(connectionString);
break;
case "mysql":
options.UseMySql(connectionString,
ServerVersion.AutoDetect(connectionString));
break;
case "sqlite":
options.UseSqlite(connectionString);
break;
default:
throw new InvalidOperationException($"Unsupported database type: {dbType}");
}
return options;
}
}
// 使用
builder.Services.AddDbContext<AppDbContext>(options =>
options.ConfigureDatabase(builder.Configuration));appsettings.json:
json
{
"Database": {
"Type": "SqlServer",
"ConnectionString": "Server=localhost;..."
}
}🔍 诊断与调试
1. 启用详细日志
csharp
options.LogTo(
Console.WriteLine,
new[]
{
DbLoggerCategory.Database.Command.Name, // SQL 命令
DbLoggerCategory.Query.Name, // 查询翻译
DbLoggerCategory.Model.Validation.Name // 模型验证
},
LogLevel.Debug);2. 查看生成的 SQL
csharp
// 方法 1:ToQueryString(不执行)
var sql = context.Products
.Where(p => p.Price > 100)
.ToQueryString();
Console.WriteLine(sql);
// 方法 2:实际执行并查看日志
var products = await context.Products
.Where(p => p.Price > 100)
.ToListAsync();
// 日志中会显示执行的 SQL3. MiniProfiler 集成
bash
dotnet add package MiniProfiler.EntityFrameworkCorecsharp
// Program.cs
builder.Services.AddMiniProfiler(options =>
{
options.RouteBasePath = "/profiler";
});
builder.Services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(connectionString);
options.UseMiniProfilerProfiledConnection();
});
// 访问 https://localhost:5001/profiler 查看性能分析🧪 测试环境配置
InMemory 数据库
bash
dotnet add package Microsoft.EntityFrameworkCore.InMemorycsharp
// 单元测试
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase(databaseName: "TestDb")
.Options;
await using var context = new AppDbContext(options);
// 注意:InMemory 不模拟真实数据库行为!SQLite 内存数据库(推荐)
csharp
var connection = new SqliteConnection("DataSource=:memory:");
connection.Open();
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseSqlite(connection)
.Options;
await using var context = new AppDbContext(options);
await context.Database.EnsureCreatedAsync();⚠️ 常见配置错误
1. 忘记安装工具包
错误:
bash
dotnet ef migrations add Initial
# Could not execute because the specified command or file was not found.解决:
bash
dotnet add package Microsoft.EntityFrameworkCore.Tools2. 连接字符串错误
错误:
A network-related or instance-specific error occurred...检查清单:
- ✅ 服务器地址是否正确
- ✅ 数据库名称是否存在
- ✅ 用户名密码是否正确
- ✅ 防火墙是否允许连接
3. 未配置依赖注入
错误:
Unable to resolve service for type 'AppDbContext'解决:
csharp
// 确保在 Program.cs 中注册
builder.Services.AddDbContext<AppDbContext>(...);4. 多线程访问 DbContext
错误:
A second operation was started on this context instance before a previous operation completed.解决:
- ✅ 使用 Scoped 生命周期
- ✅ 不要在线程间共享 DbContext
- ✅ 后台服务使用
IDbContextFactory
📊 配置检查清单
部署前确认:
- [ ] 连接字符串正确配置
- [ ] 生产环境禁用敏感数据日志
- [ ] 启用重试策略(云数据库)
- [ ] 设置合理的命令超时
- [ ] 配置连接池大小
- [ ] 添加健康检查
- [ ] 性能监控已配置
📚 延伸阅读
💡 小结
安装步骤:
- 安装 .NET SDK
- 创建项目
- 添加 NuGet 包
- 配置连接字符串
- 注册 DbContext
关键要点:
- ✅ 使用依赖注入(Web 应用)
- ✅ 区分开发和生产环境配置
- ✅ 启用适当的日志级别
- ✅ 考虑使用 DbContext 池化提升性能
下一步:创建你的第一个 DbContext!