问题
I have a scenario wherein I have multiple connection strings defined under appsettings.json like this:
"ConnectionString": {
"ConnectionZone1": "Server=(localdb)\\mssqllocaldb;Database=Blogging;Trusted_Connection=True;",
"ConnectionZone2": "Server=localhost;Database=Blogging;Trusted_Connection=True;"
},
This I have registered in my startup.cs file as well:
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);
}
I have created Model and context classes using database first approach, and registered my context classes as follows:
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; }
and created two other context classes which inherits from the above main base class:
public class DbContextZone1 : BloggingContext
{
public DbContextZone1()
{
}
}
public class DbContextZone2 : BloggingContext
{
public DbContextZone2()
{
}
}
Now I have created my API controllers and am trying to call these context methods.
[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();
}
}
The issue is when I run my application it throws error that my context class should have parameterized constructor in order to pass options.
So in the DbContextZone1 and DbContextZone2 constructor which context options parameter will come?. I tried putting like this, but it never works and throws error when I call the API controller:
public class DbContextZone1 : BloggingContext
{
public DbContextZone1(DbContextOptions<BloggingContext> options)
: base(options)
{
}
}
public class DbContextZone2 : BloggingContext
{
public DbContextZone2(DbContextOptions<BloggingContext> options)
: base(options)
{
}
}
And this the error:
So any help or code ideas or suggestions in how to achieve multiple connections or make my code right?.
回答1:
From your appsettings.json,it seems that you want to connect to the same database in different server.You are no need to create a base DbContext,just inherits default DbContext like below:
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; }
}
And call the API Controller like below:
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();
}
回答2:
Change Your DbContext Cunstructors to this:
public class DbContextZone1 : BloggingContext
{
public DbContextZone1(DbContextOptions<DbContextZone1> options)
: base(options)
{
}
}
public class DbContextZone2 : BloggingContext
{
public DbContextZone2(DbContextOptions<DbContextZone2> options)
: base(options)
{
}
}
Update:
If you've got errors after changing your DbContext class is because you're trying to access default constructors like below:
using (var context = new DbContextZone1())
when there is no implemented default constructor in your classes. As you've registered your DbContext classes in .net core DI system, you just need to inject DbContextZone1 and DbContextZone2 in Controller's constructor, and then you can easily access to contexts. But before doing that you should add your DbSet to DbContext classes and change them to:
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;}
}
Note: You can keep your DbSets in BloggingContext and then access them via _context
in your controller but moving them like above makes your contexts isolated and gives single responsibility to the Contexts.
Now your Controller should be like this:
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();
}
来源:https://stackoverflow.com/questions/58017101/entity-framework-multiple-connections-error