Get Db context inside data access layer

杀马特。学长 韩版系。学妹 提交于 2021-02-07 21:38:55

问题


I have some problems with EF-Core that I'm trying to figure out.
I use the startup code in the MVC Core application to initalize the db context.
This is my DB context:

public class AccountsDBContext : DbContext
{
    public AccountsDBContext(DbContextOptions<AccountsDBContext> options)
        :base(options)
    {

    }

    // ...

}

And startup code:

 public void ConfigureServices(IServiceCollection services)
 {
        // Inject the account db
        services.AddDbContext<AccountsDBContext>(options =>
           options.UseMySQL(Configuration.GetConnectionString("AccountsStore")));

        // ...

In all the exampes I see the DB Context is a delivered via the constructor to the controller (I assume by dependency injection) and from there on to other entities\ layers.

 [Route("api/[controller]")]
 public class AccountsController : Controller
 {
    private AccountsDBContext _db;

    public AccountsController(AccountsDBContext context)
    {
        this._db = context;
    }

However, I'm not very fond of the idea that the db context will be a member at the controller.
I really prefer to get a hold of the db context in the data access layer instead of getting it passed into the repositories classes.
Is there a way to get the context inside the data access layer? (There is no IServiceCollection, IApplicationBuilder, IServiceScopeFactory there as far as I know)


回答1:


I Understand what you are trying to do. I have done exactly that. The key is to Create a static class in your DAL that uses the IServiceCollection. then in here you add your context here's mine and it works a treat My front end doesn't even know about entity framework, nethier does my business layer:

public static IServiceCollection RegisterRepositoryServices(this IServiceCollection services)
    {
        services.AddIdentity<ApplicationUser, IdentityRole<int>>(
            config => { config.User.RequireUniqueEmail = true;
                config.Cookies.ApplicationCookie.LoginPath = "/Account/Login";
                config.Cookies.ApplicationCookie.AuthenticationScheme = "Cookie";
                config.Cookies.ApplicationCookie.AutomaticAuthenticate = false;
                config.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents()
                {
                    OnRedirectToLogin = async ctx =>
                    {
                        if (ctx.Request.Path.StartsWithSegments("/visualjobs") && ctx.Response.StatusCode == 200)
                        {
                            ctx.Response.StatusCode = 401;
                        }
                        else
                        {
                            ctx.Response.Redirect(ctx.RedirectUri);
                        }
                        await Task.Yield();
                    }
                };
            }).AddEntityFrameworkStores<VisualJobsDbContext, int>()
          .AddDefaultTokenProviders();

        services.AddEntityFramework().AddDbContext<VisualJobsDbContext>();

        services.AddScoped<IRecruiterRepository, RecruiterRepository>();
        services.AddSingleton<IAccountRepository, AccountRepository>();

        return services;
    }

then in my service layer I have another static class. My service layer has a reference to the repository layer and I register the repository services here (bootstrapping the repository into the service layer), like so and then I do the same again in the UI:

Service layer code:

public static class ServiceCollectionExtensions
{
    public static IServiceCollection RegisterServices(this IServiceCollection services)
    {
        services.RegisterRepositoryServices();
        services.AddScoped<IRecruiterService, RecruiterService>();
        services.AddSingleton<IAccountService, AccountService>();

        return services;
    }
}

The Magic in the Repository Layer:

public partial class VisualJobsDbContext : IdentityDbContext<ApplicationUser, IdentityRole<int>, int>
{
    private IConfigurationRoot _config;

    public VisualJobsDbContext() { }

    public VisualJobsDbContext(IConfigurationRoot config, DbContextOptions<VisualJobsDbContext> options) : base(options)
    {
        _config = config;
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);

        optionsBuilder.UseSqlServer(@_config["ConnectionStrings:VisualJobsContextConnection"]);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {....



回答2:


Inject your repository/DAL implementation into the controller and have the DbContext injected into the repo constructor. The DI container will hook it all up as long as the appropriate classes are registered




回答3:


How about this?

DALAccount.cs

public class DALAccount
{
     private AccountsDBContext _db;
     public DALAccount(AccountsDBContext db)
     {
          _db = db;
     }
     public IQueryable<User> Get()
         => _db.User.AsQueryable();
}

Your Api

public class AccountsController : Controller
{
     private AccountsDBContext _db;

     public AccountsController(AccountsDBContext context)
     {
          this._db = context;
     }
     public IActionResult Index()
     {
          DALAccount dal = new DALAccount(_db);
          var list = dal.Get();
     }
}


来源:https://stackoverflow.com/questions/40862162/get-db-context-inside-data-access-layer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!