加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – LINQ to Entities和LINQ to Objects处理强制转换的方式不

发布时间:2020-12-15 22:10:19 所属栏目:百科 来源:网络整理
导读:我最近加入了一个项目,其中Sort方法有条件地将lambda表达式传递给LINQ查询以定义应该对哪个属性进行排序.问题是lambda表达式是在Func TEntity,Object中传递的.而不是表达式 Func TEntity,Object因此,排序发生在内存而不是数据库中(因为调用了带有IEnumerable
我最近加入了一个项目,其中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,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,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方法的排序算法中的委托.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读