代码之家  ›  专栏  ›  技术社区  ›  Greg Gum

EntityFrameworkCore插入现有相关项

  •  0
  • Greg Gum  · 技术社区  · 7 年前

    考虑

     public class Item
     {
        public int Id{get;set;}
        public string Name{get;set;}
        public List<ItemTag> ItemTags{get;set;}
     }
    
     public class ItemTag
     {
        public int Id{get;set;}
        public int Name{get;set;}
     }
    

    我现在使用EntityFrameworkCore向项添加一个itemTag。这很管用。

    现在我将第二个itemtag添加到同一个item。保存时,将传递整个对象,包括现有的相关itemtag。EF然后尝试插入现有的itemtag,但失败,异常是“无法将值插入标识列…”

    那么如何防止现有对象被插入呢?

    我的解决方法是循环遍历itemtags,并将任何具有id的设置为entitystate.unchanged以强制它不保存它。但似乎不需要这样的变通办法。

    这是保存项目的代码:

    //Get the current item, so that only updated fields are saved to the database.
    var item = await this.DbContext.Items.SingleAsync(a => a.Id == itemInput.Id);
    item.UpdatedBy = this._applicationUserProvider.CurrentAppUserId;
    item.Updated = DateTimeOffset.UtcNow;
    
    //Use Automapper to map fields.
    this._mapper.Map(itemInput, item);
    
    //Workaround for issue.
    foreach (var itemTag in item.ItemTags)
    {
        var entry = this.DbContext.Entry(itemTag);
        if (itemTag.Id > 0)
        {
            entry.State = EntityState.Unchanged;
        }
    }
    
    await this.SaveChangesAsync();
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Tseng    7 年前

    automapper不适合返回到持久性或域模型。automapper的作者 stated .

    这也不能像ef(core)那样很好地工作 change tracking .

    更改跟踪是基于从数据库加载的实体完成的。当更改实体值时,其状态将从 Unchanged 到 Modified 并将生成一个更新方法。

    当您加载一个没有items关系的实体时(使用eager loading),那么当您添加一个实体时,它将被标记为 Added ,保存时导致插入。

    你也有可能 Attach 和 Detach 实体。

    从链接的博客文章:

    Rowan Miller总结了Github问题(bit.ly/295goxw)中的新行为:

    add:添加尚未跟踪的每个可访问实体。

    附加:附加每个可访问实体,除非可访问实体具有存储生成的密钥且未分配密钥值;这些将标记为已添加。

    更新:与附加相同,但实体被标记为已修改。

    删除:与附加相同,然后将根标记为已删除。因为cascade delete现在发生在savechanges上,这允许cascade规则稍后流向实体。

    因此,您必须附加项目(如果您只想添加不带主键的新项目)或调用 Update/UpdateRange 上 DbSet 用一个键更新和添加没有的键。

    或者,像您已经做的那样,通过设置/更改其跟踪状态来自己处理它。但请记住, 不变 不会更新传递的实体。

        2
  •  0
  •   Edward    7 年前

    用于插入新的 ItemTag ,您可以插入到 ITTAG标签 表直接不反映 Item .

    如下定义模型:

    public class ItemTag
    {
        public int Id { get; set; }
        public int Name { get; set; }
        public int ItemId { get; set; }
        public virtual Item Item { get; set; }
    }
    

    尝试设置 ItemId 对于 ITTAG标签 插入新的 ITTAG标签 对于 项目 .

    如果您愿意插入 项目 具有 ITTAG标签 ,你可以试试 JsonPatchDocument 它描述了如何操作模型。

    尝试引用 JSON Patch With ASP.net Core .

    为了 jsonpatchdocument文件 ,您需要生成 JsonPatchDocument<Item> 在客户端。尝试引用 ASP Core PatchDocument returning Invalid Input .

    推荐文章