Linq 从一个列表中获取对象,其中其他整数列表包含在第一个列表中
Posted
技术标签:
【中文标题】Linq 从一个列表中获取对象,其中其他整数列表包含在第一个列表中【英文标题】:Linq get object from one list where other list of integers are contained in the first list 【发布时间】:2020-10-04 10:53:03 【问题描述】:我有以下类结构:
public class Party
public int Id get;set;
public List<int> PartyAgents get;set;
还有一个 PartyAgents 的整数列表 => public List<int> PartyAgentIds get;set;
我如何获得所有 Party 包含列表中的派对代理的各方
我试过了:
var domainParties = (from party in _context.Party //.Include("Address")
where party.PartyAgents.Any(agent =>
PartyAgentIds.Contains(agent))
select party).ToList();
但这是抛出错误
无法翻译查询。要么重写表单中的查询 可以翻译,或通过以下方式显式切换到客户评估 插入对 AsEnumerable()、AsAsyncEnumerable() 的调用, ToList() 或 ToListAsync()。
【问题讨论】:
尝试将_context.Party
更改为_context.Party.ToList()
。
你确定你的数据库结构看起来像那样...我的“猜测”它是 PartyAgents 是子表的集合导航属性,这使得问题完全不同,解决方案又不同了
【参考方案1】:
Take #1 - 使用简短的 sn-p 代码快速尝试执行此操作;有一个合理的机会使用 EF,因为只有 _context.Party.Where(p => p.PartyAgents.Contains(i) 需要翻译成 SQL,但这意味着运行多个查询:(
List<Party> domainParties = new List<Party>();
List<int> partyAgentIds = new List<int> 1, 3, 5, 7, 9 ;
partyAgentIds.ForEach(
(i) => domainParties.AddRange (
_context.Party.Where(p => p.PartyAgents.Contains(i)
&& !domainParties.Contains(p)
)
)
);
采取 #2 - 动态表达式应该更有效,因为它对数据库进行一次查询。已经测试了这个特定的代码,它适用于 Party 类的 IQueryable 集合,我之前也在 EF Core 中使用过这种类型的代码。
if (partyAgentIds.Count() > 0)
ParameterExpression typeParam = Expression.Parameter(typeof(Party));
Expression propertyValue = Expression.Property(typeParam, typeof(Party).GetProperty("PartyAgents"));
MethodInfo containsMethod = typeof(List<int>).GetMethod("Contains", new Type[] typeof(int) );
List<Expression> expressions = new List<Expression>();
foreach(int i in partyAgentIds)
Expression containsValue = Expression.Constant(i, typeof(int));
Expression expression = Expression.Call(propertyValue, containsMethod, containsValue);
expressions.Add(expression);
Expression body = expressions.First();
if (expressions.Count() > 1)
for (int i = 1; i < expressions.Count; i++)
Expression right = expressions.ElementAt(i);
body = Expression.Or(body, right);
// Create the final criteria
Expression<Func<Party, bool>> criteria = Expression.Lambda<Func<Party, bool>>(
body,
new ParameterExpression[] typeParam );
// Now run the query with the criteria
List<Party> results = _context.Party.Where(criteria).ToList();
注意 - 作为示例提供的基本代码,为了更好地实现,将其分解为几个通用类,以便您可以使用类型 T 以及不同的运算符和属性类型等构建适当的动态表达式。希望它有用:)
【讨论】:
如果你想投反对票,请说明你会如何做得更好;) OP 的查询更加简洁易懂。 OP 遇到问题,因为 EF 没有将查询转换为 SQL。您的代码没有希望作为 SQL 执行。 不同意你的第一点,第二点,也许——我没有用 EF 测试过,因为我没有类似的测试项目。该代码显示了一种不同的方法,如果 OP 将其分解为单独的查询,他可能会获得一些成果。 看看你以前的答案,看起来你知道你的东西,所以我不会过多地谈论这个。我只是不觉得这是你最好的之一。以上是关于Linq 从一个列表中获取对象,其中其他整数列表包含在第一个列表中的主要内容,如果未能解决你的问题,请参考以下文章