Skip to content

安装与配置 EF Core ​

完整的 NuGet 包安装、依赖注入和数据库配置指南

📦 安装 EF Core ​

1. 安装 .NET SDK ​

首先确保安装了 .NET 8/9/10 SDK:

bash
# 检查版本
dotnet --version

# 应显示: 8.0.x, 9.0.x 或 10.0.x

下载 .NET SDK

2. 创建项目 ​

bash
# 创建 Web API 项目
dotnet new webapi -n EfCoreDemo
cd EfCoreDemo

# 或创建控制台项目
dotnet new console -n EfCoreDemo
cd EfCoreDemo

3. 安装 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 EFCoreSecondLevelCacheInterceptor

4. 验证安装 ​

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_0

3. 慢查询阈值 ​

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();
// 日志中会显示执行的 SQL

3. MiniProfiler 集成 ​

bash
dotnet add package MiniProfiler.EntityFrameworkCore
csharp
// 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.InMemory
csharp
// 单元测试
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.Tools

2. 连接字符串错误 ​

错误:

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

📊 配置检查清单 ​

部署前确认:

  • [ ] 连接字符串正确配置
  • [ ] 生产环境禁用敏感数据日志
  • [ ] 启用重试策略(云数据库)
  • [ ] 设置合理的命令超时
  • [ ] 配置连接池大小
  • [ ] 添加健康检查
  • [ ] 性能监控已配置

📚 延伸阅读 ​


💡 小结 ​

安装步骤:

  1. 安装 .NET SDK
  2. 创建项目
  3. 添加 NuGet 包
  4. 配置连接字符串
  5. 注册 DbContext

关键要点:

  • ✅ 使用依赖注入(Web 应用)
  • ✅ 区分开发和生产环境配置
  • ✅ 启用适当的日志级别
  • ✅ 考虑使用 DbContext 池化提升性能

下一步:创建你的第一个 DbContext!

基于 MIT 许可发布