Asp.net mvc LINQ-OrderBy的动态表达式
我有个小问题,我会详细解释的 在我的系统中,我有一个使用EF4.1的通用存储库。 一切都很好,但我有一个问题,在某些情况下,我需要在一些查询上执行动态orderBy 我通过参数接收表示类上字段的“字符串”,以执行orderBy(如“id”或“description”) 部分代码:Asp.net mvc LINQ-OrderBy的动态表达式,asp.net-mvc,linq,entity-framework,Asp.net Mvc,Linq,Entity Framework,我有个小问题,我会详细解释的 在我的系统中,我有一个使用EF4.1的通用存储库。 一切都很好,但我有一个问题,在某些情况下,我需要在一些查询上执行动态orderBy 我通过参数接收表示类上字段的“字符串”,以执行orderBy(如“id”或“description”) 部分代码: public class SomeClass { public int id { get; set; } public string de
public class SomeClass
{
public int id { get; set; }
public string description { get; set; }
}
// First we define the parameter that we are going to use
// in our OrderBy clause. This is the same as "(parameter =>"
// in the example above.
var param = Expression.Parameter(typeof(SomeClass), "parameter");
// Now we'll make our lambda function that returns the
// request.SortingName property by it's name.
var expression = Expression.Lambda<Func<SomeClass, int>>(Expression.Property(param, request.SortingName), param);
公共类SomeClass
{
公共int id{get;set;}
公共字符串说明{get;set;}
}
//首先,我们定义要使用的参数
//在我们的订货条款中。这与“(参数=>”相同
//在上面的例子中。
var param=Expression.Parameter(typeof(SomeClass),“Parameter”);
//现在我们将生成lambda函数,该函数返回
//按名称排序的request.SortingName属性。
var expression=expression.Lambda(expression.Property(param,request.SortingName),param);
如果“request.SortingName”的类型是“int”(id),那么这段代码可以工作,但是如果我想通过“string”(description)或其他类型创建orderBy,那么这段代码就不能工作
我将表达式改为使用“对象”:
var expression=expression.Lambda(expression.Property(param,request.SortingName),param);
但当我运行代码时,编译器会引发下一个异常:
“System.Int32”类型的表达式不能用于返回类型“System.Object”
如果属性为字符串类型,则异常为
“System.String”类型的表达式不能用于返回类型“System.Object”
换句话说,代码不能与“对象”类型一起工作
有人知道我该怎么弄清楚吗
感谢您的时间。以下是我如何使用EF4和我在标准开发人员库中创建的一些通用方法进行动态排序和分页。重要的是第二段代码,您可以使用它为SortBy方法创建Lambda表达式
public enum SqlOrderByDirecton
{
ASC,
DESC
}
//从字符串派生Lambda表达式
字符串sortByKey=“BusinessId”;
字符串值=“DESC”;
var p=表达式参数(typeof(T));
this.SortBy=Expression.Lambda(Expression.TypeAs(Expression.Property(p,sortByKey),typeof(object)),p.Compile();
this.SortOrder=(DevCore.SqlOrderByDirecton)Enum.Parse(typeof(DevCore.SqlOrderByDirecton),value,true);
公共静态列表排序和分页(IEnumerable查询,
Func sortBy,
SqlOrderByDirecton排序器,
整数行限制,
int startRecord,
out int记录计数)
{
recordCount=query.Count();
列表=新列表();
if(sortOrder==SqlOrderByDirecton.ASC)
{
list=query.OrderBy(sortBy).Skip(startRecord).Take(rowLimit).ToList();
}
其他的
{
list=query.OrderByDescending(sortBy).Skip(startRecord).Take(rowLimit).ToList();
}
退货清单;
}
您不能对目标类型使用反射并根据您拥有的名称查找属性并确定正确的类型吗?可能会有帮助!我用Expression.Lambda(Expression.TypeAs(Expression.property(param,request.SortingName),typeof(object)),param)修改了我的代码;然后我做了.Compile();在我的存储库中,它工作得很好。但是…如果我不“编译”查询就不工作。你知道解释是什么吗?@HolloW我不完全确定为什么会这样-我最初是从我问的一个问题中得到代码的,它工作得很好,我没有进一步研究它-它真的正确地映射到SQL的顺序吗?Skip/Take如何?@Konstantin您必须在SQL Server Profiler或其他一些EF工具中检查查询是什么-但我不明白为什么不…OrderBy()是标准的Linq to Entity语法。关于Skip/Take,SQL Server如何实现这一点存在一些复杂性(至少在较旧的2008/12版本中是这样的?)但是它们又是LINQ到实体的推荐的箱外解决方案。BTW我绝不是暗示这些是有效的-这取决于数据的数量和查询的频率。如果您需要快速点亮,则需要考虑本机SQL或我的PREF是一个存储过程或视图。
public enum SqlOrderByDirecton
{
ASC,
DESC
}
//Derive Lambda Expression from string
string sortByKey = "BusinessId";
string value = "DESC";
var p = Expression.Parameter(typeof(T));
this.SortBy = Expression.Lambda<Func<T, dynamic>>(Expression.TypeAs(Expression.Property(p, sortByKey), typeof(object)), p).Compile();
this.SortOrder = (DevCore.SqlOrderByDirecton)Enum.Parse(typeof(DevCore.SqlOrderByDirecton), value, true);
public static List<T> SortAndPaginate<T>(IEnumerable<T> query,
Func<T, object> sortBy,
SqlOrderByDirecton sortOrder,
int rowLimit,
int startRecord,
out int recordCount)
{
recordCount = query.Count();
List<T> list = new List<T>();
if (sortOrder == SqlOrderByDirecton.ASC)
{
list = query.OrderBy(sortBy).Skip(startRecord).Take(rowLimit).ToList();
}
else
{
list = query.OrderByDescending(sortBy).Skip(startRecord).Take(rowLimit).ToList();
}
return list;
}