Entity Framework 多个连接错误

Entity Framework Multiple Connections Error

我有一个场景,其中我在 appsettings.json 下定义了多个连接字符串,如下所示:

"ConnectionString": {
    "ConnectionZone1": "Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;",
    "ConnectionZone2": "Server=localhost;Database=Blogging;Trusted_Connection=True;"
},

这个我也在我的 startup.cs 文件中注册了:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<DbContextZone1>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("ConnectionZone1")));

        services.AddDbContext<DbContextZone2>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("ConnectionZone2")));

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

我使用数据库优先方法创建了模型和上下文 classes,并按如下方式注册了我的上下文 classes:

public partial class BloggingContext : DbContext
{
    public BloggingContext()
    {
    }

    public BloggingContext(DbContextOptions<BloggingContext> options)
        : base(options)
    {
    }

    public virtual DbSet<Blog> Blog { get; set; }
    public virtual DbSet<Post> Post { get; set; }

并创建了另外两个上下文 classes 继承自上述主要基础 class:

public class DbContextZone1 : BloggingContext
{
    public DbContextZone1()
    {
    }        
}

public class DbContextZone2 : BloggingContext
{
    public DbContextZone2()
    {

    }
}

现在我已经创建了 API 控制器并尝试调用这些上下文方法。

[HttpGet]
    public async Task<ActionResult<IEnumerable<object>>> GetItems()
    {
        if (alternate)
        {
            alternate = false;
            using (var context = new DbContextZone1())
            {
                return await context.Blog.ToListAsync();
            }
        }

        using(var context = new DbContextZone2())
        {
            return await context.Post.ToListAsync();
        }            
    }

问题是当我 运行 我的应用程序抛出错误时,我的上下文 class 应该有参数化构造函数才能传递选项。

那么在 DbContextZone1 和 DbContextZone2 构造函数中,哪个上下文选项参数会来?。我试过这样放置,但是当我调用 API 控制器时它永远不会工作并抛出错误:

public class DbContextZone1 : BloggingContext
{
    public DbContextZone1(DbContextOptions<BloggingContext> options)
        : base(options)
    {
    }        
}

public class DbContextZone2 : BloggingContext
{
    public DbContextZone2(DbContextOptions<BloggingContext> options)
        : base(options)
    {

    }
}

这是错误:

那么关于如何实现多个连接或使我的代码正确的任何帮助或代码想法或建议?

将您的 DbContext Cunstructors 更改为:

public class DbContextZone1 : BloggingContext
{
    public DbContextZone1(DbContextOptions<DbContextZone1> options)
        : base(options)
    {
    }        
}

public class DbContextZone2 : BloggingContext
{
    public DbContextZone2(DbContextOptions<DbContextZone2> options)
        : base(options)
    {

    }
}

更新:

如果您在更改 DbContext 后出现错误 class 是因为您正在尝试访问如下所示的默认构造函数:

using (var context = new DbContextZone1())

当您的 classes 中没有实现默认构造函数时。由于您已经在.net core DI系统中注册了DbContext classes,您只需要在Controller的构造函数中注入DbContextZone1和DbContextZone2,然后您就可以轻松访问上下文。但在这样做之前,您应该将 DbSet 添加到 DbContext classes 并将它们更改为:

public class DbContextZone1 : BloggingContext
{
    public DbContextZone1(DbContextOptions<DbContextZone1> options)
        : base(options)
    { }

    public virtual DbSet<Blog> Blogs { get; set;}
}

public class DbContextZone2 : BloggingContext
{
    public DbContextZone2(DbContextOptions<DbContextZone2> options)
        : base(options)
    { }

    public virtual DbSet<Post> Posts { get; set;}
}

注意:您可以将 DbSet 保留在 BloggingContext 中,然后通过控制器中的 _context 访问它们,但是像上面那样移动它们会使您的上下文隔离并赋予上下文单一责任。

现在你的控制器应该是这样的:

private readonly DbContextZone1 _context1;
private readonly DbContextZone2 _context2;
public MyController(DbContextZone1 context1, DbContextZone2 context2)
{
    _context1 = context1;
    _context2 = context2;
}

[HttpGet]
public async Task<ActionResult<IEnumerable<object>>> GetItems()
{
    if (alternate)
    {
        alternate = false;
        return await _context1.Blogs.ToListAsync();
    }
    return await _context2.Posts.ToListAsync();
}

从你的 appsettings.json 看来,你想在不同的 server.You 连接到同一个数据库不需要创建基础 DbContext,只需继承默认的 DbContext,如下所示:

public class DbContextZone1 : DbContext
{
    public DbContextZone1(DbContextOptions<DbContextZone1> options)
        : base(options)
    {
    }
    public virtual DbSet<Blog> Blog { get; set; }
}
public class DbContextZone2 :DbContext
{
    public DbContextZone2(DbContextOptions<DbContextZone2> options)
        : base(options)
    {
    }
    public virtual DbSet<Post> Post { get; set; }
}

然后像下面这样调用 API 控制器:

private readonly DbContextZone1 _context1;
private readonly DbContextZone2 _context2;
    public ABCController(DbContextZone1 context1, DbContextZone2 context2)
    {
        _context1 = context1;
        _context2 = context2;
    }
    [HttpGet]
    public async Task<ActionResult<IEnumerable<object>>> GetItems()
    {
        //....
        if (alternate)
        {
            alternate = false;
            return await _context1.Blog.ToListAsync();
        }
        return await _context2.Post.ToListAsync();
    }