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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用EF.Core将同一模型映射到多个表

發布時間:2023/12/4 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用EF.Core将同一模型映射到多个表 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在 EntityFramework Core 中,我們可以使用屬性或Fluent API來配置模型映射。有一天,我遇到了一個新的需求,有一個系統每天會生成大量數據,每天生成一個新的表存儲數據。例如,數據庫如下所示:

所有表都具有相同的結構。那么,如何更改映射以避免創建多個模型呢?

在本文中,我將向您展示如何更改映射以處理這種情況。您也可以使用此方法擴展出更多的用法。

創建 .NET Core 3.1 項目

現在,我們可以使用.NET Core 3.1,它是.NET Core的LTS版本,將來可以輕松將其升級到.NET 5。

假設您已經在計算機上安裝了最新的.NET Core SDK。如果沒有,則可以從https://dotnet.microsoft.com/download下載。然后,您可以使用dotnet CLI創建項目。對于此示例,我將使用.NET Core 3.1。

讓我們創建一個名為DynamicModelDemo的新.NET Core Console項目:

dotnet new console --name DynamicModelDemo

然后用以下命令創建一個新的解決方案:

dotnet new sln --name DynamicModelDemo

接下來使用以下命令把剛才創建的項目添加到解決方案:

dotnet sln add "DynamicModelDemo/DynamicModelDemo.csproj"

接下來可以用Visual Studio打開解決方案了。

創建模型

該模型非常簡單。在項目中添加一個名為ConfigurableEntity.cs的新文件:

using System;namespace DynamicModelDemo {public class ConfigurableEntity{public int Id { get; set; }public string Title { get; set; }public string Content { get; set; }public DateTime CreateDateTime { get; set; }} }

我們將使用CreateDateTime屬性來確定模型應該映射到哪個表。

添加 EntityFramework Core

導航到項目目錄并使用以下命令添加所需的EF.Core packages:

dotnet add package Microsoft.EntityFrameworkCore.SqlSever dotnet add package Microsoft.EntityFrameworkCore.Design

如果您還沒有安裝 ef tool,請運行以下命令來安裝:

dotnet tool install --global dotnet-ef

這樣您就可以使用 dotnet ef 工具創建遷移或通過應用遷移來更新數據庫。

創建 DbContext

向項目添加一個名為DynamicContext.cs的新類文件。內容如下所示:

