【问题标题】:How to check for duplicates before saving?保存前如何检查重复项?
【发布时间】:2012-11-23 21:18:07
【问题描述】:

我花了很长时间弄清楚如何将这样的实体添加到我的数据库中。

public class ThingWithListings
{
    public virtual ICollection<Listing> Listings;
}

public class Listing
{
    public int Id;

    public virtual ListingData Data { get; set; } // has a FK to ListingData
    public DateTime Creation { get; set; }
}

public class ListingData
{
   public int listing_id; // PK

   ....
}

我正在从另一个来源检索“ThingWithLIstings”并将其写入我的数据库。棘手的部分是任何数量的列表都可能报告给相同的列表数据。所以当我添加或更新一个 ThingWithListings 时,我需要查看一个 ListingData 是否已经存在,如果存在,就使用那个。

我是 EF 的新手,所以我一直在使用作者 Vickers 的文章 here 中的 AddOrUpdate:显然,这不适用于这种情况,所以我尝试了一天左右的时间来弄清楚找出正确的方法来做到这一点。我会把我主要失败尝试的所有故事都告诉你,希望有人能告诉我正确的方法。

【问题讨论】:

  • 不幸的是,您很可能必须查询整个表来检查每个值是否有重复。如果有比这更好的方法,我想听听。
  • 因此,来自批量传入数据的listing_ids 可能已经或可能不在ListingData 表中。对吗?
  • 你在Listing 中有listing_id(顺便说一下,这个名字很混乱)吗?

标签: c# entity-framework duplicates


【解决方案1】:
if (DatabaseContext.ListingData.Any(l => l.listing_id == myId)) 
{   
  //already exists 
}
else 
{   
  //do whatever 
}

【讨论】:

  • Alex,是的,listing_id 可能已经在表中。我可以检测到该项目已经存在,没问题。但是然后呢?在添加之前,我无法将现有的 ListingData 分配给 Listing 对象。我尝试添加Listing 对象,然后将Listing.ListingData 标记为未更改。看起来它不可能那么难,所以我想我一定是错过了简单的事情。
  • 以后,请在您的帖子中添加描述,而不仅仅是代码。 :)
【解决方案2】:
var newArrivals = new ThingWithListings();
newArrivals.Listings = new List<Listing>();
newArrivals.Listings.Add(
    new Listing()
    {
        creation = DateTime.Now,
        ListingData = new ListingData()
        {
            listing_id = 1
        }
    });

//another Listing with the same ListingData listing_id
newArrivals.Listings.Add(
    new Listing()
    {
        creation = DateTime.Now,
        ListingData = new ListingData()
        {
            listing_id = 1
        }
    });

//dummy id generator
int counter = 1;
using (var ctx = new Database1Entities())
{
    //get the ListingData from the current db context
    var dbListingData = ctx.ListingData;

    // the new arrivals
    foreach (Listing item in newArrivals.Listings)
    {
        //get the listing_id of a new arrival's ListingData
        int id = item.ListingData.listing_id;

        //get the ListingData from the db, if it exists
        var listingDataFromDb = dbListingData.FirstOrDefault(i => i.listing_id == id);

        //if not, create it and add it to the db
        if (listingDataFromDb == null)
        {
            listingDataFromDb = new ListingData()
                {
                    //use the new arrival's listing_id
                    listing_id = item.ListingData.listing_id
                };
            ctx.ListingData.Add(listingDataFromDb);
            ctx.SaveChanges();
        }

        //add the Listing by using the listingDataFromDb, which now references the db ListingData
        ctx.Listing.Add(new Listing()
        {
            id = counter++,
            creation = item.creation,
            ListingData = listingDataFromDb
        });
        ctx.SaveChanges();
    }
}

【讨论】:

    【解决方案3】:

    我假设除了 Data 对象引用之外,您的清单类中还具有原始外键字段 listing_id。如果没有,我建议添加它。

    您可以从获取列表或数组中现有的listing_ids 开始。这样可以节省以后的大量数据库往返。

    那么这个过程真的很简单:对于每个到达的Listing对象,检查它的listing_id是否出现在预取列表中:

    • 如果是这样,请不要对 ListingData 执行任何操作 - 只需添加(或更新)Listing,包括 listing_id 属性。
    • 如果没有,添加Listing 并将Listing.DataListingData 对象一起设置为新的(添加的)对象。 EF 将设置密钥。

    (注意这里假设没有并发用户在修改ListingData,所以对Id进行快照是安全的)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-04
      • 1970-01-01
      • 2021-03-21
      • 2014-09-03
      • 1970-01-01
      相关资源
      最近更新 更多