时间:2018-04-28 07:05:57

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

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

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

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

的DbContext

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中的Configuration连接字符串。< / p>

有没有人能帮我理解如何在新的asp.net核心2中做到这一点?

此外,如果有人需要更多代码,我不介意分享我所拥有的代码,如果有人帮助他人的话。

提前致谢。

2 个答案:

答案 0 :(得分:0)

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

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

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 ???

答案 1 :(得分:0)

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

在阅读了很多文章之后,我想出了在租户初始化中获取主要DbContext的最佳方法DbContext是使用服务提供商将其作为注入依赖项来获取。

IServiceProvider serviceProvider

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();
}

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

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

它创建数据库并初始化我们需要的表,如语言,contries ......和公司one,从主DbContext的表Client获取所有信息。

这是一个多租户应用程序,asp.net核心2,代码的单一安装,一个主数据库和每个租户的一个数据库。每个租户都有不同的域名,因此我们使用主机来区分租户。

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