我需要重构一个实体,并将其某些属性移至具有1:1关系的另一个实体。但是,当我创建一个新类并主要将即时类型属性移动到它时,将Entity1Id
作为其密钥以及它们之间的虚拟导航属性创建,当我想创建迁移时,我会收到以下错误:
system.notsupportedException:'Instant'的类型映射尚未实现代码文字生成。
发生了什么事?我没有播种(找到此错误:https://github.com/npgsql/npgsql.entityframeworkcore.postgresql/issues/526(
我创建了一个简单的存储库,该存储库可演示这种行为,您可以在其中使用.NET Core 2.2对其进行测试。我目前在Mac上;我不确定它是否有任何影响。
github repo:https://github.com/slaviusz/efcoresplittingentityproblem
编辑:
根据要求,github repo的实际内容是什么,代码示例如下。请注意,我在具有数十实体的解决方案中遇到了这个问题,但我能够将其缩小到一个实体重构项目的简单。
从一个简单的实体开始:
public class Table1
{
public int Id { get; set; }
public string Name { get; set; }
public Instant Starts { get; set; }
public Instant Ends { get; set; }
}
public class ApplicationDbContext : DbContext
{
... // other code like constructors and configure method overrides
public DbSet<Table1> Table1s { get; set; }
}
创建迁移成功,然后成功进行dotnet ef database update
。(但是,为了触发这一点,这根本不是必需的(
可以在第一个提交中看到更多详细信息:https://github.com/slaviusz/efcoresplittittityproblem/commit/57562f0c978287e15d75fff1bead435501c28befc p>下一步是执行重构,将两个即时属性提取到辅助类之间,在它们之间创建逻辑关系。典型的用例是将实体详细信息提取到其自己的表,仅在需要详细信息时才需要加入/子选择。
在这种情况下,PROPS Instant Starts
和Instant Ends
移至Table2
。
public class Table1
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Table2 Table2 { get; set; }
}
public class Table2
{
[Key] public int Table1Id { get; set; }
public Instant Starts { get; set; }
public Instant Ends { get; set; }
public virtual Table1 Table1 { get; set; }
}
public class ApplicationDbContext : DbContext
{
... // other code like constructors and configure method overrides
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Table2>()
.HasOne(p => p.Table1)
.WithOne(p => p.Table2);
}
public DbSet<Table1> Table1s { get; set; }
public DbSet<Table2> Table2s { get; set; }
}
所有人都可以在第三项提交中看到:https://github.com/slaviusz/efcoresplittittityproblem/commit/04fe59563bd510d110df26a37e5937e5938888888888888888888888888888841673
注意:第二个提交是我添加的.gitignore以排除不必要的文件。
此时执行dotnet ef migrations add Split
导致:
$ dotnet ef migrations add Split
An operation was scaffolded that may result in the loss of data. Please review the migration for accuracy.
System.NotSupportedException: The type mapping for 'Instant' 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.Migrations.Design.CSharpMigrationOperationGenerator.Generate(AddColumnOperation operation, IndentedStringBuilder builder)
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid3[T0,T1,T2](CallSite site, T0 arg0, T1 arg1, T2 arg2)
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)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType)
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 'Instant' has not implemented code literal generation.
我觉得要注意的是,为了能够使用EF核心内存中提供商测试我,我正在使用2个构造函数:
// constructor for mocking with InMemory provider
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// return if already configured (by mocking with InMemory provider)
if (optionsBuilder.IsConfigured)
return;
... // the rest of the code to init
}
然而,这导致dotnet
工具无法执行CLI EF核心操作(迁移,数据库更新(。因此,我还有扩展IDesignTimeDbContextFactory<>
的其他类别。
public class CliDbContext : IDesignTimeDbContextFactory<ApplicationDbContext>
{
public ApplicationDbContext CreateDbContext(string[] args)
{
... // code to init in cli cases
}
}
在测试项目中处理问题时,似乎只是清除了Poco类的即时属性,这会触发此错误。
非常粗略的解决方法是将删除分为2个迁移:
- 将即时道具施放到第一次迁移中的字符串(VARCHAR(
- 最终在第二个迁移中从类中删除字符串道具
两个迁移都成功了,我能够运行有关可能数据丢失的小警告的dotnet ef database update
- 这是我编写自定义SQL代码以在以前的迁移中迁移的数据,在此我在另一类中创建了新的即时属性。