C# 在LINQ中对子表使用WHERE子句
在我的C# 在LINQ中对子表使用WHERE子句,c#,linq,entity-framework-core,C#,Linq,Entity Framework Core,在我的客户型号中,我有 public virtual ICollection<AddressModel> AddressIDs { get; set; } 按姓氏限制返回的数据集 我正在尝试添加在地址中搜索邮政编码的功能。通过各种链接,它可以在VisualStudio中工作,但在执行时会中断 CustomerList = CustomerList .Include(ps => ps.AddressIDs .Where(a =&
客户
型号中,我有
public virtual ICollection<AddressModel> AddressIDs { get; set; }
按姓氏限制返回的数据集
我正在尝试添加在地址中搜索邮政编码的功能。通过各种链接,它可以在VisualStudio中工作,但在执行时会中断
CustomerList = CustomerList
.Include(ps => ps.AddressIDs
.Where(a => a.Postcode == postcodeToSearchFor));
带着错误
InvalidOperationException: The property expression 'ps => {from AddressModel a in ps.AddressIDs where ([a].Postcode == __p_0) select [a]}' is not valid. The expression should represent a property access: 't => t.MyProperty
如何将Where
子句添加到子表上的LINQ中
编辑
无论是谁提出的答案,这个问题显然与一个表有关,而我明确询问的是子表。您不能在Include中使用where语句。您可以通过以下单个linq查询获得所需:
var CustomerList = _context.Customers.Where(ps =>
ps.Surname.Contains(surnameToSearchFor)
&& ps.AddressIDs.Any(ad => ad.Postcode == postcodeToSearchFor ));
正如前面提到的另一个答案(渐进式),您无法在包含中进行筛选
另一个答案(渐进式)可能是你的解决方案,也可能不是。它将为您提供在邮政编码中至少有一个地址的所有客户,但随后它将加载客户的所有地址(包括不同邮政编码中的地址)
如果您只想检索邮政编码的地址,那么就写下这个答案,我怀疑就是这样。如果您只希望检索客户并仅对其地址进行筛选(但不加载地址),则另一个答案(通过渐进方式)是解决方案
正如我所说,你不能通过包含来实现。但是,还有其他解决方案:
1。查找地址并包括客户。
而不是查找客户并包括他们的地址
var addresses = _context.Addresses
.Include(a => a.Customer)
.Where(a =>
a.Postcode == postcodeToSearchFor
&&
a.Customer.Surname.Contains(surnameToSearchFor))
.ToList();
您仍然可以通过以下方式获得客户列表:
var customer = addresses.Select(a => a.Customer).Distinct();
一般的经验法则是,始终从子级开始查询,并包含其父级,而不是相反。在某些情况下,这并不重要,但在您的特定情况下,这确实很重要,因为您希望避免隐式加载所有子项
2。明确定义结果集
换句话说,使用Select()
如果您对结果有具体的期望,这将为您提供更多的控制,但它更为冗长,而且(依我看)不如其他解决方案。只有在第一个解决方案不适合您时才使用它
_context.Customers.Where(ps =>
ps.Surname.Contains(surnameToSearchFor)
&&
ps.AddressIDs.Any(ad => ad.Postcode == postcodeToSearchFor))
.Select(ps => new
{
Customer = ps,
Addresses = ps.AddressIDs.Where(ad => ad.Postcode == postcodeToSearchFor))
})
.ToList();
请注意,这里不需要Include()
Include()
配置隐式加载行为,但您的Select()
显式加载数据。尝试以下操作:
var CustomerList = _context.Customers.Where(ps => ps.Surname.Contains("surnameToSearchFor")).Select(ps => new
{
Surname = ps.Name,
AddressIDs = ps.AddressIDs.Where(a => a.PostCode == postcodeToSearchFor)
});
我需要客户
模型的名字和姓氏,他们有一个特定的地址,所以根据Progressive的回答,我使用了这个
var CustomerList = CustomerList.Where(ps => ps.AddressIDs
.Any(a => a.Postcode.Contains(postcodeToSearchFor)));
这会带回任何带有邮政编码任何部分的客户
,但不会带回任何带有空白或空
邮政编码的客户。使用内置方法无法做到这一点。看起来这是一个已知的问题,并且有一个扩展库:请注意,这不会过滤包含的列表。它将为您提供在邮政编码中至少有一个地址的所有客户,但随后它将加载该客户的所有地址,而不管他们的邮政编码是什么。@如果不包含关键字,则它不会加载所有地址。实际上,它还没有加载任何地址(假设op使用了eager加载选项)。但是你的思维方式实际上是对的。我错过了缺少的Include()
,你是对的。我有点假设OP想要加载地址。我在这个假设下写了一个答案,但如果OP不需要地址,你的答案会更好。你还将加载在postcodeToSearchFor
中没有任何地址的客户。这可以通过添加以下条件和条件来解决:ps.姓氏.Contains(“姓氏ToSearchFor”)&&ps.AddressIDs.Count>0但这完全取决于您想要什么,如果您想要拥有0个AddressIDs的客户,则需要删除第二个条件。&&ps.AddressIDs.Count>0
将过滤掉没有任何地址的客户。它不会筛选出在postcodetosearch for
中有地址但没有地址的客户。ps.lasname.Contains(“namesttosearch”)&&ps.AddressIDs.Where(a=>a.PostCode==postcodetosearch for)。计数>0:)
var CustomerList = CustomerList.Where(ps => ps.AddressIDs
.Any(a => a.Postcode.Contains(postcodeToSearchFor)));