实体框架代码第一个唯一索引外键抛出DbUpdate异常 [英] Entity Framework Code First unique index foreign key throws DbUpdate Exception

查看:608
本文介绍了实体框架代码第一个唯一索引外键抛出DbUpdate异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是文字和上下文代码:

  public class Family 
{
public int FamilyID {得到;组; }
public String address {get;组; }
public virtual ICollection< Member>家庭成员{get;组; }
}
public class Member
{
[Index(MemberUniqueID,IsUnique = true)]
public int MemberID {get;组; }

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

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

现在,我添加了几个例子,添加它们和的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'的一个未处理的异常发生在
EntityFramework.dll无法插入重复的键行在对象
'dbo.Members'中使用唯一索引'MemberUniqueIndex'。重复键
值是(John,Smith)。该语句已被终止。


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



编辑:



好的,所以我按照推荐做了,阅读你链接的artice之后,我有了这个:

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

方法如下所示:

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

但这会产生一个新问题:


违反PRIMARY KEY约束PK_dbo.Members'。无法在对象'dbo.Members'中插入
重复键,重复键值为
(0).\\\\
n该语句已被终止。


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


$ b $另外还有一件事:这篇文章没有提到如何以一对多的关系来解决这个问题。如何在家庭和会员之间添加FK?我添加一些属性,如 public List< Member> FamilyMembersFK

解决方案

实体框架是重新添加您的Owner(Member)。有几种方法可以解决这个问题,但是由于你有FK尝试这样做:

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

public int MemberID {get;组; } //您可以调用该ownerId,但是您需要设置与注释或流利的关系
public virtual Member Owner {get;组;
}

public void bike_set_FK(int IDbicycle,int IDmember)
{
var bicycleToFind = BicycleDB.Find(IDbicycle);
// var memberToSetAsFK = MemberDB.Find(IDmember); **不需要这样做,因为你有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;组; } 

[ForeignKey(OwnerID)]
public virtual Member Owner {get;组;

其次,您不需要此注释:

  // [Index(MemberUniqueID,IsUnique = true)] ** MemberID将默认为一个身份密钥,因此它将创建唯一的索引。 
public int MemberID {get;组; }

现在您可以插入现有的所有者,如下所示:

  public void bicycle_set_FK(int IDbicycle,int IDmember)
{
var bicycleToFind = BicycleDB.Find(IDbicycle);
bicycleToFind.OwnerID = IDmember; //不要担心nav类,只要设置FK
SaveChanges();
}

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

  public virtual ICollection< Member>家庭成员{get;组; 

所以要添加一个新成员:

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

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


Here's the entites and context code:

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

Now, I add a few examples of each, add them and SaveChanges();. Then I try to run this code:

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

And as a result, I get this error:

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.

The weird thing is, if I run that method simultaneously while adding the examples, the method works fine and sets the FK as expected. But if I first add the examples with the first run of the code, and I try to set FKs on the second run of the code, it throws that exception.

EDIT:

Okay, so I've done as recommended and after reading the artice you linked I have this:

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

And the method looks like this:

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

But this generates a new problem:

"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."

The values I use are 1 and 3 (bicycle_set_FK(1, 3);). Members contain 3 rows with IDs: 1, 2 and 3. So where does it find that zero, since it's not in the database nor do I enter it at any point in the code?

And one more thing: the article doesn't mention how to solve that problem in a one-to-many relationship. How do I add FK between Family and Member? Do I add some property such as public List<Member> FamilyMembersFK?

解决方案

Entity framework is re-adding your Owner(Member). There are a couple of ways around this, but since you have the FK try this:

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

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

EDIT: First, I highly recommend you follow some convention when naming your navigation classes and keys. You are calling your navigation class "MemberId" - that is very confusing. If you want the FK to be OwnerId, go with something like this:

public int? OwnerID { get; set; }

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

Second, you don't need this annotation:

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

Now you can insert an existing owner like this:

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

Regarding the one to many, you already have that configured with:

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

So to add a new member:

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

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

这篇关于实体框架代码第一个唯一索引外键抛出DbUpdate异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