C# 如何在保存前检查重复项?

C# 如何在保存前检查重复项?,c#,entity-framework,duplicates,C#,Entity Framework,Duplicates,我花了很长时间才弄明白如何将这样的实体添加到我的数据库中 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 publi

我花了很长时间才弄明白如何将这样的实体添加到我的数据库中

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

   ....
}
public class ThingWithListings
{
公共虚拟ICollection列表;
}
公共类列表
{
公共int Id;
公共虚拟ListingData数据{get;set;}//对ListingData具有FK
公共日期时间创建{get;set;}
}
公共类列表数据
{
public int listing_id;//PK
....
}
我正在从另一个源中检索“ThingWithLIstings”,并将其写入数据库。棘手的是,任何数量的列表都可能报告给相同的ListingData。因此,当我添加或更新带有Listings的东西时,我需要查看ListingData是否已经存在,如果已经存在,就使用它

我是EF的新手,所以我一直在使用作者Vickers文章中的AddOrUpdate:显然,这不适用于这种情况,所以我花了一天左右的时间来尝试找到正确的方法。我将向大家讲述我的主要失败尝试,希望有人能告诉我正确的方法。

var newArrivals=newthingwithlistings();
if (DatabaseContext.ListingData.Any(l => l.listing_id == myId)) 
{   
  //already exists 
}
else 
{   
  //do whatever 
}
newArrivals.Listings=新列表(); newArrivals.Listings.Add( 新清单() { creation=DateTime。现在, ListingData=新的ListingData() { 清单1\u id=1 } }); //具有相同ListingData Listing\u id的另一个列表 newArrivals.Listings.Add( 新清单() { creation=DateTime。现在, ListingData=新的ListingData() { 清单1\u id=1 } }); //虚拟id生成器 int计数器=1; 使用(var ctx=newdatabase1entities()) { //从当前数据库上下文获取ListingData var dbListingData=ctx.ListingData; //新来者 foreach(在newArrivals.Listings中列出项目) { //获取新到达的ListingData的列表id int id=item.ListingData.listing\u id; //从数据库中获取ListingData(如果存在) var listingDataFromDb=dbListingData.FirstOrDefault(i=>i.listing_id==id); //如果没有,则创建它并将其添加到数据库中 if(listingDataFromDb==null) { listingDataFromDb=新ListingData() { //使用新员工的登录id listing_id=item.ListingData.listing_id }; ctx.ListingData.Add(listingDataFromDb); ctx.SaveChanges(); } //使用listingDataFromDb添加列表,它现在引用db ListingData 添加(新清单() { id=计数器+++, creation=item.creation, ListingData=listingDataFromDb }); ctx.SaveChanges(); } }
我假设除了
数据
对象引用之外,您的listing类中还有原始外键字段
listing\u id
。如果没有,我建议添加它

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

然后这个过程非常简单:对于每个到达的
列表
对象,检查其
列表_id
是否出现在预取列表中:

  • 如果是这样,请不要使用
    列表数据
    ——只需添加(或更新)
    列表
    ,包括
    列表id
    属性
  • 如果没有,则添加
    列表
    ,并将
    列表数据
    列表数据
    对象一起设置为新的(添加的)对象。EF将设置键

(请注意,这假设没有并发用户修改ListingData,因此拍摄Id的快照是安全的)

不幸的是,您很可能需要查询整个表以检查每个值是否存在重复。如果有比这更好的方法,我想听听。因此,来自批量传入数据的
listing_id
s可能已经在ListingData表中,也可能不在其中。是吗?你在
列表
中有
列表id
(顺便说一句,名称混乱)吗?Alex,是的,列表id可能已经在表中了。我可以检测到该项目已经存在,没有问题。那又怎么样?在添加列表对象之前,我无法将现有的ListingData分配到列表对象。我尝试添加Listing对象,然后将Listing.ListingData标记为未更改。看起来不可能那么难,所以我想我一定错过了简单的部分。以后,请在你的帖子中添加描述,而不仅仅是代码。:)
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();
    }
}