在同一个ASP.NET Core解决方案中,无法让两个DbContext与 EF Core和 SQL Server一起正常工作

编程语言 2026-07-09

两个 DbContext 在同一个基础设施项目中的两个独立数据库(如果这点重要,它们都在同一个命名空间内)。所有实体都在同一个领域项目中(每个数据库的实体在各自的命名空间里)。这两个数据库都没有同名的表。

尝试查询数据时的异常:

Microsoft.Data.SqlClient.SqlException (0x80131904): Invalid object name '[TABLE_NAME]'

(请查看底部的调用代码)。我搜索到的结果多为关于迁移的问题(例如未创建数据库),但这是一个DB-first项目,因此没有迁移。

下面是我用于依赖注入的相关服务代码。底部那个 DbContext 的实现能工作。在这个例子中,"DocumentLibrary" 会工作,但如果把底部改成 "HR",也能工作。这似乎表明问题并非出在数据库、连接字符串或实体配置上。

connectionString = builder.Configuration.GetConnectionString("HR") ?? throw new InvalidOperationException("Connection string 'HR' not found.");
builder.Services.AddDbContext<HrDbContext>(options =>
    // I've tried commenting out all the options except UseSqlServer() to narrow down the issues, but it had no effect
    options
        .UseSqlServer(connectionString)
        .EnableDetailedErrors()
        .UseLazyLoadingProxies()
);

connectionString = builder.Configuration.GetConnectionString("DocumentLibrary") ?? throw new InvalidOperationException("Connection string 'DocumentLibrary' not found.");
builder.Services.AddDbContext<DocumentLibraryDbContext>(options =>
    // I've tried commenting out all the options except UseSqlServer() to narrow down the issues, but it had no effect
    options
        .UseSqlServer(connectionString)
        .EnableDetailedErrors()
        .UseLazyLoadingProxies()
);

简化的 DbContext 文件。两者除了名称和实体之外完全相同:

public class HrDbContext : DbContext
{
    public HrDbContext(DbContextOptions<HrDbContext> options)
        : base(options)
    {
    }

    public DbSet<Employee> Employees => Set<Employee>();
    // other DbSets...

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);  // I've moved this to the top and bottom with no effect

        builder.ApplyConfiguration(new EmployeeConfiguration());
        // other entity configurations
    }
}

简化的示例实体配置:

public class EmployeeConfiguration : IEntityTypeConfiguration<Employee>
{
    public void Configure(EntityTypeBuilder<Employee> builder)
    {
        builder.HasKey(pk => pk.Id);
        builder.ToTable("Employee");
        // other configurations
    }
}

异常发生的测试页面:

// This is just a test for working through this issue. I know injecting a DbContext into a page is generally bad practice.
public class DbContextTestModel(HrDbContext hrDbContext, DocumentLibraryDbContext documentLibraryDbContext) : PageModel
{
    public async Task OnGet()
    {
        // works when it's the last DbContext declared, fails if it's first
        var doc = await documentLibraryDbContext.Documents.OrderBy(x => x.Id).FirstOrDefaultAsync();

        // works when it's the last DbContext declared, fails if it's first
        var employee = await hrDbContext.Employees.OrderBy(x => x.Id).FirstOrDefaultAsync();
    }
}

解决方案

问题在于对 connectionString 变量的重复使用。由于它在回调操作中被使用,不能保证第一次回调在第二次赋值之前发生。 (事实上很可能不会发生。)

为说明如下:

// This happens FIRST
connectionString = builder.Configuration.GetConnectionString("HR") ?? throw new InvalidOperationException("Connection string 'HR' not found.");

builder.Services.AddDbContext<HrDbContext>(options =>
    // This happens THIRD
    options
        .UseSqlServer(connectionString)
        .EnableDetailedErrors()
        .UseLazyLoadingProxies()
);

// This happens SECOND
connectionString = builder.Configuration.GetConnectionString("DocumentLibrary") ?? throw new InvalidOperationException("Connection string 'DocumentLibrary' not found.");

builder.Services.AddDbContext<DocumentLibraryDbContext>(options =>
    // This happens FOURTH
    options
        .UseSqlServer(connectionString)
        .EnableDetailedErrors()
        .UseLazyLoadingProxies()
);

这符合这样的模式:后者的连接总是能工作。因为前者最终使用了错误的连接字符串。

只需使用一个不同的变量:

// Self-contained HR connection
var hrConnectionString = builder.Configuration.GetConnectionString("HR") ?? throw new InvalidOperationException("Connection string 'HR' not found.");
builder.Services.AddDbContext<HrDbContext>(options =>
    options
        .UseSqlServer(hrConnectionString)
        .EnableDetailedErrors()
        .UseLazyLoadingProxies()
);

// Self-contained DocumentLibrary connection
var dlConnectionString = builder.Configuration.GetConnectionString("DocumentLibrary") ?? throw new InvalidOperationException("Connection string 'DocumentLibrary' not found.");
builder.Services.AddDbContext<DocumentLibraryDbContext>(options =>
    options
        .UseSqlServer(dlConnectionString)
        .EnableDetailedErrors()
        .UseLazyLoadingProxies()
);
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章