为什么EF代码第一次[InverseProperty]属性失败,[ForeignKey的]属性使用时

2019-09-16 08:09发布

使用:EF 4.3.1时,Visual Studio 2010,SQL CE 4.0

我的理解是,在EF DataAnnotation声明外键时,它可以做到以下任一方式:

选项1-

[ForeignKey("Player1Home")]
public long? HPlayer1Id { get; set; }

public virtual Player Player1Home { get; set; }

选项2 -

public long? HPlayer1Id { get; set; }

[ForeignKey("HPlayer1Id")]
public virtual Player Player1Home { get; set; }

问题:

当InverseProperty DataAnnotation获取与方案2中使用的额外的列被在除了HPlayer1Id 数据库 (Player1Home_Id) 生成

[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,然后选择2级的作品。 但DataAnnotation的整个目的是允许显式的命名时,“公约”不能自动确定匹配性质。

在Player类删除InverseProperty DataAnnotation也似乎解决这个问题,但不幸的是,我不能这样做,因为我的实际匹配类中有四名球员,因此我需要明确的映射。

最后,我知道我可以只使用选项1,但我更喜欢的ID字段,而不是导航属性外键声明所有我的钥匙(主键和外)的一致性。 而在技术上,无论哪种方式应该工作。

这是刚刚在4.3.1中的错误? 在EF代码第一?

或者映射一个ForeignKey,并从两个不同的属性,以一个共同的第三个属性的InverseProperty不支持?

任何信息将不胜感激!

更新:第二个错误吗?

第三个选项应该工作以及(由Slauma的建议),但导致引发我第一次尝试将实体添加到数据库中一个NullReferenceException。 该数据库从来没有最终得到创建,而方案2从上面没有这个问题。 看来这对Slauma工作的EF 4.1,但不为我用EF 4.3.1。 (我使用它与SQL CE 4.0)

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

Answer 1:

同样的行为在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版本到4.3.1 EF引起NullReferenceException与上面的模型。 该数据库还没有生成。



Answer 2:

这是固定在EF5,我已经证实,它仍然在EF6行为正确。

你可以看到在这个问题上的调查笔记- https://entityframework.codeplex.com/workitem/138 。



文章来源: Why does EF Code First [InverseProperty] attribute fail to work when used with [ForeignKey] attribute?