[英]EF Core 5.0 - Do you need to generate a migration when changing a “Defining Query” -mapped entity?
[英]EF Core 5.0 - How to seed entity with List<string> property in a migration?
我試圖解決這個問題需要幾個小時,但可以找到解決方案。
我有一個具有List<string>
屬性的實體,我想對其進行數據播種。 我成功使用modelBuilder.Entity<T>.HasData()
,但它不適用於dotnet ef migrations
。
這是我的實體:
public class MyEntity
{
public int Id { get; set; }
public List<string> Names { get; set; }
}
這是我的DbContext.OnModelCreating
覆蓋:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MyEntity>()
.HasData(
new MyEntity { Id = 1, Names = new List<string> { "text1", "text2" } },
new MyEntity { Id = 2, Names = new List<string> { "text1", "text2", "text3" } },
new MyEntity { Id = 3, Names = new List<string> { "text1", "text2" } },
new MyEntity { Id = 4, Names = new List<string> { "text1", "text2" } },
new MyEntity { Id = 5, Names = new List<string> { "text1", "text2", "text3" } });
}
如果我運行我的應用程序,這將有效,它會創建表並使用所需值對其進行播種。 但是如果我運行dotnet ef migrations add AddMyEntities --project src/MyProject --startup-project src/MyProject.Api
,我會得到這個 output:
Build started...
Build succeeded.
System.NotSupportedException: The type mapping for 'List<string>' has not implemented code literal generation.
at Microsoft.EntityFrameworkCore.Storage.CoreTypeMapping.GenerateCodeLiteral(Object value)
at Microsoft.EntityFrameworkCore.Design.Internal.CSharpHelper.UnknownLiteral(Object value)
at Microsoft.EntityFrameworkCore.Design.Internal.CSharpHelper.Literal(Object[,] values)
at Microsoft.EntityFrameworkCore.Migrations.Design.CSharpMigrationOperationGenerator.Generate(InsertDataOperation operation, IndentedStringBuilder builder)
at Microsoft.EntityFrameworkCore.Migrations.Design.CSharpMigrationOperationGenerator.Generate(String builderName, IReadOnlyList`1 operations, IndentedStringBuilder builder)
at Microsoft.EntityFrameworkCore.Migrations.Design.CSharpMigrationsGenerator.GenerateMigration(String migrationNamespace, String migrationName, IReadOnlyList`1 upOperations, IReadOnlyList`1 downOperations)
at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsScaffolder.ScaffoldMigration(String migrationName, String rootNamespace, String subNamespace, String language)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
The type mapping for 'List<string>' has not implemented code literal generation.
如何播種一個簡單的List<string>
屬性?
編輯:我認為這個問題與實體框架 - 代碼優先 - 無法存儲列表等其他問題不同,因為如果我在空白數據庫上啟動它,我的程序可以正常工作(使用 PostgreSQL,它會創建一個text[]
類型的Names
列 [ text[]
,如您所料)。 問題是當我使用dotnet ef
遷移工具時。
編輯: OP 提到它使用 PostgreSQL 和相應的 EF 提供程序,所以問題不是缺失值轉換器。
該問題似乎與 EF Core 本身的限制有關。 遷移腳手架過程當前使用內置的硬編碼CSharpHelper class,它知道如何為一組封閉的類型生成 C# 文字。 例如,它知道如何生成object[]
文字,但不知道IEnumerable<>
。 (參考: dotnet/efcore#12979 )。 似乎現在提供者可以為其他類型的代碼文字添加生成,我可以發現它是為npgsql/efcore.pg#0deb6a23中的某些類型添加的,但據我所知,不是為List<>
添加的。 ..但我可能是錯的,因為我自己沒有測試過這些。
我的建議? 要么使用string[]
要么HasData
並提供一些自定義的種子邏輯。
OLD:問題不在於HasData
功能本身。 根本問題是 EF Core 本身並不知道如何將List<string>
存儲到數據庫中,因此它失敗了。
您可以做的是定義一個自定義的ValueConverter
來指示 EF Core 如何將該特定屬性存儲到您的數據庫列中(您可以查看有關此主題的EF Core 文檔)。
go 的最佳方法可能是使用Newtonsoft JSONConvert定義此轉換:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MyEntity>()
.Property(p => p.Names)
.HasConversion(
listOfStringNames => JsonConvert.SerializeObject(listOfStringNames),
namesJsonRepresentation => JsonConvert.DeserializeObject<List<string>>(namesJsonRepresentation));
.HasData(
new MyEntity { Id = 1, Names = new List<string> { "text1", "text2" } },
new MyEntity { Id = 2, Names = new List<string> { "text1", "text2", "text3" } },
new MyEntity { Id = 3, Names = new List<string> { "text1", "text2" } },
new MyEntity { Id = 4, Names = new List<string> { "text1", "text2" } },
new MyEntity { Id = 5, Names = new List<string> { "text1", "text2", "text3" } });
}
作為旁注,我想提一下,盡管HasData
很好,但根據我的個人經驗,最好只編寫我自己的DatabaseInitializer
class ,它可以使用我想要的任何自定義邏輯播種我需要的數據,而沒有任何限制HasData
有(參考: https://docs.microsoft.com/en-us/ef/core/modeling/data-seeding#limitations-of-model-seed-data )
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.