【问题标题】:Entity framework Navigation Properties实体框架导航属性
【发布时间】:2014-12-12 07:29:36
【问题描述】:

我目前正在尝试开发我的第一个 .NET MVC 应用程序并学习主要概念。

在我的应用程序中,我有一个表格,显示动物表格中的动物列表。在表中,我也试图显示动物品种,但我正在从动物表中存储的外键的品种表中提取品种

我目前正在尝试使用导航属性来显示品种文本而不是 ID,所以我 将我的 Animal 模型更改为如下所示

public partial class Animal
{
    public int AnimalId { get; set; }
    public Nullable<int> UserId { get; set; }
    public string TagNo { get; set; }
    public Nullable<int> Species { get; set; }
    public Nullable<bool> Sex { get; set; }
    public Nullable<int> AnimalBreed { get; set; }
    public Nullable<System.DateTime> DOB { get; set; }
    public Nullable<int> OwnershipStatus { get; set; }
    public Nullable<System.DateTime> DateAdded { get; set; }
    public Nullable<bool> BornOnFarm { get; set; }

    public virtual Breed Breed { get; set; }
}

我的品种模型看起来像

public partial class Breed
{
    public int id { get; set; }
    public Nullable<int> SpeciesID { get; set; }
    public string Breed1 { get; set; }
}

在我看来,我正试图从我的动物模型中显示 Breeds 字段,如下所示,但品种列只是空的

<td>
  @Html.DisplayFor(modelItem => item.Breed.Breed1)
</td>

最后,这是我用来将模型发送到视图的代码

List<Animal> Animal1 = (from animals in db.Animals
    where animals.Species == 2 && animals.OwnershipStatus == 1
    && animals.UserId == WebSecurity.CurrentUserId
    select animals).ToList();

return View(Animal1);

【问题讨论】:

    标签: asp.net-mvc entity-framework navigation-properties


    【解决方案1】:

    首先,不要将单个项目复数。它会在您的代码中造成混乱:

    public virtual Breed Breed { get; set; }
    

    -或-

    public virtual ICollection<Breed> Breeds { get; set; }
    

    virtual 属性允许延迟加载(获取品种的查询将在您第一次尝试访问它时发出)。您几乎总是希望在属性中包含virtual,因此如果您实际上并未最终使用该属性,Entity Framework 不会不必要地发出连接。但是,在这种情况下,您,因此您需要通过在查询中包含 .Include("Breed") 来告诉 EF 急切加载它。但是,这只是为了优化;这不是你的问题。

    您的问题是 Razor 不知道如何显示 Breed。显然,它不是普通类型,因为您创建了它。所以,你真正需要的是在Breed 上显示你想要的实际属性:

    @Html.DisplayFor(m => m.Breed.Breed1)
    

    还有另一种方法,但它更复杂,并且对于这种情况可能有点过分。如果你真的想直接使用Breed,那么你需要为Breed定义一个显示模板。为此,您可以向Views\Shared 添加一个名为DisplayTemplates 的新文件夹。在该文件夹中,添加一个名为 Breed.cshtml 的视图。这里的视图名对应的是class名,而不是属性名。在该视图中,您可以执行以下操作:

    @model Namespace.To.Breed
    @Html.DisplayFor(m => m.Breed1)
    

    那么,在你看来,你可以这样做:

    @Html.DisplayFor(m => m.Breed)
    

    并且 Razor 会使用显示模板来渲染合适的东西。就像我说的,这样做有点过头了,但在更复杂的对象渲染中,它可能会派上用场。

    【讨论】:

    • 嗨,克里斯。感谢您的帮助,但我仍然没有解决问题。我已经更改了我的代码并调整了我上面的问题以反映它。听取您的建议后,我仍然遇到同样的问题。它仍然显示一个空白列。我做错什么了吗?谢谢
    • 您确定Breed1 实际上不是空白吗?您的实体没有任何要求,因此它很容易为 NULL 或空字符串。
    • 我刚刚检查了我的 Breed 表,所有行中的所有列都包含数据?
    【解决方案2】:

    如果您的DbContext 中未启用延迟加载,则您必须显式加载(或使用预先加载)导航属性。

    http://msdn.microsoft.com/en-us/data/jj574232.aspx

    你最终会得到类似的东西:

    var res = (from animals in db.Animals.Include("Breeds")
                                        where animals.Species == 2 & animals.OwnershipStatus == 1
                                        & animals.UserId == WebSecurity.CurrentUserId
                                        select animals).ToList();
    

    【讨论】:

    • 我仍然不确定如何“急切地加载”我上面的查询。我必须将“包含”合并到选择中??
    猜你喜欢
    • 1970-01-01
    • 2016-03-29
    • 2016-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多