我创建了一些模型,添加了迁移,然后执行了更新数据库操作,但在我上次更新数据库操作时,我收到了错误消息:
序列包含多个元素
您可以在下面找到我的迁移配置:
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; }
}
知道怎么解决吗?
答案 0 :(得分:20)
序列包含多个元素
尝试使用AddOrUpdate
指定标识符表达式(例如p => p.CategoryName
)时会导致此异常。可能有两个Categories
具有相同的名称" Sport"或"音乐"。
这可能发生在Subcategories
和Services
上,Subcategories
使用p => p.SubcategoryName
而Services
使用p => p.ServiceType
。
您需要先在数据库中清除重复的条目。这是必须的,因为你想使用AddOrUpdate
,在内部这段代码将使用SingleOrDefault
,如果找到多个匹配元素,将抛出异常。
对象引用未设置为对象的实例
此错误可能是由此代码引起的。
Category = { CategoryName = "Sport" },
Subcategory = { SubcategoryName = "Football" }
默认情况下,创建新的Service
将为空Category
,您无法直接设置CategoryName
。
添加新服务时出现问题。我想使用已添加的类别和子类别。
Categories
和Subcategories
应存储在变量中,以便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