C# 动态Lambda选择索引
我需要一些关于我正在编写的LINQ扩展的帮助。我正在尝试创建一个扩展,该扩展计算IQueryable中给定Id的行索引,但该类型可以是任何表。我想我已经完成了大部分工作,但我似乎无法完成。我在线路上收到以下错误消息C# 动态Lambda选择索引,c#,linq,reflection,lambda,expression-trees,C#,Linq,Reflection,Lambda,Expression Trees,我需要一些关于我正在编写的LINQ扩展的帮助。我正在尝试创建一个扩展,该扩展计算IQueryable中给定Id的行索引,但该类型可以是任何表。我想我已经完成了大部分工作,但我似乎无法完成。我在线路上收到以下错误消息 Select(lambda) 方法的类型参数 'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, 无法从用法推断System.Func“”。 尝试指定类型参数 明确地c:\users\shaw
Select(lambda)
方法的类型参数
'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable,
无法从用法推断System.Func“”。
尝试指定类型参数
明确地c:\users\shawn\u 000\documents\visual studio
2013\projects\dexconstruktaweb\dexconstruktaweb\generalhelper.cs 157 17 dexconstruktaweb
更新
我做了一些进一步的挖掘,发现一些LINQ语句不适用于LINQ to实体,这就是我所使用的:
特别是“大多数投影和过滤方法的重载在LINQ to实体中都受支持,但接受位置参数的除外。”
为了解决这个问题,我使用了一个对AsEnumerable()的调用,将其转换为一个通用的可枚举项,然后调用Select和SingleOrDefault,如上所述。但是,我发现调用AsEnumerable和ToList创建的SQL没有区别,因此我决定只调用:
.ToList().FindIndex(e => e.Id == id)
直接在IQueryable上,无需创建扩展,因为它是一段足够小的代码
谢谢你的帮助。如果有人仍然认为这是一个更好的方法,请让我知道
干杯
更新2
作为一个学习练习,我接受了Servy的建议和这个答案,并得出以下结论:
public static int GetRowIndex<T>(this IQueryable<T> query, Expression<Func<T, int>> property, int id)
{
var lambda = Expression.Lambda<Predicate<T>>(
Expression.Equal(property.Body, Expression.Constant(id)), property.Parameters);
return query.ToList().FindIndex(lambda.Compile());
}
其中查询的类型为IQueryable
虽然这没有什么意义,但它只是一个真正有用的学习练习
谢谢。您的lambda始终返回
GetRowCountClass
并接受T
,因此您可以使用表达式的通用版本。lambda
方法:
var lambda = Expression.Lambda<Func<T, GetRowCountClass>>(member, parameter);
var item = query.Select(lambda);
return item.SingleOrDefault(x => x.Id == id).Index;
var lambda=Expression.lambda(成员、参数);
var item=query.Select(lambda);
返回item.SingleOrDefault(x=>x.Id==Id).Index;
为什么不接受谓词作为参数?如果您接受一个表达式
,它不仅使该方法的实现变得非常简单,而且使所有内容都是静态类型的;你不必担心在没有Id
属性的东西上调用它,或者你可以使用它来查找一个基于它的Id以外的东西的项目的索引。@Servy这听起来比我目前所做的更好。您介意在回答中充实一下吗?如果您添加.ToList
或.AsEnumerable
,那么来自该查询的所有数据都将加载到服务器端,您的FindIndex将处理加载的数据。它不会被翻译成中文SQL@SergeyLitvinov对。但是我不知道有什么方法可以在不返回所有数据的情况下获取项目的索引,同时仍然使用LINQ对实体进行访问。感谢您的回复。不幸的是,这不起作用。在使用LINQ to实体时,我需要在选择之前包含.AsEnumerable()。但是,这会导致错误“System.Collections.Generic.IEnumerable”不包含“Select”的定义以及“System.Linq.Queryable.Select(System.Linq.IQueryable,System.Linq.Expressions.Expression)”的最佳扩展方法重载具有一些无效参数–仅为澄清,如果我没有包含一个numerable,那么在执行时会出现以下错误。SingleOrDefault:LINQ to Entities无法识别方法'System.LINQ.IQueryable1[Entities.GeneralHelpers.LinqExtensions+GetRowCountClass]选择[Book,GetRowCountClass](System.LINQ.IQueryable
1[Entities.BLL.Models.Book],System.Linq.Expressions.Expression1[System.Func
3[Entities.BLL.Models.Book,System.Int32,Entities.GeneralHelpers.LinqExtensions+GetRowCountClass]])方法,此方法无法转换为存储表达式。
public static int GetRowIndex<T>(this IQueryable<T> query, Expression<Func<T, int>> property, int id)
{
var lambda = Expression.Lambda<Predicate<T>>(
Expression.Equal(property.Body, Expression.Constant(id)), property.Parameters);
return query.ToList().FindIndex(lambda.Compile());
}
var result2 = query.GetRowIndex(x => x.Id, id);
var lambda = Expression.Lambda<Func<T, GetRowCountClass>>(member, parameter);
var item = query.Select(lambda);
return item.SingleOrDefault(x => x.Id == id).Index;