5

我正在使用 Code First 方法并具有以下模型:

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();

即使DB 表 "persons" 中存在(1, "Testname", 0, 0)的行,"model" 也会为 NULL。

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

想要一个 INNER JOIN,而是一个 LEFT JOIN,因为“CurrentStation”不需要在数据库中。

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

不幸的是,没有 [Optional]-attribute 并且通过 OnModelCreate-override 执行“HasOptional()”对我来说不是一个选项。

4

2 回答 2

7

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

 public int? CurrentStationId {get;set;}

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

于 2012-06-15T17:10:28.133 回答
2

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

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

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

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

于 2012-06-16T15:52:10.590 回答