EF 包含始终为第一个导航属性生成内部联接

本文关键字:内部 属性 导航 包含始 第一个 EF | 更新日期: 2023-09-27 18:37:16

我正在使用代码优先方法,并具有以下模型:

public class Person
{
    public int ID {get; set;}
    public string Name {get; set;}
    public int CurrentStationID {get; set;}
    public virtual Station CurrentStation {get; set;}
    public int CurrentTransportationID {get; set;}
    public virtual Transportation CurrentTransporation {get; set;}
}

我的控制器中的以下代码:

Models.Person model = myDBContext.Persons
                        .Include("CurrentStation")
                        .Include("CurrentTransportation")
                        .Where(p => p.ID == 1)
                        .FirstOrDefault();

"model"将为NULL,即使数据库表"persons"中存在带有(1,"Testname",0,0)的行。

上面生成了一个带有 [...] INNER JOIN stations AS [...] LEFT JOIN transportations [...] 的 SQL 语句。对于我的所有模型,它总是为第一个导航属性执行 INNER JOIN,无论底层表/类型是什么或我以什么顺序指定它们,它始终是第一个 Include()。

我不想要一个内部连接,而是在所有这些上都有一个左连接,因为"当前站"不需要在数据库中。

EF 为什么要这样做???我不明白,但我想明白。我没有在任何属性上指定 [Required] 属性,但它的行为就像我这样做一样。

不幸的是,没有[Optional]属性,通过OnModelCreate-overover执行"HasOptional()"对我来说不是一个选择。

EF 包含始终为第一个导航属性生成内部联接

如果我

没记错的话,为了允许属性是可选的或在数据库意义上为空,您必须使该属性可为空。 因此,对于 CurrentStationId 属性,您可以尝试按如下方式声明它:

 public int? CurrentStationId {get;set;}

更新这篇文章可能对您的情况有所帮助。

首先应该让你烦恼的是数据库的设计。如果您可以CurrentStationId = 0并且同时没有Station Id = 0则意味着您的数据库不使用引用完整性。

引用完整性是使用 EF 的先决条件。如果你想在实体之间建立关系,请确保这种关系存在于数据库中,并且强制执行引用约束,否则我相信无论如何你都会遇到许多其他意想不到的行为。

如果可以在没有 Person 的情况下Station则唯一正确的方法是使CurrentStationId列和属性可为空。由于 EF 认为约束是在数据库中强制实施的(并且您无法将其关闭),因此它可以使用 INNER JOIN,并且您无法在不使 FK 可为空的情况下更改它。如果无法在数据库中更改此设置,请不要在 EF 中映射关系 - 或者最好不要使用 EF。

如果你可以控制数据库,而且如果你以这种方式设计它,你应该停止编码并回到白板来思考设计并改进它以遵循数据库设计最佳实践。它将为您节省许多将来可能遇到的问题。