在我们的项目中我们有时候需要在我们的项目中建设DbContext,并且这些DbContext之间有明明的边界,好比系统中两个DbContext一个是和整个数据库的权限相关的内容而别的一个DbContext则主要是和详细业务相关的内容,这两个部门互相之间可以分隔,那么这个时候我们就可以在我们的项目中建设两个差异的DbContext,然后别离注入进去,虽然这两个DbContext可以共用一个ConnectionString,也可以别离利用差异的DbContext,这个需要按照差异的需要来确定,在我们成立完了差异的DbContext的时候,我们就需要别离将每一个DbContext修改的内容迁移到数据库内里去,这个就涉及到数据库Migration的问题了,所以整篇文章主要环绕如何建设多个DbContext和每个DbContext的Migration的问题。
下面我们通过代码来建设两个差异的DbContext
1 建设AuthorityDbContextpublic class AuthorityDbContext : AbpZeroDbContext<Tenant, Role, User, AuthorityDbContext> { /* Define a DbSet for each entity of the application */ public DbSet<UserMapping> UserMappings { get; set; } public SunlightDbContext(DbContextOptions<SunlightDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.ApplyConfiguration(new TenantConfiguration()); // 请在此处填写所有与详细数据库无关的 Model 调解,确保单位测试可以包围 if (Database.IsInMemory()) return; } }
这个DbContext主要用来做一些和身份验证以及权限相关的操纵,这里只是界说了一个最简朴的布局,后头的一个DbContext就是详细业务相关的内容,在我们的项目中,我们两个DbContext会利用沟通的毗连字符串。
2 IDesignTimeDbContextFactory接话柄现/// <summary> /// 用于 EF Core Migration 时建设 DbContext,数据库毗连信息来自 XXX.Dcs.WebHost 项目 appsettings.json /// </summary> public class AuthorityDesignTimeDbContextFactory : IDesignTimeDbContextFactory<AuthorityDbContext> { private const string DefaultConnectionStringName = "Default"; public SunlightDbContext CreateDbContext(string[] args) { var configuration = AppConfigurations.Get(WebContentDirectoryFinder.CalculateContentRootFolder()); var connectString = configuration.GetConnectionString(DefaultConnectionStringName); var builder = new DbContextOptionsBuilder<SunlightDbContext>(); builder.UseSqlServer(connectString); return new SunlightDbContext(builder.Options); } }
在相识这段代码之前,你可以先相识一下这个到底是做什么用的,就像注释内里说的,当我们利用EFCore Migration的时候,这里会默认读取WebHost项目内里的appsettings.json内里的Default设置的毗连字符串。
{ "ConnectionStrings": { "Default": "Server=XXXX,XX;Database=XXXX;User Id=XXXX;Password=XXXX;", "DcsEntity": "Server=XXXX,XX;Database=XXXX;User Id=XXXX;Password=XXXX;" }, "Redis": { "Configuration": "127.0.0.1:XXXX", "InstanceName": "XXXX-Sales" }, "App": { "ServerRootAddress": "http://localhost:XXXX/", "ClientRootAddress": "http://localhost:XXXX/", "CorsOrigins": "http://localhost:XX,:XX,:XX" }, "Kafka": { "BootstrapServers": "127.0.0.1:XX", "MessageTimeoutMs": 5000, "Topics": { "CustomerAndVehicleEvent": "XXXX-customer-update", "AddOrUpdateProductCategoryEvent": "XXXX-add-update-product-category", "AddOrUpdateDealerEvent": "XXXX-add-update-dealer", "ProductUpdateEvent": "XXXX-product-update", "VehicleInformationUpdateStatusEvent": "XXXX-add-update-vehicle-info", "AddCustomerEvent": "cowin-add-customer" } }, "Application": { "Name": "XXXX-sales" }, "AppSettings": { "ProductSyncPeriodMi": 60, "DealerSyncPeriodMi": 60 }, "Eai": { "Authentication": { "Username": "2XXX2", "Password": "XXXX" }, "Services": { "SapFinancial": "http://XXXX:XXXX/OSB_MNGT/Proxy/XXXX" } }, "DependencyServices": { "BlobStorage": "http://XXXX-XXXX/" }, "Authentication": { "JwtBearer": { "IsEnabled": true, "Authority": "http://XXXX/", "RequireHttpsMetadata": false } }, "Sentry": { "IncludeRequestPayload": true, "SendDefaultPii": true, "MinimumBreadcrumbLevel": "Debug", "MinimumEventLevel": "Warning", "AttachStackTrace": true }, "Logging": { "LogLevel": { "Default": "Warning" } } }
3 DB Migration