在传递给Where子句的方法中使用时填充导航属性

时间:2019-03-07 12:13:43

标签: c# asp.net-core entity-framework-core asp.net-core-webapi

我有一个端点,该端点应列出按搜索词过滤的所有候选资格,因此我要做的是创建一个接受候选资格实体和searchTerm作为参数的方法。然后,我将该方法传递给Where子句,但问题是我得到了NullReferenceException,因为导航属性为null。如果我将语句放在Where子句而不是方法中,则它不是throw Exception。问题是如何解决此问题,但我想保留外部方法,因为会有更多逻辑,但是我需要访问所有navigation properties,即应填充它们。

if (!string.IsNullOrEmpty(searchTerm))
{
    query = query.Where(c => FilterBySearchTerm(c, searchTerm));
}

var result = await query.Select(c => new CandidaturesResponseModel()
{
    Id = c.Id,
    Name = c.PrimaryMember.FullName, // that's filled
}).ToListAsync();

private bool FilterBySearchTerm(Candidature c, string searchTerm)
{
    return c.PrimaryMember.FirstName.Contains(searchTerm); // here is the exception because PrimaryMember navigation property is null. So I want this to be filled.
}

2 个答案:

答案 0 :(得分:1)

只需使用Include方法添加PrimaryMember

  query = query.Include(x=> x.PrimaryMember).Where(c => FilterBySearchTerm(c, searchTerm));

答案 1 :(得分:1)

问题是您正在使用FilterBySearchTerm方法来实现查询。 EF无法将随机方法转换为SQL,因此它必须继续运行查询,获取结果,然后再应用Where。 EF过去实际上会抛出异常,但是EF Core会静默处理此异常。

无论如何,运行查询后,就完成了。您的过滤是在内存中进行的,此时,没有Include,您的相关实体就无法使用。总之,您需要就地构建过滤器(而不是使用单独的方法),以便EF能够将其转换为SQL。

另一种可能会更好地为您服务的方法是将可查询项传递给您的FilterBySearchTerm方法。例如,不要这样做:

query = query.Where(c => FilterBySearchTerm(c, searchTerm));

query = FilterBySearchTerm(query, searchTerm);

然后,在FilterBySearchTerm内,您可以将Where子句直接应用于传入的查询。这样一来,您可以构建EF可以理解的实际查询,同时还可以封装逻辑。