【问题标题】:EF6: How create a predicate which checks if a property is contained in the property of a list of objectsEF6:如何创建一个谓词来检查属性是否包含在对象列表的属性中
【发布时间】:2021-06-21 12:21:00
【问题描述】:

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

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,其中StatusDetailedDisplayName == StatusDetailedDisplay.activeOpenAssignedSubteamId 包含在对象列表UserAccountSubteam 中,其中UserAccountSubteam 具有属性Id

以下代码对我来说成功:

// 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: 第一个是使用 LINQExists 方法:

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# linq entity-framework-6


    【解决方案1】:

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

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

    【讨论】:

    • 为什么我提到的选项都不起作用,即Exists, Any...?在这种情况下有没有办法使用ExistsAny
    • 简单回答:因为 LINQ 翻译器不支持客户端集合的其他翻译。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-09
    • 2017-08-21
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 2012-02-02
    相关资源
    最近更新 更多