首页 > 解决方案 > EF6:如何创建一个谓词来检查属性是否包含在对象列表的属性中

问题描述

我有以下情况:我有一个必须调用的函数:

class WorkobjectRepository...
public async Task<IList<WorkobjectView>> FindAllMatchingAsync(Expression<Func<WorkobjectView, bool>> whereExpression)
{
    return await this.WorkobjectContext.WorkobjectViews.AsNoTracking().Where(whereExpression).ToListAsync();
}

WorkobjectView除了其他属性之外,该类还具有以下两个属性:

1. StatusDetailedDisplayName
2. AssignedSubteamId

现在我想要所有WorkobjectViews whereStatusDetailedDisplayName == StatusDetailedDisplay.activeOpenAssignedSubteamId包含在具有属性的对象UserAccountSubteam列表UserAccountSubteamId

以下代码对我来说成功:

// List<UserAccountSubteam> caredTeams, which is given
String[] teams = new string[caredTeams.Count];
for (int i = 0; i < caredTeams.Count; i++)
{
    teams[i] = caredTeams[i].Id;
}
return await this.WorkobjectRepository.FindAllMatchingAsync(w => w.StatusDetailedDisplayName == StatusDetailedDisplay.activeOpen && teams.Contains(w.AssignedSubteamId));

现在,我想使用LINQ或使用集合函数来优化代码。
选项 1:第一个是使用LINQandExists方法:

var results =  await this.WorkobjectRepository.FindAllMatchingAsync(w => w.StatusDetailedDisplayName == StatusDetailedDisplay.activeOpen && caredTeams.Exists(team => team.Id == w.AssignedSubteamId));

但这失败了,我收到以下错误消息:

LINQ to Entities does not recognize the method 'Boolean Exists(System.Predicate`1[Backend.DomainLayer.UserAccountSubteam])' method, and this method cannot be translated into a store expression.

选项2:然后,我尝试使用Any

var results =  await this.WorkobjectRepository.FindAllMatchingAsync(w => w.StatusDetailedDisplayName == StatusDetailedDisplay.activeOpen && caredTeams.Any(team => team.Id == w.AssignedSubteamId));

这也失败了:

Unable to create a constant value of type 'Backend.DomainLayer.UserAccountSubteam'. Only primitive types or enumeration types are supported in this context.

选项 3:最后但并非最不重要的是,我尝试了以下方法,但也失败了:

var results =  await this.WorkobjectRepository.FindAllMatchingAsync(w => w.StatusDetailedDisplayName == StatusDetailedDisplay.activeOpen && caredTeams.Select(c => c.Id).Contains(w.AssignedSubteamId));

错误信息:

Unable to create a constant value of type 'Backend.DomainLayer.UserAccountSubteam'. Only primitive types or enumeration types are supported in this context.

实现这一目标的正确方法是什么?请注意,我无法更改基本功能FindAllMatchingAsync

标签: c#linqentity-framework-6

解决方案


第一个选项Contains是正确的方法,但可以简化。

var teams = caredTeams.Select(t => t.Id);

return await this.WorkobjectRepository
   .FindAllMatchingAsync(w => w.StatusDetailedDisplayName == StatusDetailedDisplay.activeOpen 
      && teams.Contains(w.AssignedSubteamId));

推荐阅读