实体框架代码首先多对多创建重复行

Dan*_*his 8 c# repository-pattern code-first entity-framework-4

我的问题结果是有两个上下文.我重新编写了我的代码,只有一个上下文,我的问题就消失了.

我有一个User,它有一个UserContact列表,它本身有一个ContactOption.它是一个相当简单的1到多个,多对1,中间有UserContact表.

如果我将用户拉出数据库并创建一个新的UserContact,但将ContactOption设置为现有项目(我从数据库中取出),当我保存更改时,实体框架在数据库中创建一个新的ContactOption,基本上是我添加到UserContact的副本(除了它获得一个新的id).

我已经与它斗争了好几个小时,无法解决这个问题.有任何想法吗?

我正在使用Repository模式进行数据库查询,但我确保它们共享相同的上下文.

我用这个将用户拉出数据库:

var user = _context.Users.Include("UserContacts.ContactOption")
              .Where(id => id == 1);
Run Code Online (Sandbox Code Playgroud)

并提供以下联系方式:

var co = _context.ContactOptions.FirstOrDefault(c => c.Id == id);
Run Code Online (Sandbox Code Playgroud)

我将ContactOption添加到UserContact,如下所示:

var contactOption = _context.ContactOptions.FirstOrDefault(c => c.Id == someId);

var contact = new UserContact { ContactOption = contactOption  };
contact.Data = "someData";

user.UserContacts.Add(contact);
Run Code Online (Sandbox Code Playgroud)

我的模型看起来像这样:

public class User
{
    [Key]
    public int Id { get; set; }

    public virtual ICollection<UserContact> UserContacts { get; set; }
}

public class UserContact
{
    [Key]
    public int Id { get; set; }

    [Required]
    public User User { get; set; }

    [Required]
    public ContactOption ContactOption { get; set; }
    public string Data { get; set; }
}

public class ContactOption
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

Mor*_*avi 2

我运行您的代码并得到了确切的预期结果: UserContacts表中的一个新行包含现有的 UserId 和 ContactOptionId,因此我不确定其中发生了什么,但您可以尝试在 UserContact 对象中显式包含 FK,以便您可以完全控制 Code First 如何为您插入记录。为此,您需要更改 UserContact,如下所示:

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

    // By Convention these 2 properties will be picked up as the FKs: 
    public int UserId { get; set; }
    public int ContactOptionId { get; set; }

    [Required]
    public User User { get; set; }        
    [Required]
    public ContactOption ContactOption { get; set; }

    public string Data { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样改变你的代码:

var contactOption = _context.ContactOptions.Find(someId);
var user = _context.Users.Find(1);

var contact = new UserContact 
{ 
    ContactOptionId = contactOption.Id,  
    UserId = user.Id,
    Data = "someData"
};

user.UserContacts.Add(contact);
context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)