29

有关一些背景信息,请参阅以下帖子:

实体框架一对零或一对无导航属性的关系

我一直认为这ForeignKey是用来显示类中的哪个属性包含确定导航属性的 ForeignKey,例如

public class MemberDataSet
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int? DeferredDataId { get; set; }
    [ForeignKey("DeferredDataId")]
    public virtual DeferredData DeferredData { get; set; }
}

但是,我在链接的帖子中发现这是不对的,因为 DeferredData 的主键被称为 Id 我实际上需要:

public class MemberDataSet
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int? DeferredDataId { get; set; }
    [ForeignKey("Id")]
    public virtual DeferredData DeferredData { get; set; }
}

ieForeignKey用于指向其他类。

然后我开始更改其他一些参考:

public class MemberDataSet
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int? DeferredDataId { get; set; }
    [ForeignKey("Id")]
    public virtual DeferredData DeferredData { get; set; }

    public int? SignedOffById { get; set; }
    [ForeignKey("UserId")]
    public virtual UserProfile SignedOffBy { get; set; }
}

然而,这失败了。原来在这一点上ForeignKey需要指向MemberDataSet课堂上的 Id。

public class MemberDataSet
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int? DeferredDataId { get; set; }
    [ForeignKey("Id")]
    public virtual DeferredData DeferredData { get; set; }

    public int? SignedOffById { get; set; }
    [ForeignKey("SignedOffById")]
    public virtual UserProfile SignedOffBy { get; set; }
}

我认为这是因为第二个关系是一对多,而第一个是一对零或一,并且实际上关系的主要目的是不同的,但我希望对此/对好文章的引用有所澄清,所以我可以了解正在发生的事情以及 ForeignKey 正在做什么。

在上面的示例中,我也在寻找清楚的说明如何public int? DeferredDataId { get; set; }适合方程,因为它没有明确链接到DeferredData. 我很高兴这将按照惯例匹配,但我将如何明确告诉它,例如,如果它有不同的名称?我在这篇文章中看到的所有例子都是关于使用ForeignKey属性的,但这并不是所有情况下的答案!

非常感谢所有帮助-希望了解问题而不是解决特定问题,因为我的模型中有很多参考资料,因此需要确定每种方法应采取的方法。

谢谢。

编辑

添加了其他类来帮助:

public class DeferredData
{

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    //other properties
}

public class UserProfile
{

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }

    //other properties
}
4

3 回答 3

31

1..0 关系的必需侧MemberDataSet不应该有 FK 到DeferredData. 相反,DeferredData的 PK 也应该是一个 FK 到MemberDataSet(称为共享主键)

public class MemberDataSet
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public virtual DeferredData DeferredData { get; set; }
}

public class DeferredData
{
    // DeferredData.Id is both the PK and a FK to MemberDataSet
    [Key]
    [DatabaseGenerated( DatabaseGeneratedOption.None )]
    [ForeignKey( "MemberDataSet" )]
    public int Id { get; set; }

    [Required]
    public virtual MemberDataSet MemberDataSet { get; set; }
}

流畅的 API:

modelBuilder.Entity<MemberDataSet>()
    .HasOptional( mds => mds.DeferredData )
    .WithRequired()
    .WillCascadeOnDelete();
于 2014-02-18T14:25:10.063 回答
0

我认为你是对的(前提是我理解你的正确)。[ForeignKeyAttribute]用于对应的外键。不在链接对象的主键上。

This is my object, and the foreign key is DeferredDataId

您的对象内部既不Id是外键(它是主键),也不是ID链接对象的外键(它是关系另一端的主键)

希望我理解正确:) 因为我不确定。

于 2014-02-18T14:14:39.477 回答
0

我认为您最初的想法是正确的,只有一点例外。通过将外键放在MemberDataSet你身上,你暗示你想要一个零或一对多的关系。

在您的示例中,MemberDataSet.DeferredData是可选的,并且DeferredData可以被许多MemberDataSet实例引用。

在流利的语法中,这将表示为:

modelBuilder.Entity<MemberDataSet>()
    .HasOptional(dataSet => dataSet.DeferredData)
    .WithMany()
    .HasForeignKey(deferredData => deferredData.DeferredDataId);

为了使其成为一对零或一属性,您可以在 MemberDataSet 的 DeferredDataId 列上放置一个唯一(非空)键约束。这意味着 DeferredData 实体只能由单个 MemberDataSet 实体引用。

CREATE UNIQUE INDEX unique_MemberDataSet_DeferredDataId ON MemberDataSet(DeferredDataId) WHERE DeferredDataId IS NOT NULL

注意:这种类型的筛选键仅在 SQL Server 2008 及更高版本中可用。

于 2015-06-11T01:21:39.133 回答