如果同一实体包含在实体的不同集合中,如何更改实体的状态

时间:2017-09-26 13:04:41

标签: c# .net entity-framework entity-framework-6

我试图插入名为Document的新实体:

public class Document
{
    public int Id { get; set; }    

    public virtual ICollection<User> UsersOne { get; set; }

    public virtual ICollection<User> UsersTwo { get; set; }
}

实体文档与实体用户具有两对多关系:

public class User
{
    public int Id { get; set; }

    [Required]
    public string Email { get; set; }

    [Required]
    public string Password { get; set; }
}

在我的请求中,我发送以下Json:

{
    "UsersOne": [{"Id": 1},{"Id": 2},{"Id": 3}],
    "UsersTwo": [{"Id": 1},{"Id": 2},{"Id": 3}],
    "Id": 0 
}

问题是我在上下文中有用户,当我在上下文_context.Document.Add(entity);中添加实体文档时,实体会在添加状态的上下文中插入用户。

也许一种解决方案是改变状态以保持不变:

foreach (var user in entity.UsersOne)
    _context.Entry(user).State = EntityState.Unchanged;

foreach (var user in entity.UsersTwo)
    _context.Entry(user).State = EntityState.Unchanged;

但是当我这样做时,我有以下错误

  

保存或接受更改失败,因为多个实体的类型为&#39; Entity.User&#39;具有相同的主键值。确保显式设置的主键值是唯一的。

我还尝试将两个集合合并为一个,并更改其状态,但上下文仍然具有添加状态的用户。

我还尝试将用户状态更改为已分离,然后将文档添加到上下文中,但在_context.SaveChangesAsync();上,类型为&#39; System.Data.Entity.Validation.DbEntityValidationException&#39;抛出,因为用户需要属性电子邮件和密码。

1 个答案:

答案 0 :(得分:0)

您有两种选择:

  1. 如果正在创建用户实体并将其添加到两个不同的列表中,则必须先自行创建并保存用户实体,然后返回并将新创建的用户添加到两个列表中。

  2. 反序列化JSON时,必须创建单个User实体并将同一实例添加到两个集合中。否则,EF会认为它们是具有相同PK的两个不同的用户实体并抛出该异常。如果您向两者添加相同的实例,EF应该识别它是相同的用户并正确保存。

  3. 最后,如果您只使用Id保存此User实体,您将在Email和Password上获得所需的错误,因为那里有[Required]注释。