在投影中对嵌套集合进行排序:无法将“SortOp”类型的对象强制转换为“ProjectOp”类型

时间:2013-10-18 07:52:14

标签: c# entity-framework entity-framework-6

我正在使用查询结果投影到自定义类型,而自定义类型不是实体数据模型的一部分:

public sealed class AlgoVersionCacheItem : NotificationObject
{
    public int OrderId { get; set; }
    public string OrderTitle { get; set; }
    public int? CurrentVersion { get; set; }
    public int CachedVersion { get; set; }
    public IEnumerable<int> AvailableVersions { get; set; }
}

我希望AvailableVersions按降序排序。因此,我尝试在投影中添加AvailableVersions的排序:

        return someQueryable
            .Select(version => new AlgoVersionCacheItem
            {
                OrderId = version.OrderId,
                OrderTitle = version.Order.Title,
                CurrentVersion = version.Order.CurrentAlgoVersionId,
                CachedVersion = version.Id,
                AvailableVersions = version
                    .Order
                    .AlgoVersions
                    .Where(v => (allowUncommittedVersions || v.Statuses.Any(s => s.AlgoVersionStatusListItemId == ModelConstants.AlgoVersionCommitted_StatusId)) && v.Id != version.Id)
                    .OrderByDescending(v => v.Id) // this line will cause exception
                    .Select(v => v.Id)
            })
            .Where(item => item.AvailableVersions.Any())
            .OrderByDescending(item => item.OrderId)
            .ToArray();

通过排序,执行查询会引发System.Data.EntityCommandCompilationException System.InvalidCastException作为内部异常:

  

无法投射类型的对象   键入'System.Data.Entity.Core.Query.InternalTrees.SortOp'   'System.Data.Entity.Core.Query.InternalTrees.ProjectOp'

没有.OrderByDescending(v => v.Id)一切正常 这是另一个功能,实体框架不支持,或者我错过了什么?

P.S。我知道,我可以稍后在客户端对项目进行排序,但我想知道在服务器端进行排序。

2 个答案:

答案 0 :(得分:8)

这是EF中的一个错误。我能够在EF5和EF6上重现这一点。我认为你应该能够在创建结果之前通过过滤记录来解决这个问题,即:。

return someQueryable
    .Where(version => version.Order.AlgoVersions.Any(v => (allowUncommittedVersions || v.Statuses.Any(s => s.AlgoVersionStatusListItemId == ModelConstants.AlgoVersionCommitted_StatusId)) && v.Id != version.Id))
    .Select(version => new AlgoVersionCacheItem
        {
            OrderId = version.OrderId,
            OrderTitle = version.Order.Title,
                CurrentVersion = version.Order.CurrentAlgoVersionId,
                CachedVersion = version.Id,
                AvailableVersions = version
                    .Order
                    .AlgoVersions
                    .Where(v => (allowUncommittedVersions || v.Statuses.Any(s => s.AlgoVersionStatusListItemId == ModelConstants.AlgoVersionCommitted_StatusId)) && v.Id != version.Id)
                    .OrderByDescending(v => v.Id) // this line will cause exception
                    .Select(v => v.Id)
        })
    .OrderByDescending(item => item.OrderId)
    .ToArray();

我还有一种感觉,如果你从关系的另一端(即从Orders)开始,这个查询可以简化,但它可能取决于someQueryable的创建方式。

答案 1 :(得分:0)

在我的情况下,Linq查询正在选择一个新的匿名构造,该构造将一个属性设置为集合ToList()扩展方法。我删除了嵌入式执行,错误消失了,系统仍然运行正常。