我的理解是,在EF中使用DataAnnotation声明外键时,可以通过以下方式之一完成:
[ForeignKey("Player1Home")]
public long? HPlayer1Id { get; set; }
public virtual Player Player1Home { get; set; }
public long? HPlayer1Id { get; set; }
[ForeignKey("HPlayer1Id")]
public virtual Player Player1Home { get; set; }
[Table("Matches")]
public class Match
{
[Key]
public long Id { get; set; }
//-- Option 1 - THIS WORKS GREAT --//
public long? HPlayer1Id { get; set; }
[ForeignKey("HPlayer1Id")]
public virtual Player Player1Home { get; set; }
//-- Option 2 - THIS DOES NOT WORK, it generates an extra column in the database --//
[ForeignKey("Player1Home")]
public long? HPlayer1Id { get; set; }
public virtual Player Player1Home { get; set; }
}
[Table("Players")]
public class Player
{
[Key]
public long Id { get; set; }
[InverseProperty("Player1Home")]
public virtual ICollection<Match> MatchesAsHome1 { get; set; }
}
当然如果我将HPlayer1Id重命名为Player1HomeId,那么Option 2再次正常工作。但是,当“约定”无法自动确定匹配属性时,DataAnnotation的整个目的是允许显式命名。
删除Player类上的InverseProperty DataAnnotation似乎也解决了这个问题,但不幸的是我不能这样做,因为我的实际Match类中有四个玩家,因此我需要显式映射。
最后,我知道我可以使用选项1,但我更喜欢在Id字段上声明所有密钥(主要和外部)的一致性,而不是导航属性上的外键。从技术上讲,无论哪种方式都可行。
这只是4.3.1中的错误吗?在EF Code中首先?
或者是将ForeignKey和InverseProperty从两个不同的属性映射到不支持的常见第三个属性?
非常感谢任何信息!
[Table("Matches")]
public class Match
{
[Key]
public long Id { get; set; }
[ForeignKey("Player1Home")]
public long? HPlayer1Id { get; set; }
[InverseProperty("MatchesAsHome1")]
public virtual Player Player1Home { get; set; }
}
[Table("Players")]
public class Player
{
[Key]
public long Id { get; set; }
public virtual ICollection<Match> MatchesAsHome1 { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Match> Matches { get; set; }
public DbSet<Player> Players { get; set; }
}
用法:
try
{
MyContext mc = new MyContext();
//NullReferenceException gets thrown on the next call
mc.Matches.Add(new Match());
mc.SaveChanges();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
答案 0 :(得分:3)
这已在EF5中修复,我确认它在EF6中仍能正常运行。
您可以查看有关此问题的调查说明 - https://entityframework.codeplex.com/workitem/138。
答案 1 :(得分:2)
EF 4.1中的相同行为。
您没有提及将InverseProperty
属性移至关系另一侧的选项:
[Table("Matches")]
public class Match
{
[Key]
public long Id { get; set; }
[ForeignKey("Player1Home")]
public long? HPlayer1Id { get; set; }
[InverseProperty("MatchesAsHome1")]
public virtual Player Player1Home { get; set; }
}
[Table("Players")]
public class Player
{
[Key]
public long Id { get; set; }
public virtual ICollection<Match> MatchesAsHome1 { get; set; }
}
这对我有用,并没有创建额外的列。
您的选项2的行为看起来像是代码优先的错误。
修改强>
确认将版本从EF 4.1更改为EF 4.3.1会导致上面的模型NullReferenceException
。数据库无法创建。