日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

EntityFramework Core如何映射动态模型?

發(fā)布時(shí)間:2023/12/4 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 EntityFramework Core如何映射动态模型? 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
【導(dǎo)讀】本文我們來探討下映射動(dòng)態(tài)模型的幾種方式,相信一部分童鞋項(xiàng)目有這樣的需求,比如每天/每小時(shí)等生成一張表,此種動(dòng)態(tài)模型映射非常常見,經(jīng)我摸索,這里給出每一步詳細(xì)思路,希望能幫助到?jīng)]有任何頭緒的童鞋

本文以.NET Core 3.1控制臺(tái),同時(shí)以SQL Server數(shù)據(jù)庫作為示例演示(其他數(shù)據(jù)庫同理照搬),由于會(huì)用到內(nèi)置APi,因版本不同可能比如構(gòu)造函數(shù)需略微進(jìn)行調(diào)整即可。

注:雖為示例代碼,但我將其作為實(shí)際項(xiàng)目皆已進(jìn)行封裝,基本完全通用。本文略長(約5334字),請耐心。

動(dòng)態(tài)映射模型引入前提

首先我們給出所需要用到的特性以及對(duì)應(yīng)枚舉,看注釋一看便知

public?enum?CustomTableFormat {///?<summary>///?每天,(yyyyMMdd)///?</summary>[Description("每天")]DAY,///?<summary>///?每小時(shí),(yyyyMMddHH)///?</summary>[Description("每小時(shí)")]HOUR,///?<summary>///?每分鐘(yyyyMMddHHmm)///?</summary>[Description("每分鐘")]MINUTE }[AttributeUsage(AttributeTargets.Class,?AllowMultiple?=?false)] public?class?EfEntityAttribute?:?Attribute {///?<summary>///?是否啟用動(dòng)態(tài)生成表///?</summary>public?bool?EnableCustomTable?{?get;?set;?}?=?false;///?<summary>///?動(dòng)態(tài)生成表前綴///?</summary>public?string?Prefix?{?get;?set;?}///?<summary>///?表生成規(guī)則///?</summary>public?CustomTableFormat?Format?{?get;?set;?}?=?CustomTableFormat.DAY;public?override?string?ToString(){if?(EnableCustomTable){return?string.IsNullOrEmpty(Prefix)???Format.FormatToDate()?:?$"{Prefix}{Format.FormatToDate()}";}return?base.ToString();} }public?static?class?CustomTableFormatExetension {public?static?string?FormatToDate(this?CustomTableFormat?tableFormat){return?tableFormat?switch{CustomTableFormat.DAY?=>?DateTime.Now.ToString("yyyyMMdd"),CustomTableFormat.HOUR?=>?DateTime.Now.ToString("yyyyMMddHH"),CustomTableFormat.MINUTE?=>?DateTime.Now.ToString("yyyyMMddHHmm"),_?=>?DateTime.Now.ToString("yyyyMMdd"),};} }

通過定義特性,主要出發(fā)點(diǎn)基于以下兩點(diǎn):

其一:由外部注入模型而非寫死DbSet屬性訪問

其二:每個(gè)模型可定義動(dòng)態(tài)映射表規(guī)則

動(dòng)態(tài)映射模型方式(一)

首先我們給出需要用到的上下文,為方便演示我們以每分鐘自動(dòng)映射模型為例

public?class?EfDbContext?:?DbContext {public?string?Date?{?get;?set;?}?=?CustomTableFormat.MINUTE.FormatToDate();public?EfDbContext(DbContextOptions<EfDbContext>?options)?:?base(options){} }

動(dòng)態(tài)模型即指表名不同,比如我們實(shí)現(xiàn)每天/每小時(shí)/每分鐘動(dòng)態(tài)映射模型和生成一張表,如同流動(dòng)的水一樣并非一層不變,但本質(zhì)上還是那滴水。在下面接口中我們需要用到每分鐘生成一張表格式,所以在上下文中定義每分鐘屬性

第一種方式則是通過實(shí)現(xiàn)IModelCacheKeyFactory接口,此接口將指定上下文下所有模型表名進(jìn)行了緩存,所以我們可以根據(jù)所需動(dòng)態(tài)模型表名進(jìn)行更改即可,如下:

public?class?CustomModelCacheKeyFactory?:?IModelCacheKeyFactory {public?object?Create(DbContext?context){var?efDbContext?=?context?as?EfDbContext;if?(efDbContext?!=?null){return?(context.GetType(),?efDbContext.Date);}return?context.GetType();} }

上述其實(shí)現(xiàn)貌似感覺有點(diǎn)看不太懂,主要這是直接實(shí)現(xiàn)接口一步到位,底層本質(zhì)則是額外調(diào)用實(shí)例一個(gè)緩存鍵類,我們將上述改為如下兩步則一目了然

public?class?CustomModelCacheKeyFactory?:?ModelCacheKeyFactory {private?string?_date;public?CustomModelCacheKeyFactory(ModelCacheKeyFactoryDependencies?dependencies):?base(dependencies){}public?override?object?Create(DbContext?context){if?(context?is?EfDbContext?efDbContext){_date?=?efDbContext.Date;}return?new?CustomModelCacheKey(_date,?context);} }public?class?CustomModelCacheKey?:?ModelCacheKey {private?readonly?Type?_contextType;private?readonly?string?_date;public?CustomModelCacheKey(string?date,?DbContext?context)?:?base(context){_date?=?date;_contextType?=?context.GetType();}public?virtual?bool?Equals(CustomModelCacheKey?other)=>?_contextType?==?other._contextType?&&?_date?==?other._date;public?override?bool?Equals(object?obj)=>?(obj?is?CustomModelCacheKey?otherAsKey)?&&?Equals(otherAsKey);public?override?int?GetHashCode()?=>?_date.GetHashCode(); }

然后在OnModelCreating方法里面進(jìn)行掃描特性標(biāo)識(shí)模型進(jìn)行注冊,如下:

protected?override?void?OnModelCreating(ModelBuilder?modelBuilder) {var?entityMethod?=?typeof(ModelBuilder).GetMethod(nameof(modelBuilder.Entity),?new?Type[]?{?});var?assembly?=?Assembly.GetExecutingAssembly();//【1】使用Entity方法注冊foreach?(var?type?in?assembly.ExportedTypes){if?(!(type.GetCustomAttribute(typeof(EfEntityAttribute))?is?EfEntityAttribute?attribute)){continue;}if?(type.IsNotPublic?||?type.IsAbstract?||?type.IsSealed||?type.IsGenericType||?type.ContainsGenericParameters){continue;}entityMethod.MakeGenericMethod(type).Invoke(modelBuilder,?new?object[]?{?});}//【2】使用IEntityTypeConfiguration<T>注冊modelBuilder.ApplyConfigurationsFromAssembly(assembly);base.OnModelCreating(modelBuilder); }

上述第一種方式則通過反射將模型注冊,其本質(zhì)則是調(diào)用modeBuilder.Entity方法,若我們在模型上使用注解,則對(duì)應(yīng)也會(huì)將其應(yīng)用

但注解不夠靈活,比如要標(biāo)識(shí)聯(lián)合主鍵,則只能使用Fluent APi,所以我們通過在外部實(shí)現(xiàn)IEntityTypeConfiguration進(jìn)行注冊,然后EF Core提供針對(duì)該接口程序集注冊,其底層本質(zhì)也是掃描程序集,兩種方式都支持,不用再擔(dān)心外部模型注冊問題

緊接著我們給出測試模型,表名為當(dāng)前分鐘,表名利用注解則不行(值必須為常量),所以我們使用如下第二種映射模型

[EfEntity(EnableCustomTable?=?true,?Format?=?CustomTableFormat.MINUTE)] public?class?Test {[Table(DateTime.Now.ToString("yyyyMMdd"))]public?int?Id?{?get;?set;?}public?string?Name?{?get;?set;?} }public?class?TestEntityTypeConfiguration?:?IEntityTypeConfiguration<Test> {public?void?Configure(EntityTypeBuilder<Test>?builder){builder.ToTable(DateTime.Now.ToString("yyyyMMddHHmm"));} }

上述第二種配置未嘗不可,但我們還有更加簡潔一步到位的操作,所以這里刪除上述第二種方式

因?yàn)樵贠nModelCreating方法里面,我們反射了調(diào)用了Entity方法,所以我們直接將反射調(diào)用Entity方法強(qiáng)制轉(zhuǎn)換為EntityTypeBuilder,在已有基礎(chǔ)上,代碼做了重點(diǎn)標(biāo)識(shí)

protected?override?void?OnModelCreating(ModelBuilder?modelBuilder) {var?entityMethod?=?typeof(ModelBuilder).GetMethod(nameof(modelBuilder.Entity),?new?Type[]?{?});var?assembly?=?Assembly.GetExecutingAssembly();//【1】使用Entity方法注冊foreach?(var?type?in?assembly.ExportedTypes){if?(!(type.GetCustomAttribute(typeof(EfEntityAttribute))?is?EfEntityAttribute?attribute)){continue;}if?(type.IsNotPublic?||?type.IsAbstract?||?type.IsSealed||?type.IsGenericType||?type.ContainsGenericParameters){continue;}//?強(qiáng)制轉(zhuǎn)換為EntityTypeBuildervar?entityBuilder?=?(EntityTypeBuilder)entityMethod.MakeGenericMethod(type).Invoke(modelBuilder,?new?object[]?{?});if?(attribute.EnableCustomTable){entityBuilder.ToTable(attribute.ToString());}}//【2】使用IEntityTypeConfiguration<T>注冊modelBuilder.ApplyConfigurationsFromAssembly(assembly);base.OnModelCreating(modelBuilder); }

最后則是注入上下文,這里我們將內(nèi)外部容器進(jìn)行區(qū)分(EF Core為何分內(nèi)部容器,具體原因請參看文章《EntityFramework Core 3.x上下文構(gòu)造函數(shù)可以注入實(shí)例呢?》)

因在實(shí)際項(xiàng)目中上下文可能需要在上下文構(gòu)造函數(shù)中注入其他接口,比如我們就有可能在上下文構(gòu)造函數(shù)中注入接口從而根據(jù)具體接口實(shí)現(xiàn)來更改表架構(gòu)或不同表名規(guī)則等等

static?IServiceProvider?Initialize() {var?services?=?new?ServiceCollection();services.AddEntityFrameworkSqlServer().AddDbContext<EfDbContext>((serviceProvider,?options)?=>options.UseSqlServer("server=.;database=efcore;uid=sa;pwd=sa123;").UseInternalServiceProvider(serviceProvider));services.Replace(ServiceDescriptor.Singleton<IModelCacheKeyFactory,?CustomModelCacheKeyFactory>());return?services.BuildServiceProvider(); }

由于我們已區(qū)分EF Core內(nèi)外部容器,所以在替換自定義緩存鍵工廠時(shí),不能再像如下直接調(diào)用ReplaceService方法替換,勢必會(huì)拋出異常

?options.UseSqlServer("server=.;database=efcore;uid=sa;pwd=sa123;").ReplaceService<IModelCacheKeyFactory,?CustomModelCacheKeyFactory>()

同時(shí)謹(jǐn)記在非Web項(xiàng)目中利用EF Core始終要使用作用域(scope)來釋放上下文,不像Web可基于HTTP請求作為scope,最后我們測試如下

using?(var?scope1?=?ServiceProvider.CreateScope()) {var?context1?=?scope1.ServiceProvider.GetService<EfDbContext>();context1.Database.EnsureCreated();var?type?=?context1.Model.FindEntityType(typeof(Test));Console.WriteLine(type?.GetTableName());var?tests?=?context1.Set<Test>().ToList(); }Thread.Sleep(60000);using?(var?scope2?=?ServiceProvider.CreateScope()) {var?context2?=?scope2.ServiceProvider.GetService<EfDbContext>();context2.Database.EnsureCreated();var?type?=?context2.Model.FindEntityType(typeof(Test));Console.WriteLine(type?.GetTableName());var?tests1?=?context2.Set<Test>().ToList(); }

為方便看到實(shí)際效果,我們構(gòu)建兩個(gè)scope,然后睡眠一分鐘,在界面上打印輸出表名,若兩分鐘后打印表名不一致,說明達(dá)到預(yù)期

動(dòng)態(tài)映射模型方式(二)

上述我們使用每分鐘規(guī)則動(dòng)態(tài)映射表,同時(shí)可針對(duì)不同模型有各自規(guī)則(前綴,每小時(shí)或每天)等等,這是第一種方式

如果對(duì)第一種方式實(shí)現(xiàn)完全看懂了,可能會(huì)有所疑惑,因?yàn)榈谝环N方式其接口生命周期為單例,若不需要豈不還是會(huì)將上下文中所有模型都會(huì)進(jìn)行緩存嗎

調(diào)用OnModelCreating方法只是進(jìn)行模型構(gòu)建,我們現(xiàn)直接調(diào)用內(nèi)置APi來手動(dòng)使用所有模型,此時(shí)將不再緩存,所以不再需要IModelCacheKeyFactory接口

對(duì)EF Core稍微了解一點(diǎn)的話,我們知道OnModelCreating方法僅僅只會(huì)調(diào)用一次,我們通過手動(dòng)構(gòu)構(gòu)建和處置所有模型,說了這么多,那么我們到底該如何做呢?

如果看過我之前原理分析的話,大概能知道EntityFramework Core對(duì)于模型的處理(除卻模型緩存)分為三步,除卻模型緩存:構(gòu)建模型,使用模型,處置模型。

我們將OnModelCreating方法代碼全部直接復(fù)制過來,只是多了上面三步而已,在我們實(shí)例化ModelBuilder時(shí),我們需要提供對(duì)應(yīng)數(shù)據(jù)庫默認(rèn)約定,然后使用模型、處置模型,結(jié)果變成如下這般

?services.AddEntityFrameworkSqlServer().AddDbContext<EfDbContext>((serviceProvider,?options)?=>?{options.UseSqlServer("server=.;database=efcore;uid=sa;pwd=sa123;").UseInternalServiceProvider(serviceProvider);var?conventionSet?=?SqlServerConventionSetBuilder.Build();var?modelBuilder?=?new?ModelBuilder(conventionSet);//?OnModelCreating方法,代碼復(fù)制options.UseModel(modelBuilder.Model);modelBuilder.FinalizeModel();???????????????)};

運(yùn)行第一種方式測試代碼,然后么有問題

問題來了,要是有多個(gè)數(shù)據(jù)庫,豈不是都要像上述再來一遍?上述實(shí)現(xiàn)本質(zhì)上是每次構(gòu)造一個(gè)上下文則會(huì)構(gòu)建并重新使用新的模型,所以我們將其統(tǒng)一放到上下文構(gòu)造函數(shù)中去,然后寫個(gè)擴(kuò)展方法構(gòu)建模型,如下:

public?static?class?ModelBuilderExetension {public?static?ModelBuilder?BuildModel(this?ModelBuilder?modelBuilder){var?entityMethod?=?typeof(ModelBuilder).GetMethod(nameof(modelBuilder.Entity),?new?Type[]?{?});var?assembly?=?Assembly.GetExecutingAssembly();//【1】使用Entity方法注冊foreach?(var?type?in?assembly.ExportedTypes){if?(!(type.GetCustomAttribute(typeof(EfEntityAttribute))?is?EfEntityAttribute?attribute)){continue;}if?(type.IsNotPublic?||?type.IsAbstract?||?type.IsSealed||?type.IsGenericType||?type.ContainsGenericParameters){continue;}var?entityBuilder?=?(EntityTypeBuilder)entityMethod.MakeGenericMethod(type).Invoke(modelBuilder,?new?object[]?{?});if?(attribute.EnableCustomTable){entityBuilder.ToTable(attribute.ToString());}}//【2】使用IEntityTypeConfiguration<T>注冊modelBuilder.ApplyConfigurationsFromAssembly(assembly);return?modelBuilder;} }

最后在上下文構(gòu)造函數(shù)中,簡潔調(diào)用,如下:

public?class?EfDbContext?:?DbContext {public?string?Date?{?get;?set;?}?=?CustomTableFormat.MINUTE.FormatToDate();public?EfDbContext(DbContextOptions<EfDbContext>?options)?:?base(options){//提供不同數(shù)據(jù)庫默認(rèn)約定ConventionSet?conventionSet?=?null;if?(Database.ProviderName?==?"Microsoft.EntityFrameworkCore.SqlServer"){conventionSet?=?SqlServerConventionSetBuilder.Build();}else?if?(Database.ProviderName?==?"Microsoft.EntityFrameworkCore.Sqllite"){conventionSet?=?SqliteConventionSetBuilder.Build();}else?if?(Database.ProviderName?==?"Microsoft.EntityFrameworkCore.MySql"){conventionSet?=?MySqlConventionSetBuilder.Build();}var?modelBuilder?=?new?ModelBuilder(conventionSet);var?optionBuilder?=?new?DbContextOptionsBuilder(options);//使用模型optionBuilder.UseModel(modelBuilder.Model);//處置模型modelBuilder.FinalizeModel();}protected?override?void?OnModelCreating(ModelBuilder?modelBuilder){//構(gòu)建模型modelBuilder.BuildModel();base.OnModelCreating(modelBuilder);} }

動(dòng)態(tài)映射模型表生成

看到這里,細(xì)心的你不知道有沒有發(fā)現(xiàn),我寫的打印結(jié)果怎么成功了,居然沒拋出任何異常,實(shí)際情況是必須會(huì)拋出異常,因?yàn)槲覀冎蛔龅搅四P蛣?dòng)態(tài)映射,但表自動(dòng)生成我在此之前將其忽略了,如下:

表如何生成這個(gè)也看實(shí)際情況分析,比如SQL Server寫個(gè)作業(yè)每天自動(dòng)生成表等,若需兼容多個(gè)數(shù)據(jù)庫,怕是有點(diǎn)麻煩

我沒花太多時(shí)間去看源碼,稍微看了下,碰碰運(yùn)氣或許能直接找到根據(jù)模型來創(chuàng)建表的接口實(shí)現(xiàn),結(jié)果好像沒有,即使有也比較麻煩,那么我們就手動(dòng)構(gòu)建SQL語句或者通過lambda構(gòu)建也可

上下文中實(shí)現(xiàn)其特性需動(dòng)態(tài)生成的模型我們可以獲取得到,然后搞個(gè)定時(shí)器每分鐘去執(zhí)行生成對(duì)應(yīng)表,針對(duì)不同數(shù)據(jù)庫類型,我們可以通過如下屬性獲取得到(和包同名)

//?比如SQL Server:Microsoft.EntityFrameworkCore.SqlServer context.Database.ProviderName

這里我以SQL Server數(shù)據(jù)庫為例,其他數(shù)據(jù)庫比如MySqL、Sqlite唯一區(qū)別則是自增長設(shè)置和列類型不同而已,創(chuàng)建表,通過五部分組成:表是否存在,表名,主鍵,所有列,約束。我們定義如下:

internal?sealed?class?CustomTableModel {public?CustomEntityType?CustomEntityType?{?get;?set;?}public?string?TableName?{?get;?set;?}?=?string.Empty;public?string?CheckTable?{?get;?set;?}?=?string.Empty;public?string?PrimaryKey?{?get;?set;?}?=?string.Empty;public?string?Columns?{?get;?set;?}?=?string.Empty;public?string?Constraint?{?get;?set;?}?=?string.Empty;public?override?string?ToString(){var?placeHolder?=?$"{CheckTable}?create?table?{TableName}?({PrimaryKey}?{Columns}";placeHolder?=?string.IsNullOrEmpty(Constraint)???$"{placeHolder.TrimEnd(',')})"?:?$"{placeHolder}{Constraint})";return?placeHolder.Replace("@placeholder_table_name",?CustomEntityType.ToString());} }

由于每次生成只有表名不同,所以我們將整個(gè)表數(shù)據(jù)結(jié)構(gòu)進(jìn)行緩存,在其內(nèi)部將表名進(jìn)行替換就好。整個(gè)實(shí)現(xiàn)邏輯如下:

public?static?void?Execute() {using?var?scope?=?Program.ServiceProvider.CreateScope();var?context?=?scope.ServiceProvider.GetService<EfDbContext>();context.Database.EnsureCreated();var?cache?=?scope.ServiceProvider.GetService<IMemoryCache>();var?cacheKey?=?context.GetType().FullName;if?(!cache.TryGetValue(cacheKey,?out?List<CustomTableModel>?models)){lock?(_syncObject){if?(!cache.TryGetValue(cacheKey,?out?models)){models?=?CreateModels(context);models?=?cache.Set(cacheKey,?models,?new?MemoryCacheEntryOptions?{?Size?=?100,?Priority?=?CacheItemPriority.High?});}}}Create(context,?models); }private?static?void?Create(EfDbContext?context,?List<CustomTableModel>?models) {foreach?(var?m?in?models){context.Execute(m.ToString());} }internal?static?void?CreateEntityTypes(CustomEntityType?customEntityType) {EntityTypes.Add(customEntityType); }

上述標(biāo)紅部分很重要,為什么呢?

讓其先執(zhí)行OnModelCreating方法,也就是說我們必須保證所有模型已經(jīng)構(gòu)建完畢,我們才能在上下文中拿到所有模型元數(shù)據(jù)

接下來則是在OnModeCreating方法中,在啟動(dòng)自動(dòng)映射模型的基礎(chǔ)上,添加如下代碼(當(dāng)然也需檢查表名是否存在重復(fù)):

??if?(attribute.EnableCustomTable){entityBuilder.ToTable(attribute.ToString());var?customType?=?new?CustomEntityType(){ClrType?=?type,Prefix?=?attribute.Prefix,Format?=?attribute.Format};var?existTable?=?CreateCustomTable.EntityTypes.FirstOrDefault(c?=>?c.ToString()?==?customType.ToString());if?(existTable?!=?null){throw?new?ArgumentNullException($"Cannot?use?table?'{customType}'?for?entity?type?'{type.Name}'?since?it?is?being?used?for?entity?type?'{existTable.ClrType.Name}'?");}CreateCustomTable.CreateEntityTypes(customType);}

相信構(gòu)建SQL語句這塊都不在話下,就不再給出了,若有需要的童鞋,可私信我,人比較多的話,我會(huì)將兼容不同數(shù)據(jù)庫的SQL語句構(gòu)建都會(huì)放到github上去以供參考,控制臺(tái)入口方法調(diào)用如下:

private?const?int?TIME_INTERVAL_IN_MILLISECONDS?=?60000; private?static?Timer?_timer?{?get;?set;?} public?static?IServiceProvider?ServiceProvider?{?get;?set;?} static?void?Main(string[]?args) {ServiceProvider?=?Initialize();//初始化時(shí)檢查一次CreateCustomTable.Execute();//定時(shí)檢查_timer?=?new?Timer(TimerCallback,?null,?TIME_INTERVAL_IN_MILLISECONDS,?Timeout.Infinite);using?(var?scope1?=?ServiceProvider.CreateScope()){var?context1?=?scope1.ServiceProvider.GetService<EfDbContext>();context1.Database.EnsureCreated();var?type?=?context1.Model.FindEntityType(typeof(Test1));Console.WriteLine(type?.GetTableName());var?tests?=?context1.Set<Test1>().ToList();}Thread.Sleep(60000);using?(var?scope2?=?ServiceProvider.CreateScope()){var?context2?=?scope2.ServiceProvider.GetService<EfDbContext>();context2.Database.EnsureCreated();var?type?=?context2.Model.FindEntityType(typeof(Test2));Console.WriteLine(type?.GetTableName());var?tests1?=?context2.Set<Test2>().ToList();}Console.ReadKey();}

接下來則是通過定義上述定時(shí)器,回調(diào)調(diào)用上述Execute方法,如下:

??static?void?TimerCallback(object?state){var?watch?=?new?Stopwatch();watch.Start();CreateCustomTable.Execute();_timer.Change(Math.Max(0,?TIME_INTERVAL_IN_MILLISECONDS?-?watch.ElapsedMilliseconds),?Timeout.Infinite);}

最后我們來兩個(gè)模型測試下實(shí)際效果

[EfEntity(EnableCustomTable?=?true,?Prefix?=?"test1",?Format?=?CustomTableFormat.MINUTE)] public?class?Test1 {public?int?Id?{?get;?set;?}public?int?UserId?{?get;?set;?}public?string?Name?{?get;?set;?} }public?class?Test1EntityTypeConfiguration?:?IEntityTypeConfiguration<Test1> {public?void?Configure(EntityTypeBuilder<Test1>?builder){builder.HasKey(k?=>?new?{?k.Id,?k.UserId?});} }[EfEntity(EnableCustomTable?=?true,?Prefix?=?"test2",?Format?=?CustomTableFormat.MINUTE)] public?class?Test2 {public?int?Id?{?get;?set;?}public?int?UserId?{?get;?set;?}public?string?Name?{?get;?set;?} }public?class?Test2EntityTypeConfiguration?:?IEntityTypeConfiguration<Test2> {public?void?Configure(EntityTypeBuilder<Test2>?builder){builder.HasKey(k?=>?new?{?k.Id,?k.UserId?});} }

最后的最后,老規(guī)矩,實(shí)現(xiàn)動(dòng)態(tài)映射模型有如上兩種方式,通過手動(dòng)構(gòu)建SQL語句并緩存,總結(jié)如下!

??????使用IModelCacheKeyFactory

?????手動(dòng)構(gòu)建模型、處置模型

???????兼容不同數(shù)據(jù)庫,手動(dòng)構(gòu)建SQL語句并緩存

總結(jié)

以上是生活随笔為你收集整理的EntityFramework Core如何映射动态模型?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。