AddOrUpdate作品未如预期,并产生重复(AddOrUpdate works not as e

2019-07-04 19:01发布

我使用基于的DbContext-代码优先EF5设置。

DbMigrationsConfiguration.Seed我试图填补DB使用默认的虚拟数据。 为了完成这个任务,我用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++;
}

我试着使用/省略Id字段以及使用Id / Slug财产更新选择。

Update-Database运行, Id字段被忽略,并且由SQL Server和DB充满了重复自动产生价值; Slug选择器允许重复和在随后的运行中产生异常( Sequence contains more than one element )。

AddOrUpdate意法这样的工作方式? 我应该用手工进行更新插入?

Answer 1:

第一(无应答还), AddOrUpdate可以用新的对象的数组调用,所以可以只创建类型的数组City[]和呼叫context.CitySet.AddOrUpdate(cc => cc.Id, cityArray); 一旦。

(编辑)的

第二, AddOrUpdate使用标识符表达式( cc => cc.Id ),以找到具有相同城市Id为所述阵列中的那些。 这些城市将被更新。 阵列中的其它城市将被插入,但它们的Id值将由数据库来产生,因为Id是标识列。 它不能由一个INSERT语句来设置。 (除非你设置标识插入)。 因此,在使用时AddOrUpdate的表与标识列,你应该找到另一种方式来识别记录,因为现有记录的ID值是不可预测的。

在你的情况下,你使用的Slug作为标识符AddOrUpdate ,这应该是唯一的(根据您的评论)。 这不是很清楚,我为什么不相匹配的更新现有记录Slug秒。

我建立了一个小测试:添加或更新的ID(iedntity)和一个唯一的名称实体:

var n = new Product { ProductID = 999, ProductName = "Prod1", UnitPrice = 1.25 };
Products.AddOrUpdate(p => p.ProductName, n);
SaveChanges();

当“PROD1”现在还没有,它被插入(忽略编号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]

而旁边(当匹配被发现, UnitPrice是不同的)

update [dbo].[Products]
set [UnitPrice] = 1.26
where ([ProductID] = 15)

这表明,EF发现一个记录,现在使用的关键领域做了更新。

我希望看到这个例子将阐明你的情况的一些情况。 也许你应该监控的SQL语句以及并查看是否有意外发生在那里。



Answer 2:

var paidOutType = new List<PaidOutType>
                {
                    new PaidOutType { PaidOutTypeID = 1, Code = "001", Description = "PAID OUT 1", PType = "1", Amount = 0, IsSalesSummery = true,DayFrom=1,DayTo=31 },
                    new PaidOutType { PaidOutTypeID = 2, Code = "002", Description = "PAID OUT 2", PType = "1", Amount = 0, IsSalesSummery = true,DayFrom=1,DayTo=31 },
                    new PaidOutType { PaidOutTypeID = 3, Code = "002", Description = "PAID OUT 3", PType = "1", Amount = 0, IsSalesSummery = true,DayFrom=1,DayTo=31 },
                };
                paidOutType.ForEach(u => smartPOSContext.PaidOutType.AddOrUpdate(u));
                smartPOSContext.SaveChanges();


文章来源: AddOrUpdate works not as expected and produces duplicates