Updating Foreign key associations in Entity Framework 4.1 Code-First

只愿长相守 提交于 2019-12-01 08:49:34
Ladislav Mrnka

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

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

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; }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!