Sequence在EF CF Migrations中包含多个元素错误

11 c# entity-framework ef-migrations

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

序列包含多个元素

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

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" }
    }
);
Run Code Online (Sandbox Code Playgroud)

添加新服务时会出现问题.我已经有类别和子类别,如果我喜欢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; }

}
Run Code Online (Sandbox Code Playgroud)

知道怎么解决吗?

Yul*_*dra 21

序列包含多个元素

尝试使用AddOrUpdate指定标识符表达式时会导致此异常,例如p => p.CategoryName.可能有两个Categories具有相同名称"Sport"或"Music".

这也可能发生在SubcategoriesServices,Subcategories使用p => p.SubcategoryNameServices用途p => p.ServiceType.

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

你调用的对象是空的

此错误可能是由此代码引起的.

Category = { CategoryName = "Sport" },
Subcategory = { SubcategoryName = "Football" }
Run Code Online (Sandbox Code Playgroud)

默认情况下,创建new Service将为null 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
    }
);
Run Code Online (Sandbox Code Playgroud)

但是上面的代码仍有问题,如果服务是新实体,那么现有的运动类别和现有的足球子类别也将被添加.您可以阅读本文以获得进一步说明.

您还需要Service在外键引用上还具有外键值,以防止添加现有类别和现有子类别.

[ForeignKey("Category")]
public int CategoryId { get; set; }
[ForeignKey("Subcategory")]
public int SubcategoryId { get; set; }
Run Code Online (Sandbox Code Playgroud)

然后运行迁移.

Add-Migration AddServiceFKValues
Run Code Online (Sandbox Code Playgroud)

并手动分配临时主键并在定义服务时使用它.处理现有实体时不需要此临时主键,但如果有多个新类别或子类别,则可能存在其他问题.为了防止这种情况,最好使用临时主键,在调用之后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
    }
);
Run Code Online (Sandbox Code Playgroud)

然后更新数据库.

Update-Database
Run Code Online (Sandbox Code Playgroud)