ber*_*kyi 19 c# entity-framework upsert entity-framework-5
我正在使用基于Code-First DBContext的EF5设置.
在DbMigrationsConfiguration.Seed我试图用默认的虚拟数据填充数据库.为了完成这个任务,我使用DbSet.AddOrUpdate方法.
最简单的代码来说明我的目标:
j = 0;
var cities = new[]
{
"Berlin",
"Vienna",
"London",
"Bristol",
"Rome",
"Stockholm",
"Oslo",
"Helsinki",
"Amsterdam",
"Dublin"
};
var cityObjects = new City[cities.Length];
foreach (string c in cities)
{
int id = r.NextDouble() > 0.5 ? 0 : 1;
var city = new City
{
Id = j,
Name = c,
Slug = c.ToLowerInvariant(),
Region = regions[id],
RegionId = regions[id].Id,
Reviewed = true
};
context.CitySet.AddOrUpdate(cc => cc.Id, city);
cityObjects[j] = city;
j++;
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用/省略Id字段以及使用Id/ Slugproperty作为更新选择器.
当Update-Database运行时,Id字段被忽略,并且是由SQL Server自动生成的值和DB填充有重复; Slug选择器允许重复,并在后续运行中产生异常(Sequence contains more than one element).
AddOrUpdate方法是否以这种方式工作?我应该手动执行upsert吗?
Ger*_*old 28
首先(尚未回答),AddOrUpdate可以使用新对象数组调用,因此您只需创建一个类型数组City[]并调用context.CitySet.AddOrUpdate(cc => cc.Id, cityArray);一次.
(编辑)的
其次,AddOrUpdate使用标识符expression(cc => cc.Id)来查找与Id数组中的城市相同的城市.这些城市将会更新.将插入数组中的其他城市,但它们的Id值将由数据库生成,因为Id它是标识列.它不能通过insert语句设置.(除非您设置标识插入).因此,当使用AddOrUpdate具有标识列的表时,您应该找到另一种标识记录的方法,因为现有记录的Id值是不可预测的.
在你的情况下,你用作Slug标识符AddOrUpdate,它应该是唯一的(根据你的评论).我不清楚为什么不更新匹配Slugs的现有记录.
我设置了一个小测试:添加或更新具有Id(iedntity)和唯一名称的实体:
var n = new Product { ProductID = 999, ProductName = "Prod1", UnitPrice = 1.25 };
Products.AddOrUpdate(p => p.ProductName, n);
SaveChanges();
Run Code Online (Sandbox Code Playgroud)
当"Prod1"还没有时,它被插入(忽略Id 999).
如果它是UnitPrice不同的,则会更新.
查看发出的查询,我看到EF正在寻找名称的唯一记录:
SELECT TOP (2)
[Extent1].[ProductID] AS [ProductID],
[Extent1].[ProductName] AS [ProductName],
[Extent1].[UnitPrice] AS [UnitPrice]
FROM [dbo].[Products] AS [Extent1]
WHERE N'Prod1' = [Extent1].[ProductName]
Run Code Online (Sandbox Code Playgroud)
接下来(当匹配被发现并且UnitPrice不同时)
update [dbo].[Products]
set [UnitPrice] = 1.26
where ([ProductID] = 15)
Run Code Online (Sandbox Code Playgroud)
这表明EF找到了一条记录,现在使用密钥字段进行更新.
我希望看到这个例子能够说明你的情况.也许你应该监视sql语句,看看是否有意外的事情发生.