Entity Framework 代码优先唯一索引外键抛出 DbUpdate 异常

Entity Framework Code First unique index foreign key throws DbUpdate Exception

这是实体和上下文代码:

public class Family
{
    public int FamilyID { get; set; }
    public String address { get; set; }
    public virtual ICollection<Member> FamilyMembers { get; set; }
}
public class Member
{
    [Index("MemberUniqueID", IsUnique = true)]
    public int MemberID { get; set; }

    [StringLength(50)] [Index("MemberUniqueIndex", 1, IsUnique = true)]
    public String name { get; set; }
    [StringLength(50)] [Index("MemberUniqueIndex", 2, IsUnique = true)]
    public String surname { get; set; }

    public int age { get; set; }
    public int FamilyID { get; set; }
    public virtual Family Family { get; set; }
}
public class Bicycle
{
    public int BicycleID { get; set; }
    public virtual Member Owner { get; set; }
}
public class MyContext : DbContext
{
    public MyContext : base () { }
    public DbSet<Member> MemberDB { get; set; }
    public DbSet<Family> FamilyDB { get; set; }
    public DbSet<Bicycle> BicycleDB { get; set; }
}

现在,我为每个添加几个示例,添加它们并 SaveChanges();。然后我尝试 运行 这个代码:

    public void bicycle_set_FK(int IDbicycle, int IDmember)
{
       var bicycleToFind = BicycleDB.Find(IDbicycle);
       var memberToSetAsFK = MemberDB.Find(IDmember);
       bicycleToFind.Owner = memberToSetAsFK;
       SaveChanges();
}

结果,我得到了这个错误:

An unhandled exception of type 'System.Data.Entity.Infrastructure.DbUpdateException' occurred in EntityFramework.dll Cannot insert duplicate key row in object 'dbo.Members' with unique index 'MemberUniqueIndex'. The duplicate key value is (John, Smith). The statement has been terminated.

奇怪的是,如果我 运行 在添加示例的同时使用该方法,该方法可以正常工作并按预期设置 FK。但是,如果我首先使用代码的第一个 运行 添加示例,然后尝试在代码的第二个 运行 上设置 FK,它会抛出该异常。

编辑:

好的,我已经按照建议完成了,在阅读了您链接的文章后,我得到了这个:

[ForeignKey("MemberID")]
public int? OwnerID { get; set; }
public virtual Member MemberID { get; set; }

方法如下所示:

public void bicycle_set_FK(int IDbicycle, int IDmember)
{
   var bicycleToFind = BicycleDB.Find(IDbicycle);
   bicycleToFind.MemberID = null;
   bicycleToFind.OwnerID = IDmember;
   SaveChanges();
}

但这会产生一个新问题:

"Violation of PRIMARY KEY constraint 'PK_dbo.Members'. Cannot insert duplicate key in object 'dbo.Members'. The duplicate key value is (0).\r\nThe statement has been terminated."

我使用的值是 1 和 3 (bicycle_set_FK(1, 3);)。成员包含 3 行 ID:1、2 和 3。那么它在哪里找到零,因为它不在数据库中,我也没有在代码中的任何位置输入它?

还有一件事:这篇文章没有提到如何在一对多关系中解决这个问题。如何在家庭和成员之间添加 FK?我是否添加一些 属性 例如 public List<Member> FamilyMembersFK

Entity framework 正在重新添加您的所有者(成员)。有几种解决方法,但既然你有 FK,试试这个:

public class Bicycle
{
    public int BicycleID { get; set; }

    public int MemberID { get; set; }  // You can call this ownerId, but then you need to setup the relationship with annotation or fluent
    public virtual Member Owner { get; set; }
}

public void bicycle_set_FK(int IDbicycle, int IDmember)
{
   var bicycleToFind = BicycleDB.Find(IDbicycle);
   // var memberToSetAsFK = MemberDB.Find(IDmember); ** Don't need to do this since you have FK **
   bicycleToFind.MemberId = IDmember;
   SaveChanges();
}

https://msdn.microsoft.com/en-us/magazine/dn166926.aspx?f=255&MSPPError=-2147217396

编辑:首先,我强烈建议您在命名导航 classes 和键时遵循一些约定。您正在调用您的导航 class "MemberId" - 这非常令人困惑。如果您希望 FK 为 OwnerId,请使用以下内容:

public int? OwnerID { get; set; }

[ForeignKey("OwnerID")]
public virtual Member Owner { get; set; }

其次,您不需要此注释:

//[Index("MemberUniqueID", IsUnique = true)]  **MemberID will be a identity key by default so it will have a unique index created.
public int MemberID { get; set; }

现在您可以像这样插入现有所有者:

public void bicycle_set_FK(int IDbicycle, int IDmember)
{
   var bicycleToFind = BicycleDB.Find(IDbicycle);
   bicycleToFind.OwnerID = IDmember;  // Don't worry about the nav class, just set the FK
   SaveChanges();
}

关于一对多,您已经配置了:

public virtual ICollection<Member> FamilyMembers { get; set; }

所以要添加一个新成员:

var newMember = new Member {
    Name = "Joe",
    Surname = "Smith",
    Age = 30,
    FamilyId = familyId
};

context.Members.Add(newMember);
SaveChanges();