【问题标题】:DbMigration seed sequence contains more than one elementDbMigration 种子序列包含多个元素
【发布时间】:2014-11-09 07:22:38
【问题描述】:

我有以下课程

public class Lookup
{
    public int Id{get;set;}
    public string Name{get;set;}
    public int Order{get;set;}
}

public class CatalogType:Lookup // this was added on Add-migration "Second"
{
}

public class Catalog:Lookup
{
     public int CatalogTypeId{get;set;} // this was added on add-migration "Second"

     public CatalogType CatalogType{get;set;}
}

并且我已经在表 Lookups 中的数据库中有数据,这些数据表示一组查找类,如性别、婚姻状况、目录等,并且 Lookups 表包含目录使用的 Name="General" 行(即鉴别器字段="目录")

在种子函数里面的配置文件中我写了这段代码

context.Lookups.AddOrUpdate(p => new { p.Name, **p.GetType().FullName** },
            new CatalogType
            {
                Name = "General",
                IsActive = true,
                Order = 1,
            },
            new CatalogType
            {
                Name = "Custom",
                IsActive = true,
                Order = 2,
            });
  context.SaveChanges();

我的问题:我先尝试了context.Lookups.AddOrUpdate(p=>p.Name),当我尝试制作update-database时,迁移失败“sequence contains more than one element

然后我尝试使用p.GetType().Name 错误是:

一个匿名类型不能有多个同名的属性。

然后我尝试使用p.GetType().FullName 并在执行update-database 命令时出现以下错误:

属性表达式 'p => new f__AnonymousType18`2(Name = p.Name, FullName = p.GetType().FullName)' 无效。表达方式 应该代表一个属性: C#: 't => t.MyProperty' VB.Net: '函数(t)t.MyProperty'。当指定多个属性时,使用 匿名类型:C#: 't => new { t.MyProperty1, t.MyProperty2 }' VB.Net: 'Function(t) New With { t.MyProperty1, t.MyProperty2 }'。

我知道问题是因为 Lookups 表已经包含 Name="General",但是如何告诉 EntityFramework 在尝试 AddOrUpdate 方法时考虑列鉴别器?

换句话说,我可能有 2 个不同对象的相同数据,并且我想在添加迁移时添加数据,如果我有例如红色汽车、红色门并且我想添加红色苹果,如何实现这一点?在我目前的情况下它不允许我,如何解决这个问题?

希望我对这个问题的解释很清楚。

【问题讨论】:

    标签: c# asp.net-mvc entity-framework code-first


    【解决方案1】:

    试试这个:

    //but two lines below in "OnModelCreating" method in your Context
    
     modelBuilder.Entity<Lookup>().Map<Catalog>(m => m.Requires("IsCatalog").HasValue(true));
     modelBuilder.Entity<Lookup>().Map<CatalogType>(m =>m.Requires("IsCatalog").HasValue(false));
    
    // then :
     context.Lookups.AddOrUpdate(p => new { p.Name , p.IsCatalog},
            new CatalogType
            {
                Name = "General",
                IsActive = true,
                Order = 1,
            },
            new CatalogType
            {
                Name = "Custom",
                IsActive = true,
                Order = 2,
            });
            //context.SaveChanges(); //if you used base.OnModelCreating(modelBuilder);
            base.OnModelCreating(modelBuilder); // then you don't need to save
    

    【讨论】:

    • 这个解决方案会在 Lookup 表中创建一个 IsCatalog 列,对吗?我正在尝试使用已经存在的列鉴别器
    • 是的,如果你没有像我使用 map 那样指定 Discriminator 列(你也可以指定 type 和 value )......无论如何,它将创建自己的鉴别器(默认鉴别器)尝试使用它新的 {p.Name , p.Discriminator } .. 注意:默认鉴别器类型:位(真/假)
    • 我试过你的代码,这里的问题是我无法添加这个映射条件,因为 Catalog 是 TPC,CatalogType 是 TPH,EF 不会接受这个实现
    • 问题不是单独存在于 TPH 或 TPC 中,我试图做的是将 TPH 和 TPC 都继承自同一类查找,这在谷歌搜索后实现映射条件时是不允许的
    • BINGO,编辑你的答案,我会给你赏金
    【解决方案2】:

    在搜索了这个主题后,我得到了这个结果

    1. TPH 将使用鉴别器字段来区分派生类
    2. TPC 不依赖于鉴别器字段,因为继承类的主键与派生类的主键相同
    3. 当尝试将数据添加到目录并且我设置约束时(如果名称重复,则进行更新否则创建),EF 未能设置鉴别器='目录',因为它是 TPC,因此更新将失败,因为表包含其他数据“常规”
    4. 在尝试添加映射条件时,EF 不允许同时为 TPC 和 TPH 使用相同的继承类。

    希望这将帮助其他人像我一样遇到同样的问题

    【讨论】:

      猜你喜欢
      • 2015-01-21
      • 2014-03-09
      • 2013-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-05
      相关资源
      最近更新 更多