【问题标题】:asp.net core access dbcontext within classasp.net核心访问类内的dbcontext
【发布时间】:2018-04-28 07:05:56
【问题描述】:

我有一个 Asp.net core 2 应用程序,我在其中配置了一个带有存储库模式和工作单元的 dbContext。

一切正常,我可以在控制器中访问 UnitOfWork 并获取数据。

我正在尝试访问中间件中的上下文以及另一个项目中的类,但我真的不知道哪种方法是最好的。

数据库上下文

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

    public DbSet<Blog> Blogs { get; set; }
    ...
}

启动

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddDbContext<BloggingContext>(options => options.UseMySQL(configuration.GetConnectionString("DefaultDb")));

    services.AddScoped<IBloggingContext, BloggingContext>();
    services.AddTransient<IUnitOfWork, UnitOfWork>();
    ...
}

中间件

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    ...
    app.UseMyMiddleware();
    ...
}

public class MyMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IConfiguration _configuration;
    private readonly IMemoryCache _memoryCache;

    public MyMiddleware(RequestDelegate next, IConfiguration configuration, IMemoryCache memoryCache)
    {
        _next = next;
        _configuration = configuration;
        _memoryCache = memoryCache;
    }

    public Task Invoke(HttpContext httpContext)
    {
        ...
        HERE I NEED TO ACCESS DATABASE

        ...
        return _next(httpContext);
    }
}

public static class MyMiddlewareExtensions
{
    public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<MyMiddleware>();
    }
}

我在 Invoke 函数中所做的是:

var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
optionsBuilder.UseMySQL(_configuration.GetConnectionString("DefaultDb"));

using (var dbContext = new BloggingContext(optionsBuilder.Options))
{
    var blog = dbContext.Blogs.FirstOrDefault();
    ...
}

我很确定这不是最好的方法。此外,理想的方法是像我在控制器中访问一样直接访问 UnitOfWork,但我不知道这是否可能。

另外,我需要在不同项目的一个类中访问相同的 DbCONtext,在这种情况下我还有另一个问题:如何访问我的 web 项目的 appsettings.json 中的配置连接字符串。

谁能帮助我了解如何在新的 asp.net core 2 中做到这一点?

另外,如果有人需要更多代码,我不介意分享我所拥有的,如果它可以帮助其他人。

提前致谢。

【问题讨论】:

    标签: asp.net-core-2.0 dbcontext unit-of-work


    【解决方案1】:

    我找到了 MiddleWare 的解决方案,但没有找到其他项目中的类。

    您只需将 IUnitOfWork 注入到中间件的 Invoke 中即可。

    public class MyMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IConfiguration _configuration;
        private readonly IMemoryCache _memoryCache;
    
        public MyMiddleware(RequestDelegate next, IConfiguration configuration, 
    IMemoryCache memoryCache)
        {
            _next = next;
            _configuration = configuration;
           _memoryCache = memoryCache;
        }
    
        public Task Invoke(HttpContext httpContext, IUnitOfWork unitOfWork) 
        {
            var myData = _unitoOfWork.Blogs.GetFirst();
            ...
            return _next(httpContext);
        }
    }
    

    当我为数据库做种时,我仍然有在我的另一个 DbContext 中调用 DbContext 的问题。

    我有另一个 DbContext,我正在动态创建。这是一个多租户应用程序,我需要在租户第一次访问系统时创建租户数据库,并为该数据库播种,但我必须从主 DbContext 中播种。

    public class DbContextTenant : IdentityDbContext<ApplicationUser, ApplicationRole, int>, IDbContextTenant
    {
        private readonly string _connectionString;
    
        public DbContextTenant(DbContextOptions<SpzContextClient> options, IHttpContextAccessor contextAccessor) : base(options)
        {
            var tenantId = (int)contextAccessor.HttpContext.Items["TenantId"];
            _connectionString = contextAccessor.HttpContext.Items["DbString"].ToString();
    
            SEED DATABASE
            HERE IS WHERE I NEED TO CALL THE MAIN DBCONTEXT
        }
    

    我怎样才能在那里调用主 DbCONtext???

    【讨论】:

      【解决方案2】:

      嗯,这看起来像是一个博客,而不是一个 stackoverflow 问题...我正在回答我自己的问题,但如果它只能帮助一个人...这是一个非常富有成效的星期天。

      在阅读了很多文章后,我发现在租户 DbContext 的初始化中获取主 DbContext 的最佳方法是使用 Service Provider 将其作为注入依赖项获取。

      IServiceProvider 服务提供者

      public class DbContextTenant : IdentityDbContext<ApplicationUser, ApplicationRole, int>, IDbContextTenant
      {
          private readonly string _connectionString;
      
          public DbContextTenant(DbContextOptions<SpzContextClient> options, 
      IHttpContextAccessor contextAccessor, IServiceProvider serviceProvider) : base(options)
          {
              var tenantId = (int)contextAccessor.HttpContext.Items["TenantId"];
              _connectionString = contextAccessor.HttpContext.Items["DbString"].ToString();
      
              TenantInitialization.Initialize(serviceProvider, this, tenantId);
          }
      

      如您所见,我将 serviceProvider 传递给租户数据库的初始化。这样我就可以在另一个 DbCONtext 的初始化中使用主 DbContext,即访问所有租户的那个。

      初始化是这样的。

      public static void Initialize(IServiceProvider serviceProvider, DbContextTenant context, int tenantId)
      {
          if (((RelationalDatabaseCreator) context.GetService<IDatabaseCreator>()).Exists()) return;
      
          context.Database.EnsureCreated();
      
          LanguageInitialization.Initialize(context);
          CountryInitialization.Initialize(context);
      
          using (var DbContext = serviceProvider.GetRequiredService<DbContext>())
          {
              CompanyInitialization.Initialize(context, contextMaster, tenantId);
          }
      
          context.SaveChanges();
      }
      

      如果您知道更好的方法,请告诉我。

      如果数据库已经存在,它不会做任何事情。这只是第一次有人访问租户站点,因此我们可以将租户添加到数据库中,应用程序自己创建数据库。这种方式很容易创建新的客户(租户),只需在主数据库的客户表中添加一行即可。

      它创建数据库并初始化我们需要的表,如语言、国家……和公司之一,从主 DbContext 的表 Client 中获取所有信息。

      这是一个多租户应用,asp.net core 2,代码单次安装,一个主库,每个租户一个库。每个租户有不同的域,所以我们使用主机来区分租户。

      我遇到了很多问题,所以我分享这个以防有人需要。我很想拥有我现在拥有的所有信息。如果您有任何问题或需要任何代码,我很乐意分享您需要的任何内容。

      【讨论】:

        猜你喜欢
        • 2020-09-26
        • 2019-02-01
        • 2018-11-21
        • 2021-04-27
        • 1970-01-01
        • 2017-10-22
        • 1970-01-01
        • 2023-01-28
        • 1970-01-01
        相关资源
        最近更新 更多