使用 Select 而不是 Include 通常更有效。使用 Select 您可以选择您计划使用的属性。Include 将传输完整的项目,包括您不会使用的属性。
考虑一个具有直接一对多关系的学生的学校:每个学校有零个或多个学生,每个学生恰好就读一所学校,即外键 SchoolId 所指的学校。
假设您要查询学校 [10] 及其 2000 名学生。每个 Student of School [10] 的外键 SchoolId 的值等于 10。如果您使用 Include,您将传输此值大约 2000 次,而您已经知道该值。多么浪费处理能力。
查询数据时,始终使用 Select 并仅选择您实际计划使用的属性。仅当您计划修改包含的数据时才使用 Include。
var result = context.Vendors.Select(vendor => new
{
// Select only the Vendor properties that you intend to use:
Id = vendor.Id,
Name = vendor.Name,
...
HighRatedItems = vendor.Items.Where(item => item.Rating > 1)
.Select(item => new
{
// again: select only the properties that you plan to use
Id = item.Id,
...
// not needed, you know the value:
// VendorId = item.VendorId,
})
.ToList(),
})
.ToList();
我在这里使用自动类型。如果你真的想要供应商:
var result = context.Vendors.Select(vendor => new Vendor
{
// Select only the Vendor properties that you intend to use:
Id = vendor.Id,
Name = vendor.Name,
...
Items = vendor.Items.Where(item => item.Rating > 1)
.Select(item => new Item
{
// again only the items that you plan to use.
Id = item.Id,
...
})
.ToList(),
});
请注意,某些属性将没有正确的值。这可能会让您的方法的用户感到困惑。但话又说回来:他们知道无论如何他们都不会得到“供应商及其物品”,因为您不会退回他们所有的物品,所以他们已经不期待完整的供应商对象。
为了克服未完全填充返回对象的问题,请考虑实现存储库模式。将数据库中表的类型与实际返回的数据分开。
这将需要额外的类,这些类看起来与您的原始供应商和项目非常相似。然而,它的优势在于用户将确切地知道他们得到了什么。然而,好处是如果您决定更改数据库的布局,您的用户不必更改代码。此外,存储库隐藏了您正在使用数据库。它可以是 CSV 文件,也可以是 Json,甚至可能只是一个字典。这使得对用户进行单元测试变得更加容易。
您是否应该实施存储库取决于您的数据库将拥有多少用户、单元测试的重要性以及您期望数据库更改的频率。