在LINQ

时间:2018-07-25 11:44:22

标签: c# linq entity-framework-core

在我的Customer模型中,我已经

public virtual ICollection<AddressModel> AddressIDs { get; set; }

其中引用了AddressModel,这给了我客户与他们的地址之间的一对多关系。

我有一个使用的搜索功能

var CustomerList = _context.Customers
    .Where(ps => ps.Surname.Contains(surnameToSearchFor))

按姓氏限制返回的数据集。

我正在尝试添加在地址中搜索邮政编码的功能。通过各种链接,它可以在Visual Studio中运行,但在执行时会中断

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

如何在子表上的LINQ中添加Where子句?

修改 对于建议使用Multiple WHERE clause in Linq作为答案的人,该问题显然与单个表有关,而我明确询问了子表。

4 个答案:

答案 0 :(得分:5)

您不能在“包含”中使用where语句。您可以通过单个linq查询获得所需的内容,如下所示:

select candidateID,Salary,rank from candidateSalary where candidateID = 2

+---------------+-----------+------+
|  candidateID  | Salary    | rank |
+---------------------------+------+
|  2            | 12000     | 1    |
+---------------------------+------+

答案 1 :(得分:2)

正如已经提到的另一个答案(由Progressive提出)一样,您无法根据Include进行过滤。

(渐进式的)另一个答案可能是 为您解决,或者可能不是。它会给您邮政编码中至少有一个地址的所有客户,但随后它将加载该客户的所有地址(包括邮政编码不同的地址)。< / p>

如果您仅希望检索邮政编码的地址(我怀疑是这种情况),则会写出此答案。如果您只希望检索客户并且仅过滤其地址(而不加载地址),则另一个解决方案(通过Progressive)是解决方案。


正如我所说,您不能通过包含来做到这一点。但是,还有其他解决方案:

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

作为一般的经验法则,请始终从孩子处开始查询并包括其父母,而不是相反。在某些情况下并不重要,但是在您的特定情况下,这很重要,因为您要避免隐式加载 all 个子级。

2。明确定义结果集

换句话说,使用Select()

这可以让您更好地控制结果,以防万一您对结果确实有特定的期望,但是它比较冗长,而且(imo)不如其他解决方案好。仅在第一种解决方案不适合您时才使用它。

_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()显式加载数据。

答案 2 :(得分:1)

尝试一下:

var CustomerList = _context.Customers.Where(ps => ps.Surname.Contains("surnameToSearchFor")).Select(ps => new
{
   Surname = ps.Name,
   AddressIDs = ps.AddressIDs.Where(a => a.PostCode == postcodeToSearchFor)
 });

答案 3 :(得分:0)

我需要具有特定地址的Customer模型的姓氏和姓氏,因此根据Progressive的回答,我使用了此姓氏

var CustomerList = CustomerList.Where(ps => ps.AddressIDs
      .Any(a => a.Postcode.Contains(postcodeToSearchFor)));

这会带回邮政编码的任何部分的任何Customer,但不会带回具有空白或null邮政编码的任何人。