EntityFrameworkCore插入现有的相关项目

时间:2018-11-18 11:55:35

标签: asp.net-core entity-framework-core asp.net-core-2.1 entity-framework-core-2.1

考虑

 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;}
 }

我现在使用实体框架核心将ItemTag添加到Item。这样就可以了。

现在,我将第二个ItemTag添加到同一项目。保存时,将传递整个对象,包括现有的相关ItemTag。 EF然后尝试插入现有的ItemTag,但失败,但出现“无法将值插入到身份列...”

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

我的解决方法是遍历ItemTags,并将所有具有ID的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 个答案:

答案 0 :(得分:1)

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

这也不能像EF(核心)执行change tracking的方式一样有效。

基于从数据库加载的实体,完成了更改跟踪。更改实体值时,其状态从Unchanged变为Modified,并会导致更新方法。

当您加载没有项目关系的实体时(使用紧急加载),那么当您添加实体时,它将被标记为Added,并在保存时插入。

您还可以使用AttachDetach实体。

来自链接的博客文章:

  

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

     

添加:添加所有尚未跟踪的可达实体。

     

附加:附加每个可访问实体,除非可访问实体具有商店生成的键并且未分配键值;这些将被标记为已添加。

     

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

     

删除:与“附加”相同,然后将根标记为已删除。由于级联删除现在发生在SaveChanges上,因此以后级联规则可以流到实体。

因此,您必须附加您的项目(如果您只想添加带有主键的新项目)或致电Update/UpdateRange上的DbSet,以使用密钥更新项目并添加没有的。

您也可以通过设置/更改其跟踪状态来自己处理它。但是请记住,Unchanged不会更新传递的实体。

答案 1 :(得分:0)

要插入新的ItemTag,可以直接插入到ItemTag表中,而不反映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设置ItemTag,为ItemTag插入新的Item

如果您喜欢将Item插入ItemTag,则可以尝试使用JsonPatchDocument来描述如何操作模型。

尝试参考JSON Patch With ASP.net Core

对于JsonPatchDocument,您需要在客户端生成JsonPatchDocument<Item>。尝试引用ASP Core PatchDocument returning Invalid Input