【问题标题】:Upsert with composite key?用复合键更新?
【发布时间】:2014-11-05 14:32:35
【问题描述】:

使用 EF6.1,我正在使用具有如下复合键的表:

如何使用 Entity Framework 运行 upsert 方法?

我编写了以下方法,但我读到它不应该用于 upserts,只能用于迁移(请暂时忽略设计模式):

public void UpsertNumberOfMarkets(List<Entities.NumberOfMarkets> marketsList)
{
    using (MyDbContext db = new MyDbContext())
    {
        foreach (var market in marketsList)
        {
            db.NumberOfMarkets.AddOrUpdate(market);
        }
    }
}

我也不确定它是否正常工作。有什么想法吗?我想避免删除和插入,因为我们有一个用于更新的审计日志表。

编辑:我编写了以下可以处理此问题的方法 - 这是首选方法吗?

public void UpsertNumberOfMarkets(List<Entities.NumberOfMarkets> marketsList)
{
    using (MyDbContext db = new MyDbContext())
    {
        foreach (var market in marketsList)
        {
            var predicate = PredicateBuilder.True<Entities.NumberOfMarkets>();
            predicate = predicate.And(n => n.ProjectId == market.ProjectId);
            predicate = predicate.And(n => n.Year == market.Year);

            var existingMarketEntry = db.NumberOfMarkets.AsExpandable().Where(predicate).FirstOrDefault();

            if (existingMarketEntry != null)
                existingMarketEntry.Markets = market.Markets;
            else
            {
                db.NumberOfMarkets.Add(market);
            }
        }
        db.SaveChanges();
    }
}

【问题讨论】:

  • 唯一的问题是existingMarketEntry.Markets = market.Markets;不应覆盖现有市场条目的主键值。在这种情况下,它可能不起作用。

标签: c# entity-framework


【解决方案1】:

Yes.AddOrUpdate 只能用于迁移,原因如下

它更新所有提供的值,但将所有其他值标记为 NULL(未提供),这可能不是我们在现实世界应用程序中想要的行为。

在您的情况下,您可以按照以下步骤操作

using (MyDbContext db = new MyDbContext())
        {
            foreach (var market in marketsList)
            {
                var existingMarket =
                    db.Markets.FirstOrDefault(x => x.ProjectID == market.ProjectID && x.Year == market.Year);
                if (existingMarket != null)
                {
                    //Set properties for existing market
                     existingMarket.Year == market.Year
                     //etc
                }
                else
                {

                    db.Markets.Add(market);
                }
                db.SaveChanges();
            }
        }

【讨论】:

  • 第一个点不正确。可以指定其他属性代替主键 AddOrUpdate(p => new { p.FirstName, p.LastName }, people);
  • 谢谢。更新了答案
  • 但是,您编写的代码可能会在并发条件下导致唯一索引冲突。参见例如depesz.com/2012/06/10/why-is-upsert-so-complicated
猜你喜欢
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 2015-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多