我应该始终使用导航属性还是使用 .Where 查询?

问题描述 投票:0回答:2

这个问题是哪种方法更好还是根本无关紧要。所以,假设我有一个类Item,就像这样

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Category> Categories { get; set; }
}

以及引用的类别

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Item> Items { get; set; }
}

问题在于,当用户单击某个类别时,该类别中的所有项目都应该以列表的形式输出,该项目的类别也应该如此。

我可以使用类似的东西

_context.Items.Where(c => c.Category.Id == id);

并删除虚拟会员。 我之所以问这个问题以及为什么我“想要”删除该成员是因为当我使用 WebApi 获取客户端的 Items 表的 Json 数据时,它会输出如下所示的内容:

{
    "Id": 1,
    "Name": "String",
    "Category": [
        {
        "Id": 1,
        "Name": "CName",
        "Items": []
        }, 
        {
        "Id": 1,
        "Name": "CName",
        "Items": []
        }
    ]
}

因此,类别模型具有导航属性的唯一问题是,当我请求项目列表时,它还会向我发送“Items”:[]。 它并没有影响我或任何东西,所以我想知道我是否应该使用导航方法或 .Where 方法。或者也许我应该考虑其他方法?

c# entity-framework database-design
2个回答
4
投票

始终使用导航属性。 EF 将能够生成比您高效得多的查询(至少可能如此)。它也更容易阅读。

就是这么说的。 不要使用 EF 对象作为数据契约。在“最好”的情况下,通过序列化器运行一个将执行上面的操作,而在常见情况下会导致循环引用异常。 您的合同应单独定义,这样就不存在循环引用。使用

Select

将集合从数据库类型转换为 API 类型。

    


0
投票

在您的情况下,根据您的示例,正确的方法是在

ItemCategory

Item
之间创建一个连接表
Category
这样,您就可以更轻松地从任一大小进行查询。
你的结构将是这样的:

public class Item { public int Id { get; set; } public string Name { get; set; } public virtual ICollection<ItemCategory> Categories { get; set; } } public class Category { public int Id { get; set; } public string Name { get; set; } public virtual ICollection<Item> Items { get; set; } } public class ItemCategory { public int CategoryId { get; set; } public int ItemId { get; set; } public virtual Item Item { get; set; } public virtual Category Category { get; set; } }

这样您就可以从类别和项目的角度进行搜索:

首先,按类别查找商品:

context.ItemCategories.Where(p=>p.CategoryId == id).ToList()

其次,找到该项目所属的类别列表:

context.ItemCategories.Where(p=>p.ItemId== id).ToList()

当然您可以选择不通过

ItemCategory

查询。在这种情况下,你会做类似

context.Item.Where(p=>p.Id == id).Include(p=>p.Categories.Category).FirstOrDefault()
的事情。
同样可以从 

Category

完成,如

context.Category.Where(p=>p.Id == id).Include(p=>p.Items.Item).FirstOrDefault()

那么,导航属性总是必要的吗?

嗯,并非总是如此。仅当您从同一模型查询该属性时,才可以在模型中包含导航属性。

从上面的示例中,我们创建一个场景,您的应用程序不需要按项目查询类别。也就是说,您将始终按类别获取项目,而无需获取项目的类别。那么您就不需要

public Category Category {get; set;}

中的

ItemCategory
。因为你永远不会使用该属性。这同样适用于
public virtual ICollection<ItemCategory> Categories { get; set; }
模型中的
Item
因此,根据经验,只有在您要使用导航时才正确包含它。 EF 将始终创建虚拟属性来应对这种情况。最后,您将得到更简洁的代码,并且没有您永远不会使用的不必要的属性。所有这一切始终取决于您的数据的查询方式。因此,请正确规划您的数据流。

© www.soinside.com 2019 - 2024. All rights reserved.