我得出结论,我应该在我的Code-First设计中定义独立协会和外键协会。例如:
public class Book
{
public int ID {get; set;}
public int AuthorID {get; set;}
[ForeignKey("AuthorID")]
public Author Author {get; set;}
}
根据上面的定义,当我想要更改图书的作者时,是否必须更新AuthorID,或者仅使用以下行就足够了?
myBook.Author =作者;
如果这是我第一次为这本书定义作者,我会在上面的行中得到一个null异常吗? (当我为其分配一些值时,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;
}
}
}
答案 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; }