c# – LINQ to Entities和LINQ to Objects处理强制转换的方式不同
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – LINQ to Entities和LINQ to Objects处理强制转换的方式不同,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3661字,纯文字阅读大概需要6分钟。
内容图文
我最近加入了一个项目,其中Sort方法有条件地将lambda表达式传递给LINQ查询以定义应该对哪个属性进行排序.问题是lambda表达式是在Func< TEntity,Object>中传递的.而不是表达式< Func< TEntity,Object>>因此,排序发生在内存而不是数据库中(因为调用了带有IEnumerable的OrderBy的重载).这是SortWithDelegate中的版本(见下文).
当我使用表达式< Func< TEntity,Object>> (参见下面的SortWithExpression)然后,当在orderBy参数中传递字符串属性时,在数据库中正确完成排序.但是,当我尝试使用Expression< Func< TEntity,Object>>对整数(或日期时间)进行排序时我收到以下错误:
无法将类型“System.Int32”强制转换为“System.Object”类型. LINQ to Entities仅支持转换EDM原语或枚举类型.
为了避免这种情况,我必须将整数或日期时间字段包装在匿名类型内部,如下所示:orderByFunc = sl => new {sl.ParentUnit.Id};.我知道我需要这样做,因为Func的返回类型是Object.但是,我不明白为什么在使用LINQ to Entities提供程序而不是LINQ to Objects提供程序时需要执行此操作?
void Main()
{
var _context = new MyContext();
string sortProperty = "Id";
bool sortAscending = false;
IQueryable<Qualification> qualifications = _context.Qualifications.Include(q => q.ParentUnit);
qualifications = SortWithExpression(sortProperty, sortAscending, qualifications);
qualifications.Dump();
}
private static IQueryable<Qualification> SortWithDelegate(string orderBy, bool sortAscending, IQueryable<Qualification> qualificationsQuery)
{
Func<Qualification, Object> orderByFunc;
switch (orderBy)
{
case "Name":
orderByFunc = sl => sl.Name;
break;
case "ParentUnit":
orderByFunc = sl => sl.ParentUnit.Name;
break;
case "Id":
orderByFunc = sl => sl.ParentUnit.Id;
break;
case "Created":
orderByFunc = sl => sl.Created;
break;
default:
orderByFunc = sl => sl.Name;
break;
}
qualificationsQuery = sortAscending
? qualificationsQuery.OrderBy(orderByFunc).AsQueryable()
: qualificationsQuery.OrderByDescending(orderByFunc).AsQueryable();
return qualificationsQuery;
}
private static IQueryable<Qualification> SortWithExpression(string orderBy, bool sortAscending, IQueryable<Qualification> qualificationsQuery)
{
Expression<Func<Qualification, Object>> orderByFunc;
switch (orderBy)
{
case "Name":
orderByFunc = sl => sl.Name;
break;
case "ParentUnit":
orderByFunc = sl => sl.ParentUnit.Name;
break;
case "Id":
orderByFunc = sl => new {sl.ParentUnit.Id};
break;
case "Created":
orderByFunc = sl => new {sl.Created};
break;
default:
orderByFunc = sl => sl.Name;
break;
}
qualificationsQuery = sortAscending
? qualificationsQuery.OrderBy(orderByFunc)
: qualificationsQuery.OrderByDescending(orderByFunc);
return qualificationsQuery;
}
添加
我以为我会为这个问题添加自己的解决方案.为了避免装箱int和datetime,我在IQueryable< T>上创建了一个通用的扩展方法.我传入lambda表达式来指示sort字段,以及一个布尔值,指示排序顺序是否应该升序:
public static IQueryable<TSource> OrderBy<TSource, TResult>(this IQueryable<TSource> query, Expression<Func<TSource, TResult>> func, bool sortAscending)
{
return sortAscending ?
query.OrderBy(func) :
query.OrderByDescending(func);
}
private static IQueryable<Qualification> Sort(string orderBy, bool sortAscending, IQueryable<Qualification> qualificationsQuery)
{
switch (orderBy)
{
case "Name":
return qualificationsQuery.OrderBy(sl => sl.Name, sortAscending);
case "ParentUnit":
return qualificationsQuery.OrderBy(s1 => s1.ParentUnit.Name, sortAscending);
default:
return qualificationsQuery.OrderBy(sl => sl.Name, sortAscending);
}
}
解决方法:
表达树顾名思义就是关于做某事的表达.你可以访问表达式并将它们解释为你自己的业务,或者像lambda表达式一样,你可以编译它们并作为委托调用.
当您将表达式传递给Linq to Entities中的orderby方法时,Linq将访问实体,并且在您的情况下将生成“Int32 to Object”异常,因为它被解释为成为列名的MemberInfo用于数据库查询.但是当你将它用作Func委托时,它无法被翻译,它将被调用为orderby方法的排序算法中的委托.
内容总结
以上是互联网集市为您收集整理的c# – LINQ to Entities和LINQ to Objects处理强制转换的方式不同全部内容,希望文章能够帮你解决c# – LINQ to Entities和LINQ to Objects处理强制转换的方式不同所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。