问题
Postgres database has multiple schemes like company1, company2, ... companyN
Browser sends cookie containing scheme name . Data access operations should occur in this scheme. Web application user can select different scheme. In this case different cookie value is set.
Npgsql EF Core Data provider is used.
ASP NET MVC 5 Core application registers factory in StartUp.cs :
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddScoped<IEevaContextFactory, EevaContextFactory>();
....
Home controller tries to use it:
public class HomeController : EevaController
{
public ActionResult Index()
{
var sm = new SchemeManager();
sm.PerformInsert();
....
This throws exception since factory member is null. How to fix this ?
public interface IEevaContextFactory
{
EevaContext Create();
}
public class EevaContextFactory : IEevaContextFactory
{
private IHttpContextAccessor httpContextAccessor;
private IConfiguration configuration;
public EevaContextFactory(IHttpContextAccessor httpContextAccessor, IConfiguration configuration)
{
this.httpContextAccessor = httpContextAccessor;
this.configuration = configuration;
}
public EevaContext Create()
{
var builder = new DbContextOptionsBuilder<EevaContext>();
var pathbase = httpContextAccessor.HttpContext.Request.PathBase.Value;
var scheme = httpContextAccessor.HttpContext.Request.Cookies["Scheme"];
var csb = new NpgsqlConnectionStringBuilder()
{
Host = pathbase,
SearchPath = scheme
};
builder.UseNpgsql(csb.ConnectionString);
return new EevaContext(builder.Options);
}
}
Scheme data acess methods:
public class SchemeManager
{
readonly IEevaContextFactory factory;
public SchemeManager(IEevaContextFactory factory)
{
this.factory = factory;
}
public SchemeManager()
{
}
public void PerformInsert()
{
using (var context = factory.Create())
{
var commandText = "INSERT into maksetin(maksetin) VALUES (CategoryName)";
context.Database.ExecuteSqlRaw(commandText);
}
}
}
回答1:
var sm = new SchemeManager()
... will call the no-parameter constructor on SchemeManager so the IEevaContextFactory is not injected. You should inject your factory into your controller and pass it into your SchemeManager.
Remove your no-parameter constructor. It's not needed.
public class HomeController : EevaController
{
private IEevaContextFactor eevaFactory;
public HomeController(IEevaContextFactory factory)
{
eevaFactory = factory;
}
public ActionResult Index()
{
var sm = new SchemeManager(eevaFactory);
sm.PerformInsert();
....
}
}
Your other option is to put the SchemeManager in the DI container and then the DI container will auto-resolve IEevaContextFactory on the constructor and then just inject SchemeManager into your controller.
Either way, remove that no-parameter constructor.
来源:https://stackoverflow.com/questions/65478936/create-database-context-from-cookie-and-base-path-in-entity-framework-core