【问题标题】:Sequence contains more than one element error in EF CF Migrations序列在 EF CF 迁移中包含多个元素错误
【发布时间】:2014-08-10 22:49:40
【问题描述】:

我创建了一些模型,添加了迁移,然后进行了更新数据库操作,但在我上次更新数据库操作时,我收到了错误消息:

序列包含多个元素

您可以在下面找到我的迁移配置:

context.Categories.AddOrUpdate(p => p.CategoryName,
    new Category
    {
        CategoryName = "Sport"
    },
    new Category
    {
        CategoryName = "Music"
    }
);

context.Subcategories.AddOrUpdate(p => p.SubcategoryName,
    new Subcategory
    {
        SubcategoryName = "Football"
    },
    new Subcategory
    {
        SubcategoryName = "Basketball"
    },
    new Subcategory
    {
        SubcategoryName = "Piano"
    },
    new Subcategory
    {
        SubcategoryName = "Violin"
    }
);

context.Services.AddOrUpdate(p => p.ServiceType,
    new Service
    {
        ServiceType = "Football player",
        Category = { CategoryName = "Sport" },
        Subcategory = { SubcategoryName = "Football" }
    },
    new Service 
    {
        ServiceType = "Piano lessons",
        Category = { CategoryName = "Music" },
        Subcategory = { SubcategoryName = "Piano" }
    }
);

当我添加新服务时出现问题。我已经有了类别和子类别,如果我喜欢Category = new Category { CategoryName = "Music" },那么它可以工作,但我在我的数据库中获得了两次音乐条目(对于这个例子)。我想使用已经添加的类别和子类别。您还可以在下面找到我的模型定义。

public class Category
{
    [Key]
    public int CategoryID { get; set; }

    public string CategoryName { get; set; }
}

// Subcategory is defined the same way...

public class Service
{
    public int ServiceID { get; set; }

    public string ServiceType { get; set; }

    public virtual Category Category { get; set; }

    public virtual Subcategory Subcategory { get; set; }

}

知道怎么解决吗?

【问题讨论】:

  • @YuliamChandra 这不是答案。
  • 为什么不使用p => p.CategoryIDp => p.SubcategoryID 之类的东西?
  • 数据库中可能存在重复的Piano lessonsAddOrUpdate 基于重复条目ServiceType 将不起作用,因为您使用p => p.ServiceType
  • @YuliamChandra 如果我将它们更改为 p.CategoryID 和 p.SubcategoryID,我会在更新数据库时收到另一条错误消息:对象引用未设置为对象的实例。

标签: c# entity-framework entity-framework-migrations


【解决方案1】:

序列包含多个元素

此异常是在尝试使用 AddOrUpdate 并指定标识符表达式时引起的,例如 p => p.CategoryName。可能有两个Categories 具有相同的名称“运动”或“音乐”。

这也可能发生在SubcategoriesServicesSubcategories 使用p => p.SubcategoryNameServices 使用p => p.ServiceType

您需要先清除数据库上的重复条目。这是必须的,因为你要使用AddOrUpdate,所以在内部这段代码会使用SingleOrDefault,如果找到多个匹配元素,就会抛出异常。

对象引用未设置为对象的实例

这个错误可能是由这段代码引起的。

Category = { CategoryName = "Sport" },
Subcategory = { SubcategoryName = "Football" }

新建Service默认会有空的Category,不能直接设置CategoryName

添加新服务时出现问题。我想使用已经添加的类别和子类别。

CategoriesSubcategories 应该存储在变量中,以便Service 可以使用。

var sportCategory = new Category { CategoryName = "Sport" };
var musicCategory = new Category { CategoryName = "Music" };
context.Categories.AddOrUpdate(p => p.CategoryName, 
   sportCategory, musicCategory);

var footballSub = new Subcategory { SubcategoryName = "Football" };
var basketballSub = new Subcategory { SubcategoryName = "Basketball" };
var pianoSub = new Subcategory { SubcategoryName = "Piano" };
var violinSub = new Subcategory { SubcategoryName = "Violin" };
context.Subcategories.AddOrUpdate(p => p.SubcategoryName,
   footbalSub, basketballSub , pianoSub, violinSub);

context.Services.AddOrUpdate(p => p.ServiceType,
    new Service
    {
        ServiceType = "Football player",
        Category = sportCategory,
        Subcategory = footballSub
    },
    new Service 
    {
        ServiceType = "Piano lessons",
        Category = musicCategory,
        Subcategory = pianoSub
    }
);

但上面的代码还是有问题,如果服务是新实体,现有的运动类别和现有的足球子类别也会被添加。您可以阅读this article 以获得进一步的解释。

解决方案

Service 上还需要有外键值,不仅是外键引用,以防止添加现有类别和现有子类别。

[ForeignKey("Category")]
public int CategoryId { get; set; }
[ForeignKey("Subcategory")]
public int SubcategoryId { get; set; }

然后运行迁移。

Add-Migration AddServiceFKValues

并手动分配temporary primary key 并在定义服务时使用它。处理现有实体时不需要此临时主键,但如果有多个新类别或子类别,则可能会出现另一个问题。为避免这种情况,最好使用临时主键,调用AddOrUpdate后,每个实体主键如果是现有实体,都会更新。

var sportCategory = new Category { CategoryID = 1000, CategoryName = "Sport" };
var musicCategory = new Category { CategoryID = 1001, CategoryName = "Music" };
context.Categories.AddOrUpdate(p => p.CategoryName, 
   sportCategory, musicCategory);

var footballSub = new Subcategory { SubcategoryID = 1000, SubcategoryName = "Football" };
var basketballSub = new Subcategory { SubcategoryID = 1001, SubcategoryName = "Basketball" };
var pianoSub = new Subcategory { SubcategoryID = 1002, SubcategoryName = "Piano" };
var violinSub = new Subcategory { SubcategoryID = 1003, SubcategoryName = "Violin" };
context.Subcategories.AddOrUpdate(p => p.SubcategoryName,
   footbalSub, basketballSub , pianoSub, violinSub);

context.Services.AddOrUpdate(p => p.ServiceType,
    new Service
    {
        ServiceType = "Football player",
        CategoryID = sportCategory.CategoryID,
        SubcategoryID = footballSub.SubcategoryID
    },
    new Service 
    {
        ServiceType = "Piano lessons",
        CategoryID = musicCategory.CategoryID,
        SubcategoryID = pianoSub.SubcategoryID
    }
);

然后更新数据库。

Update-Database

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 1970-01-01
    • 2017-09-26
    • 1970-01-01
    • 2012-09-12
    • 1970-01-01
    相关资源
    最近更新 更多