实体框架多重连接错误

时间:2019-09-19 18:32:55

标签: asp.net-core-webapi ef-core-2.2

在我的情况下,我在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);
    }

我已经使用数据库优先方法创建了Model和context类,并按如下方式注册了我的context类:

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; }

并创建了另外两个上下文类,它们从上述主要基类继承:

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();
        }            
    }

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

enter image description here

因此在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)
    {

    }
}

这是错误: enter image description here

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

2 个答案:

答案 0 :(得分:1)

从您的appsettings.json文件中,您似乎想连接到不同服务器上的同一数据库。您无需创建基本的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();
    }

答案 1 :(得分:0)

将您的DbContext Cunstructor更改为此:

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

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

    }
}

更新

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

using (var context = new DbContextZone1())

当您的类中没有实现的默认构造函数时。在.net核心DI系统中注册DbContext类后,只需将DbContextZone1和DbContextZone2注入Controller的构造函数中,即可轻松访问上下文。但是在此之前,您应该将DbSet添加到DbContext类并将其更改为:

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();
}