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

发布于 2024-11-02 09:50:33 字数 786 浏览 0 评论 0原文

我得出的结论是,我应该在我的代码优先设计中定义独立关联和外键关联。例如:

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. 如果这是我第一次为这本书定义作者,我会在上面的行中得到一个空异常吗? (当我给书的作者分配一些值时,EF 会自动初始化它吗?)我应该在定义中初始化它吗:

代码:

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

I have come to a conclusion that I should define both Independent Association and Foreign Key Association in My Code-First design. e.g:

public class Book
{
  public int ID {get; set;}
  public int AuthorID {get; set;}
  [ForeignKey("AuthorID")]
  public Author Author {get; set;} 
}  
  1. With the above definition, do I have to update AuthorID when I want to change the book's author, Or just using the below line is enough?
    myBook.Author = author;

  2. Am I going to get a null exception on the above line if that is the first time I'm defining an author for the book? (Does EF initialize book's author automatically when I assign some value to it?) Should I initialize it in the definition:

The code:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

把人绕傻吧 2024-11-09 09:50:33

首先,您不能同时使用独立和外国键关联 - 您使用第一个或第二个。区别在于是否使用 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();

First of all you can't use both independent and foreign key association - you use either first or second. The difference is if you use FK property or not. If you use foreign key association you should use foreign key to build a relation. That is the reason why FK association was introduced in EFv4.

Edit:

Simple example why you should use FK instead of navigation property when using custom POCOs (common in EFv4.1) and FK relations:

This works without any problem:

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

This throws exception:

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

This again works without any problem:

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();
蓬勃野心 2024-11-09 09:50:33

下面的示例也存在同样的问题:

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   [email protected] 10 <br>
b   [email protected] 15 <br>
c   [email protected] 12 <br>
d   [email protected] 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; }

The example below has the same issue:

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

If I bind a property of a Control to the Player1Name property I get a NullPointerException. In the database I can see the table and it seems to have the correct key values.

Name    EMail   Ranking <br>
a   [email protected] 10 <br>
b   [email protected] 15 <br>
c   [email protected] 12 <br>
d   [email protected] 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

To fix the problem just replace:

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

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

by

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

[ForeignKey("FrkPlayer2")]
public virtual PingPongPlayer Player2 { get; set; }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文