一尘不染

使用Entity Framework Fluent API一对一的可选关系

c#

我们想使用实体框架代码优先使用一对一的可选关系。我们有两个实体。

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可能有一个,LoyaltyUserDetailLoyaltyUserDetail必须有一个PIIUser。我们尝试了这些流利的方法技术。

modelBuilder.Entity<PIIUser>()
            .HasOptional(t => t.LoyaltyUserDetail)
            .WithOptionalPrincipal(t => t.PIIUser)
            .WillCascadeOnDelete(true);

这种方法没有LoyaltyUserDetailIdPIIUsers表中创建外键。

之后,我们尝试了以下代码。

modelBuilder.Entity<LoyaltyUserDetail>()
            .HasRequired(t => t.PIIUser)
            .WithRequiredDependent(t => t.LoyaltyUserDetail);

但是这次,EF没有在这两个表中创建任何外键。

您对此问题有任何想法吗?我们如何使用实体框架流利的API创建一对一的可选关系?


阅读 278

收藏
2020-05-19

共1个答案

一尘不染

EF Code First支持1:11:0..1建立关系。后者是您要寻找的内容(“一对零或一对”)。

是说你在流畅的尝试 需要在两端 在一种情况下和 可选的两端 中的其他。

您需要的是一端是 可选的 ,而另一端是 必需 的。

这是《编程EF代码第一书》中的示例

modelBuilder.Entity<PersonPhoto>()
.HasRequired(p => p.PhotoOf)
.WithOptional(p => p.Photo);

PersonPhoto实体呼叫导航属性PhotoOf,它指向一个Person类型。该Person类型有一个叫做导航属性Photo指向PersonPhoto型。

在两个相关的类中,使用每种类型的 主键 ,而不是 外键
。即,您将不会使用LoyaltyUserDetailIdPIIUserId属性。而是,关系取决于Id两种类型的字段。

如果您使用上述流利的API,则无需将其指定LoyaltyUser.Id为外键,EF会予以解决。

因此,无需您的代码来测试自己(我讨厌从头开始)……我会将其翻译为您的代码,如下所示:

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,一对一(或一对零/一)关系是最容易在代码中配置的关系之一,因此您并不孤单!:)

2020-05-19