更新实体框架4.1代码优先中的外键关联

时间:2011-04-19 12:59:50

标签: c# .net entity-framework-4.1 foreign-key-relationship

我得出结论,我应该在我的Code-First设计中定义独立协会和外键协会。例如:

public class Book
{
  public int ID {get; set;}
  public int AuthorID {get; set;}
  [ForeignKey("AuthorID")]
  public Author Author {get; set;} 
}  
  1. 根据上面的定义,当我想要更改图书的作者时,是否必须更新AuthorID,或者仅使用以下行就足够了?
    myBook.Author =作者;

  2. 如果这是我第一次为这本书定义作者,我会在上面的行中得到一个null异常吗? (当我为其分配一些值时,EF会自动初始化图书的作者吗?)我应该在定义中对其进行初始化:

  3. 代码:

    public class Book
    {
      public int ID {get; set;}
      public int AuthorID {get; set;}
    
      private Author m_Author;
      [ForeignKey("AuthorID")]
      public Author Author {get
      {
        get
        {
          if (m_Author == null)
            m_Author = new Author();
          return m_Author;
        }
        set
        {
          this.m_Author = value;
        }
      } 
    }
    

2 个答案:

答案 0 :(得分:4)

首先,您不能同时使用independent and foreign key association - 您可以使用第一个或第二个。区别在于您是否使用FK属性。如果使用外键关联,则应使用外键来建立关系。这就是为什么在EFv4中引入FK关联的原因。

编辑:

使用自定义POCO(EFv4.1中常见)和FK关系时,为什么要使用FK而不是导航属性的简单示例:

这没有任何问题:

var child = new ChildEntity() {Id = 1};
child.ParentEntityId = 1;  // Assigning FK
context.Childs.Attach(child);
context.Entry(child).State = EntityState.Modified;
context.SaveChanges();

抛出异常:

var parent = new ParentEntity() { Id = 1 };
context.Parents.Attach(parent);
var child = new ChildEntity() {Id = 1};
child.Parent = parent;  // <-- Assigning only navigation property
// Next line will cause InvalidOperationException:
// A referential integrity constraint violation occurred: 
// The property values that define the referential constraints 
// are not consistent between principal and dependent objects in 
// the relationship.
context.Childs.Attach(child);
context.Entry(child).State = EntityState.Modified;
context.SaveChanges();

这也没有任何问题:

var parent = new ParentEntity() { Id = 1 };
context.Parents.Attach(parent);
var child = new ChildEntity() {Id = 1};
child.Parent = parent;
child.ParentEntityId = 1; // <-- AGAIN assigning FK
context.Childs.Attach(child);
context.Entry(child).State = EntityState.Modified;
context.SaveChanges();

答案 1 :(得分:2)

以下示例具有相同的问题:

public class PingPongPlayer
{
    [Key]
    public string Name { get; set; }
    public string EMail { get; set; }
    public int Ranking { get; set; }
}

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

    public string FrkPlayer1 { get; set; }
    public string FrkPlayer2 { get; set; }

    [ForeignKey("FrkPlayer1")]
    public PingPongPlayer Player1 { get; set; }

    [ForeignKey("FrkPlayer2")]
    public PingPongPlayer Player2 { get; set; }

    public DateTime MatchDate { get; set; }

    public bool AlreadyPlayed { get; set; }

    public string Player1Name
    {
        get { return Player1.Name; }
    }

    public string Player2Name
    {
        get { return Player2.Name; }
    }
}

如果我将Control的属性绑定到Player1Name属性,我会得到NullPointerException。在数据库中,我可以看到表,它似乎有正确的键值。

Name    EMail   Ranking <br>
a   a@q.com 10 <br>
b   b@q.com 15 <br>
c   c@q.com 12 <br>
d   d@q.com 20 <br>

Id  FrkPlayer1  FrkPlayer2  MatchDate   AlreadyPlayed
1   a           b           2011-04-21 00:00:00.000 0
2   a           c           2011-04-21 00:00:00.000 0
3   b           c           2011-04-21 00:00:00.000 0
4   a           d           2011-04-21 00:00:00.000 0
5   a           c           2011-04-21 00:00:00.000 0
6   d           c           2011-04-21 00:00:00.000 0

要解决问题,请更换:

[ForeignKey("FrkPlayer1")]
public PingPongPlayer Player1 { get; set; }

[ForeignKey("FrkPlayer2")]
public PingPongPlayer Player2 { get; set; }

通过

[ForeignKey("FrkPlayer1")]
public virtual PingPongPlayer Player1 { get; set; }

[ForeignKey("FrkPlayer2")]
public virtual PingPongPlayer Player2 { get; set; }
相关问题