实体框架代码 第一个唯一索引外键引发 DbUpdate 异常

本文关键字:DbUpdate 异常 索引 框架 代码 第一个 唯一 实体 | 更新日期: 2023-09-27 18:36:59

以下是属性和上下文代码:

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

结果,我收到此错误:

类型的未处理异常 "System.Data.Entity.Infrastructure.DbUpdateException"发生在 实体框架.dll无法在对象中插入重复的键行 '哎呀。具有唯一索引"成员唯一索引"的成员"。重复键 值是(约翰,史密斯)。该语句已终止。

奇怪的是,如果我在添加示例的同时运行该方法,该方法工作正常并按预期设置 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();
}

但这会产生一个新问题:

"违反主键约束'PK_dbo。成员'。无法插入 对象'dbo'中的重复键。成员'。重复的键值为 (0)。''r'语句已终止。"

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

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

实体框架代码 第一个唯一索引外键引发 DbUpdate 异常

实体框架正在重新添加您的所有者(成员)。有几种方法可以解决这个问题,但是由于您有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

编辑:首先,我强烈建议您在命名导航类和键时遵循一些约定。您将导航类称为"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();