拆分实体时"The type mapping for 'Instant' has not implemented code literal generation"



我需要重构一个实体,并将其某些属性移至具有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 StartsInstant 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个迁移:

  1. 将即时道具施放到第一次迁移中的字符串(VARCHAR(
  2. 最终在第二个迁移中从类中删除字符串道具

两个迁移都成功了,我能够运行有关可能数据丢失的小警告的dotnet ef database update - 这是我编写自定义SQL代码以在以前的迁移中迁移的数据,在此我在另一类中创建了新的即时属性。

相关内容

最新更新