using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using System;namespace DynamicModelDemo {public class DynamicContext : DbContext{public DbSet<ConfigurableEntity> Entities { get; set; }#region OnConfiguringprotected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)=> optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=DynamicContext;Trusted_Connection=True;");#endregion#region OnModelCreatingprotected override void OnModelCreating(ModelBuilder modelBuilder){modelBuilder.Entity<ConfigurableEntity>(b =>{b.HasKey(p => p.Id);});}#endregion} }

目前,這只是EF.Core的基本配置。它使用默認映射,這意味著模型將映射到名為Entities的表。那么,如果我們想基于其CreateDateTime屬性將模型映射到不同的表,該怎么辦呢?

您可能知道我們可以使用ToTable()方法來更改表名,但是如何在OnModelCreating方法中更改所有模型的表名呢?EF建立模型時,只會執行一次OnModelCreating。所以這種方式是無法實現的。

對于這種情況,我們需要使用IModelCacheKeyFactory來更改默認映射,通過這個接口我們可以定制模型緩存機制,以便EF能夠根據其屬性創建不同的模型。

IModelCacheKeyFactory是什么?

這是微軟官方的文檔解釋:

EF uses IModelCacheKeyFactory to generate cache keys for models.

默認情況下,EF假定對于任何給定的上下文類型,模型都是相同的。但是對于我們的方案,模型將有所不同,因為它映射到了不同的表。因此,我們需要用我們的實現替換IModelCacheKeyFactory服務,該實現會比較緩存鍵以將模型映射到正確的表。

請注意,該接口通常由數據庫提供程序和其他擴展使用,一般不在應用程序代碼中使用。但是對于我們的場景來說,這是一種可行的方法。

實現IModelCacheKeyFactory

我們需要使用CreateDateTime來區分表。在DynamicContext類中添加一個屬性:

public DateTime CreateDateTime { get; set; }

在項目中添加一個名為DynamicModelCacheKeyFactory.cs的新類文件。代碼如下所示:

using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure;namespace DynamicModelDemo {public class DynamicModelCacheKeyFactory : IModelCacheKeyFactory{public object Create(DbContext context)=> context is DynamicContext dynamicContext? (context.GetType(), dynamicContext.CreateDateTime): (object)context.GetType();} }

在生成模型緩存鍵時,此實現將考慮CreateDateTime屬性。

應用IModelCacheKeyFactory

接下來,我們可以在上下文中注冊新的IModelCacheKeyFactory:

#region OnConfiguring protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)=> optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=DynamicContext;Trusted_Connection=True;").ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>(); #endregion

這樣我們就可以在OnModelCreating方法中分別映射表名了:

#region OnModelCreating protected override void OnModelCreating(ModelBuilder modelBuilder) {modelBuilder.Entity<ConfigurableEntity>(b =>{b.ToTable(CreateDateTime.ToString("yyyyMMdd"));b.HasKey(p => p.Id);}); } #endregion

CreateDateTime來自DynamicContext的屬性。

我們可以在創建DynamicContext時指定CreateDateTime屬性:

var context = new DynamicContext { CreateDateTime = datetime };

如果datetime為2020/03/27,則context的模型將映射到名為20200327的表。

創建數據庫

在驗證代碼之前,我們需要首先創建數據庫。但是,EF遷移并不是這種情況的最佳解決方案,因為隨著時間的流逝,系統將生成更多表。我們只是使用它來創建一些示例表來驗證映射。實際上,系統應該具有另一種每天動態生成表的方式。

運行以下命令以創建第一個遷移:

dotnet ef migrations add InitialCreate

您會看到在Migrations文件夾中生成了兩個文件。打開xxx_InitialCreate.cs文件,并通過以下代碼更新Up方法:

protected override void Up(MigrationBuilder migrationBuilder) {for (int i = 0; i < 30; i++){var index = i;migrationBuilder.CreateTable(name: DateTime.Now.AddDays(-index).ToString("yyyyMMdd"),columns: table => new{Id = table.Column<int>(nullable: false).Annotation("SqlServer:Identity", "1, 1"),Title = table.Column<string>(nullable: true),Content = table.Column<string>(nullable: true),CreateDateTime = table.Column<DateTime>(nullable: false)},constraints: table =>{table.PrimaryKey($"PK_{DateTime.Now.AddDays(-index):yyyyMMdd}", x => x.Id);});}}

所做的更改是為了確保數據庫中可以有足夠的表進行測試。請注意,我們不應該在生產環境中使用這種方式

接下來,我們可以使用此命令來創建和更新數據庫:

dotnet ef database update

您會看到它在數據庫中生成了最近30天的表。

驗證映射

現在該驗證新映射了。通過以下代碼更新Program.cs中的Main方法:

static void Main(string[] args) {DateTime datetime1 = DateTime.Now;using (var context = new DynamicContext { CreateDateTime = datetime1 }){context.Entities.Add(new ConfigurableEntity { Title = "Great News One", Content = $"Hello World! I am the news of {datetime1}", CreateDateTime = datetime1 });context.SaveChanges();}DateTime datetime2 = DateTime.Now.AddDays(-1);using (var context = new DynamicContext { CreateDateTime = datetime2 }){context.Entities.Add(new ConfigurableEntity { Title = "Great News Two", Content = $"Hello World! I am the news of {datetime2}", CreateDateTime = datetime2 });context.SaveChanges();}using (var context = new DynamicContext { CreateDateTime = datetime1 }){var entity = context.Entities.Single();// Writes news of todayConsole.WriteLine($"{entity.Title} {entity.Content} {entity.CreateDateTime}");}using (var context = new DynamicContext { CreateDateTime = datetime2 }){var entity = context.Entities.Single();// Writes news of yesterdayConsole.WriteLine($"{entity.Title} {entity.Content} {entity.CreateDateTime}");} }

您將會看到如下輸出:

現在,我們可以通過傳遞CreateDateTime屬性來使用相同的DbContext來表示不同的模型了。

小結

該演示旨在演示如何使用IModelCacheKeyFactory更改默認模型映射。請注意,您仍然需要實現分別生成表的方法。托管服務是一種實現方式。有關更多信息,請訪問Background tasks in ASP.NET Core[1]

參考資料

[1]

Background tasks in ASP.NET Core: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.1&tabs=visual-studio

求贊賞

????????????

推薦閱讀

  • 【手把手教程】如何讓你的求職簡歷敲開新西蘭雇主的大門(文末送福利)

  • 【手把手教程】新西蘭求職,如何寫好Cover Letter?

  • 再不拼老命我們就真老了——大齡碼農DIY新西蘭技術移民全記錄

  • 移民路上為什么別人總能得到更多的信息,今天知道真相還不算太晚

  • 還在愁紐村的面試嗎?安啦~史上最靠譜的面試題借你看兩眼!

  • 雅思之路——只有絕境沒有捷徑

  • 身在中國,如何應對海外公司的電話面試?

  • 大齡碼農來新西蘭三個月拿到兩個offer,真的只是運氣好?

  • 找工作的本命年——從國內大廠到NZ大廠

  • 苦中有甜、笑中含淚的新移民生活——多的是你不知道的事

總結

以上是生活随笔為你收集整理的使用EF.Core将同一模型映射到多个表的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。