Multiple connection to DbContext in EFCore and .ne

2020-05-10 06:23发布

问题:

I have facing a problem to connecting to DBcontext with multiple connection. please help me out from this problem , here is me scenario .

  1. I have an Angular5 application and Webapi Controllers. I have 4 databases and Each database has different users .

  2. When 4 user are trying to connecting to their database at Same time through Webapi controller , that time all users are getting data from single database (instead of getting different database ) .

  3. When we try to Connecting one by one then data getting correctly .

Here is my sample code for dynamic connection .

Context Connectionstring :

 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
         #warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
          optionsBuilder.UseSqlServer(LoginController.ConnectionString);

    }

Controler API :

public IEnumerable<object> Getvendordetails([FromBody] dynamic id)
    {
        if (Request != null)
        {
            LoginController.DynamicDbname = Request.Headers["Connectionstring"];
        }
        ContextEntity obj = new ContextEntity();
    }

Here LoginController.DynamicDbname is Static variable .

EDIT CODE :

Controller :

    namespace AngularDotnetCore.Controllers
   {
     [Route("api/[controller]")]
    public class HomeController : Controller
    {
       private readonly IHttpContextAccessor httpContext;
       private ContextEntity db;
      public HomeController(IHttpContextAccessor _httpContext)
    {

        this.httpContext = _httpContext;
        db = new ContextEntity(httpContext);

    }
    [HttpPost("GetVendors")]
    public IEnumerable<object> Getvendordetails([FromBody] dynamic id)
    {
        //string DynamicConnection = Request.Headers["Connection"];
        db = new ContextEntity(httpContext);
        return db.Vendors;
    }

    [HttpGet("GetItems")]
    public IEnumerable<object> GetItems()
    {
        //string DynamicConnection = Request.Headers["Connection"];
        db = new ContextEntity(httpContext);
        return db.Items;
    }

}

}

DBContext :

   private readonly HttpContext httpContext;
  public ContextEntity(IHttpContextAccessor httpContextAccessor)
    : base()
    {
        httpContext = httpContextAccessor.HttpContext;
    }
     protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
   {
       var connection = httpContext.Request.Headers["Connection"];
      optionsBuilder.UseSqlServer(connection);

   }

I have pass httpcontext parameter to Dbcontext base class for each API Request.

Please help me on this problem , if my code is wrong please suggest me in good way.

Thanks Victor.A

回答1:

If LoginController.DynamicDbName is a static variable, It is shared between all your requests. It means Your API is overrading this value on each request and all users are using the last one to create dbconnection. Make it non static and create new instance of your login contoller for each request and inject It to all related services like DbContext. Then your problem will disappear.

If you are using migrations from command line, you might need to upgrade EF Core version to 2.1 (or 2.2, I can't remeber) because 2.0 has some problem with injecting not-standard classes/interfaces to your Context



回答2:

For accessing http header from DbContext, you could try IHttpContextAccessor, there is no need to refer LoginContoller.

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    private readonly HttpContext httpContext;
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IHttpContextAccessor httpContextAccessor)
        : base(options)
    {
        httpContext = httpContextAccessor.HttpContext;
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var connection = httpContext.Request.Headers["Connectionstring"];
        optionsBuilder.UseSqlServer(connection);
    }       
}

Edit It seems you initlize the ContextEntity in the controller instead of using DI, if so, try passing the connectionstring directly instead of IHttpContextAccessor.

namespace AngularDotnetCore.Controllers
   {
 [Route("api/[controller]")]
public class HomeController : Controller
{      
   private ContextEntity db;
  public HomeController()
{

    var connection = Request.Headers["Connection"];
    db = new ContextEntity(connection);

}
  }

DbContext

private readonly string _connection;
  public ContextEntity(string connection)
: base()
{
    _connection = connection;
}
 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
   {
  optionsBuilder.UseSqlServer(_connection);

    }