问题描述
我有一个Asp.net core 2应用程序,在其中配置了带有存储库模式和工作单元的dbContext.
一切正常,我可以在控制器内访问UnitOfWork并获取数据.
我试图访问中间件中的上下文以及另一个项目中的类,但是我真的不知道哪种方法是最好的.
DbContext
公共类BloggingContext:DbContext{公共BloggingContext(DbContextOptions< BloggingContext>选项):base(选项){}公共DbSet< Blog>博客{get;放;}...}
启动
public void ConfigureServices(IServiceCollection服务){...services.AddDbContext< BloggingContext>(options => options.UseMySQL(configuration.GetConnectionString("DefaultDb"))));services.AddScoped< IBloggingContext,BloggingContext>();services.AddTransient< IUnitOfWork,UnitOfWork>();...}
中间件
public void Configure(IApplicationBuilder应用程序,IHostingEnvironment env){...app.UseMyMiddleware();...}公共类MyMiddleware{私有只读RequestDelegate _next;私有只读IConfiguration _configuration;私有只读IMemoryCache _memoryCache;公共MyMiddleware(下一个RequestDelegate,IConfiguration配置,IMemoryCache memoryCache){_next =下一个;_configuration =配置;_memoryCache = memoryCache;}公共任务调用(HttpContext httpContext){...在这里我需要访问数据库...返回_next(httpContext);}}公共静态类MyMiddlewareExtensions{公共静态IApplicationBuilder UseMyMiddleware(此IApplicationBuilder构建器){返回builder.UseMiddleware< MyMiddleware>();}}
我在Invoke函数中正在执行的操作是:
var optionsBuilder = new DbContextOptionsBuilder< BloggingContext>();optionsBuilder.UseMySQL(_configuration.GetConnectionString("DefaultDb"));使用(var dbContext = new BloggingContext(optionsBuilder.Options)){var blog = dbContext.Blogs.FirstOrDefault();...}
我很确定这不是最好的方法.同样,理想的方式是访问,就像我在控制器中访问一样,直接访问不带UnitOfWork的设备,但我不知道这样做是否可行.
此外,我需要访问其他项目中的类中的同一DbCOntext,在这种情况下,我还有另一个问题:如何访问Web项目的appsettings.json中的配置连接字符串./p>
有人可以帮助我理解在新的asp.net核心2中如何做到这一点吗?
此外,如果某人需要更多代码,那么我不介意分享我对他人有帮助的东西.
提前谢谢.
好吧,这看起来像是一个博客,而不是stackoverflow问题……我在回答我自己的问题,但如果它只能帮助一个人..这是一个非常富有成效的星期天.
阅读大量文章后,我想出了在租户DbContext初始化中获取主要DbContext的最佳方法是使用服务提供商将其作为注入依赖项获得.
IServiceProvider serviceProvider
公共类DbContextTenant:IdentityDbContext< ApplicationUser,ApplicationRole,int> ;, IDbContextTenant{私有只读字符串_connectionString;公共DbContextTenant(DbContextOptions< SpzContextClient>选项,IHttpContextAccessor contextAccessor,IServiceProvider serviceProvider):基础(选项){var tenantId =(int)contextAccessor.HttpContext.Items ["TenantId"];_connectionString = contextAccessor.HttpContext.Items ["DbString"].ToString();TenantInitialization.Initialize(serviceProvider,this,tenantId);}
如您所见,我将serviceProvider传递给租户数据库的初始化.这样,我可以在其他DbCOntext的初始化中使用主DbContext,该DbCOntext可以访问所有租户.
初始化将是这样的.
public静态void Initialize(IServiceProvider serviceProvider,DbContextTenant上下文,int tenantId){如果((((RelationalDatabaseCreator)context.GetService< IDatabaseCreator>()).Exists())返回;context.Database.EnsureCreated();LanguageInitialization.Initialize(context);CountryInitialization.Initialize(context);使用(var DbContext = serviceProvider.GetRequiredService< DbContext>()){CompanyInitialization.Initialize(context,contextMaster,tenantId);}context.SaveChanges();}
如果您知道更好的方法,请告诉我.
如果数据库已经存在,则它什么都不做.这仅是首次有人访问租户站点,因此我们可以将租户添加到数据库中,然后应用程序将创建数据库本身.这种方法很容易创建新的客户端(租户),只需在主数据库的clients表中添加一行即可.
它创建数据库并初始化我们需要的表,例如语言,竞争...以及公司之一,并从主DbContext的表Client中获取所有信息.
这是一个多租户应用程序,asp.net核心2,单次安装代码,每个租户一个主数据库和一个数据库.每个租户都有一个不同的域,因此我们使用主机来区分租户.
我遇到了很多问题,因此,如果有人需要它,我将与大家分享.我很想拥有我现在拥有的所有信息.如果您有任何疑问或需要任何代码,我很乐意与您分享所需的内容.
I have an Asp.net core 2 application where I've configued a dbContext with a repository pattern and unit of work.
Everything works fine, I can access the UnitOfWork within a controller and get data.
I'm trying to access the context within a Middleware and also a class in another project, but I don't really know which is the best way.
DbContext
public class BloggingContext : DbContext
{
public BloggingContext(DbContextOptions<BloggingContext> options)
:base(options)
{ }
public DbSet<Blog> Blogs { get; set; }
...
}
Startup
public void ConfigureServices(IServiceCollection services)
{
...
services.AddDbContext<BloggingContext>(options => options.UseMySQL(configuration.GetConnectionString("DefaultDb")));
services.AddScoped<IBloggingContext, BloggingContext>();
services.AddTransient<IUnitOfWork, UnitOfWork>();
...
}
Middleware
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>();
}
}
What I'm doing inside the Invoke function is:
var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
optionsBuilder.UseMySQL(_configuration.GetConnectionString("DefaultDb"));
using (var dbContext = new BloggingContext(optionsBuilder.Options))
{
var blog = dbContext.Blogs.FirstOrDefault();
...
}
I'm pretty sure this is not the best way. Also the ideal way would be accesing like I access in a controller, directly to the UnitOfWork without, but I don't know if this is possible.
Also, I need to access to the same DbCOntext within a class in a different project, and in that case I have another problem: how to access the Configuration connection string which is in the appsettings.json of my web project.
Could anyone help me understanding how to do this in the new asp.net core 2?
Also, if someone needs more code I don't mind sharing what I have if it helps others.
Thanks in advance.
Well, this looks like a blog instead of a stackoverflow question...I'm asnwering my own questions, but if it can help just one person...It has been a very productive Sunday.
After reading a lot of articles I figure out the best way to get the main DbContext in the initialization of the tenant DbContext is using the Service Provider to get it as injected dependency.
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);
}
As you can see I pass the serviceProvider to the initialization of the tenant database. This way I can use the main DbContext in the initialization of the other DbCOntext, the one accessing all the tenants.
The initialization would be something like this.
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();
}
If you know a better way of doing this, please let me know.
If the database already exists, it diesn't do anything. This is only for the first time someone access to the tenant site, so we can just add the tenant to the database and the application creates the database itself. This way is really easy to create new clients (tenants), just adding a line to the clients table of the main database.
It creates the database and initialize the tables we need to, like languages, contries...and the company one, getting all the info from the table Client of main DbContext.
This is a multi-tenant application, asp.net core 2, single instalation of the code, one main database and one database for each tenant. Each tenant has a different domain, so we use the host to difference between tenants.
I have had a lot of issues to get here, so I'm sharing this in case someone needs it. I'd have loved to have all the info I have now. If you have any questions or need any code, I'd love to share whatever you need.
这篇关于类内的asp.net核心访问dbcontext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!