EF Core 3.0 可为空的导航属性

V0l*_*dek 5 c# entity-framework-core .net-core c#-8.0 entity-framework-core-3.0

所以 EF Core 预览版 7 发布了,我决定将它与 C# 8 预览版和 .NET Core 3.0 预览版 7 一起使用。假设我有一个表示多对多关系的类:

public class A 
{
    public int Id { get; set; }
    public ICollection<Relation> Relations { get; set; }
}

public class B
{
    public int Id { get; set; }
    public ICollection<Relation> Relations { get; set; }
}

public class Relation
{
    public A A { get; set; }
    public B B { get; set; }

    public int AId { get; set; }
    public int BId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我会将它们映射为:

modelBuilder.Entity<A>(entity => entity.HasKey(e => e.Id));

modelBuilder.Entity<B>(entity => entity.HasKey(e => e.Id));

modelBuilder.Entity<Relation>(entity =>
{
    entity.HasKey(e => new { e.AId, e.BId });

    entity.HasOne(e => e.A).WithMany(a => a.Relations).HasForeignKey(e => e.AId);

    entity.HasOne(e => e.B).WithMany(b => b.Relations).HasForeignKey(e => e.BId);
});
Run Code Online (Sandbox Code Playgroud)

现在,因为我可能不想包含一个或两个关系的类,A并且B可以为空。因此,它们应该可以为空。

var relation = Set<Relations>().Include(r => r.A).First(); // relation.A is not null, but relation.B is null.
Run Code Online (Sandbox Code Playgroud)

所以我将类重写为:

public class Relation
{
    public A? A { get; set; }
    public B? B { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

但是现在模型构建不起作用,因为这些行:

entity.HasOne(e => e.A).WithMany(a => a.Relations).HasForeignKey(e => e.AId);

entity.HasOne(e => e.B).WithMany(b => b.Relations).HasForeignKey(e => e.BId);
Run Code Online (Sandbox Code Playgroud)

提高CS8602 - Dereference of a possibly null referencea.RelationsNADb.Relations的访问,这是我设置被视为错误的解决方案范围的,因为它似乎是一个明智的事情。

请注意,从另一侧构建模型,因此HasManyA和 上进行配置B,将提高CS8603 - Possible null reference return.

我能够通过去默默地解决这个问题,#pragma warning disable CS8602但这显然是一种解决方法。在我看来,它就像是 EF Core 中的一种气味,这种用法是正确的并且永远不会引发任何问题似乎是合理的null。但是,我无法在 EF Core 的 github 上找到这样的问题。

所以问题是,在当前的 EF Core 3.0.0 Preview 7 中,有没有一种方法可以在不发出模型构建警告的情况下拥有可为空的导航属性?如果没有,这确实是一个问题,它是否已知并且我在 EF Core 的 github 上错过了它,还是应该在那里提出它?

小智 -1

我没有使用过 .NET Core 3.0 预览版 7,但这就是它在 .net Core 2.2 上的工作方式,据我所知,这方面没有任何变化。导航属性加载默认设置为显式加载,因此如果不使用.Include()属性 A 和 B 将为 null。您不必将它们设置为可为空。AId并且BId将被加载,通过使用.Include(r => r.A)属性 A 将被加载,但 B 将为空。

我无法发表评论,所以我将此作为答案发布。