首先了解entity framework代码中的ForeignKey属性
有关背景信息,请参阅以下post:
entity framework一到零或一个没有导航属性的关系
我一直认为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; } }
但是,我在链接的post上发现这是不对的,因为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; } }
即ForeignKey
用于指向另一个类。
然后我继续改变其他一些参考文献:
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; } }
但是,这失败了。 事实certificate, 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; }
如何清晰public int? DeferredDataId { get; set; }
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 }
1..0关系MemberDataSet
的必需端不应具有到DeferredData
的FK。 相反, 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() .HasOptional( mds => mds.DeferredData ) .WithRequired() .WillCascadeOnDelete();
我认为你最初的想法是正确的,只有一个例外。 通过将外键放在MemberDataSet
上,您暗示您想要一个零或一对多的关系。
在您的示例中, MemberDataSet.DeferredData
是可选的,并且许多MemberDataSet
实例MemberDataSet
。
在流利的语法中,这将表示为:
modelBuilder.Entity() .HasOptional(dataSet => dataSet.DeferredData) .WithMany() .HasForeignKey(deferredData => deferredData.DeferredDataId);
为了使它成为一对一或零的属性,您可以在MemberDataSet的DeferredDataId列上放置一个唯一的(where not null)键约束。 这意味着DeferredData实体只能由单个MemberDataSet实体引用。
CREATE UNIQUE INDEX unique_MemberDataSet_DeferredDataId ON MemberDataSet(DeferredDataId) WHERE DeferredDataId IS NOT NULL
注意: 此类型的筛选密钥仅在SQL Server 2008及更高版本中可用。
我认为你是对的(前提是我理解你的权利)。 [ForeignKeyAttribute]
用于相应的外键。 不在链接对象的主键上。
This is my object, and the foreign key is DeferredDataId
对象中的Id
既不是外键(它的主键),也不是链接对象的ID
是外键(它是关系另一端的主键)
希望我理解正确:)因为我不确定。