簡體   English   中英

實體框架:避免插入重復項

[英]Entity Framework: Avoiding Inserting Duplicates

說,我有以下概念模型,有些標簽有多個標簽(多個,所以它是多對多的關系),加上每個標簽都屬於一個特定的類別。

我的數據來自外部源,在插入之前我想確保沒有添加重復的標簽。

更新的代碼段:

static void Main(string[] args)
    {
        Story story1 = new Story();
        story1.Title = "Introducing the Entity Framework";
        story1.Tags.Add(new Tag { Name = ".net",  });
        story1.Tags.Add(new Tag { Name = "database" });

        Story story2 = new Story();
        story2.Title = "Working with Managed DirectX";
        story2.Tags.Add(new Tag { Name = ".net" });
        story2.Tags.Add(new Tag { Name = "graphics" });

        List<Story> stories = new List<Story>();
        stories.Add(story1);
        stories.Add(story2);

        EfQuestionEntities db = new EfQuestionEntities();

        Category category = (from c in db.Categories
                             where c.Name == "Programming"
                             select c).First();

        foreach (Story story in stories)
        {
            foreach (Tag tag in story.Tags)
            {
                Tag currentTag = tag;
                currentTag = GetTag(tag.Name, category, db);
            }

            db.Stories.AddObject(story);
        }

        db.SaveChanges();
    }

    public static Tag GetTag(string name, Category category, EfQuestionEntities db)
    {
        var dbTag = from t in db.Tags.Include("Category")
                    where t.Name == name
                    select t;

        if (dbTag.Count() > 0)
        {
            return dbTag.First();
        }

        var cachedTag = db.ObjectStateManager.GetObjectStateEntries(EntityState.Added).
            Where(ose => ose.EntitySet == db.Tags.EntitySet).
            Select(ose => ose.Entity).
            Cast<Tag>().Where(x => x.Name == name);

        if (cachedTag.Count() != 0) 
        {
            return cachedTag.First();
        }

        Tag tag = new Tag();
        tag.Name = name;
        tag.Category = category;

        db.Tags.AddObject(tag);

        return tag;
    }

但是,我得到一個異常,該對象具有與ObjectContext中已存在的相同的EntityKey。

此外,如果我刪除else語句,我將獲得有關違反FK約束的異常,因此它的Category屬性似乎設置為null。

我和EF有同樣的問題。 這是我最終做的事情:

  1. 而不是自己做story1.Tags.Add(new Tag { Name = ".net", }) ,通過這樣的幫助方法路由所有Tag創建: story1.Tags.Add(GetTag(".net"))
  2. GetTag方法檢查上下文中的標記,以查看它是否應該返回現有實體,就像您一樣。 如果是,則返回該值。
  3. 如果沒有現有實體,它會檢查ObjectStateManager以查看是否有Tag實體添加到上下文但尚未寫入db。 如果找到匹配的Tag ,則返回該Tag
  4. 如果它仍然沒有找到Tag ,它會創建一個新Tag ,將其添加到上下文中,然后返回它。

實質上,這將確保在整個程序中將使用任何Tag的任何實例(無論是已存在還是剛創建)。

一些示例代碼從我的項目中解除(使用InventoryItem而不是Tag ,但是你明白了)。

步驟3中的檢查是這樣完成的:

// Second choice: maybe it's not in the database yet, but it's awaiting insertion?
inventoryItem = context.ObjectStateManager.GetObjectStateEntries(EntityState.Added)
    .Where(ose => ose.EntitySet == context.InventoryItems.EntitySet)
    .Select(ose => ose.Entity)
    .Cast<InventoryItem>()
    .Where(equalityPredicate.Compile())
    .SingleOrDefault();

if (inventoryItem != null) {
    return inventoryItem;
}

如果在步驟3中找不到Tag ,則這是步驟4的代碼:

inventoryItem = new InventoryItem();
context.InventoryItems.AddObject(inventoryItem);
return inventoryItem;

更新:

它應該像這樣使用:

Story story1 = new Story();
story1.Title = "Introducing the Entity Framework";
story1.Tags.Add(GetTag(".net", category, db));
story1.Tags.Add(GetTag("database", category, db));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM