我们想使用实体框架代码优先使用一对一的可选关系。我们有两个实体。
public class PIIUser { public int Id { get; set; } public int? LoyaltyUserDetailId { get; set; } public LoyaltyUserDetail LoyaltyUserDetail { get; set; } } public class LoyaltyUserDetail { public int Id { get; set; } public double? AvailablePoints { get; set; } public int PIIUserId { get; set; } public PIIUser PIIUser { get; set; } }
PIIUser可能有一个,LoyaltyUserDetail但LoyaltyUserDetail必须有一个PIIUser。我们尝试了这些流利的方法技术。
PIIUser
LoyaltyUserDetail
modelBuilder.Entity<PIIUser>() .HasOptional(t => t.LoyaltyUserDetail) .WithOptionalPrincipal(t => t.PIIUser) .WillCascadeOnDelete(true);
这种方法没有LoyaltyUserDetailId在PIIUsers表中创建外键。
LoyaltyUserDetailId
PIIUsers
之后,我们尝试了以下代码。
modelBuilder.Entity<LoyaltyUserDetail>() .HasRequired(t => t.PIIUser) .WithRequiredDependent(t => t.LoyaltyUserDetail);
但是这次,EF没有在这两个表中创建任何外键。
您对此问题有任何想法吗?我们如何使用实体框架流利的API创建一对一的可选关系?
EF Code First支持1:1和1:0..1建立关系。后者是您要寻找的内容(“一对零或一对”)。
1:1
1:0..1
是说你在流畅的尝试 需要在两端 在一种情况下和 可选的两端 中的其他。
您需要的是一端是 可选的 ,而另一端是 必需 的。
这是《编程EF代码第一书》中的示例
modelBuilder.Entity<PersonPhoto>() .HasRequired(p => p.PhotoOf) .WithOptional(p => p.Photo);
该PersonPhoto实体呼叫导航属性PhotoOf,它指向一个Person类型。该Person类型有一个叫做导航属性Photo指向PersonPhoto型。
PersonPhoto
PhotoOf
Person
Photo
在两个相关的类中,使用每种类型的 主键 ,而不是 外键 。即,您将不会使用LoyaltyUserDetailId或PIIUserId属性。而是,关系取决于Id两种类型的字段。
PIIUserId
Id
如果您使用上述流利的API,则无需将其指定LoyaltyUser.Id为外键,EF会予以解决。
LoyaltyUser.Id
因此,无需您的代码来测试自己(我讨厌从头开始)……我会将其翻译为您的代码,如下所示:
public class PIIUser { public int Id { get; set; } public LoyaltyUserDetail LoyaltyUserDetail { get; set; } } public class LoyaltyUserDetail { public int Id { get; set; } public double? AvailablePoints { get; set; } public PIIUser PIIUser { get; set; } } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<LoyaltyUserDetail>() .HasRequired(lu => lu.PIIUser ) .WithOptional(pi => pi.LoyaltyUserDetail ); }
这就是说LoyaltyUserDetails PIIUser属性是 必需的, 而PIIUser的LoyaltyUserDetail属性是可选的。
您可以从另一端开始:
modelBuilder.Entity<PIIUser>() .HasOptional(pi => pi.LoyaltyUserDetail) .WithRequired(lu => lu.PIIUser);
现在说PIIUser的LoyaltyUserDetail属性是可选的,而LoyaltyUser的PIIUser属性是必需的。
您始终必须使用模式HAS / WITH。
HTH和FWIW,一对一(或一对零/一)关系是最容易在代码中配置的关系之一,因此您并不孤单!:)