entity-framework - LINQ to Entities - 无法按顺序将 'System.DateTime' 转换为 'System.Object'

标签 entity-framework linq-to-entities

我正在尝试从传入的 Expression< Func< T, object>> 中按日期订购实体的 IQueryable 并收到错误:“无法将类型 'System.Nullable`1' 转换为类型 'System.Object' . LINQ to Entities 仅支持强制转换实体数据模型原始类型。”该实体上有一个可为空的日期时间属性,我正在尝试对其进行排序:

示例:(其中 e.Date 是可为空的 DateTime)

Expression<Func<T,object>> sorter = (e) => e.Date;
IOrderedQueryable<T> sortedData = data.OrderBy(sorter);

提前致谢!

最佳答案

我编写了一个简单的类,用于在运行时基于 lambda 表达式对实体进行排序。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace DataModeling
{
    public class QueryOrderer<TEntity>
        where TEntity : class
    {
        private LambdaExpression defaultSortExpression;
        private Dictionary<string, LambdaExpression> orderFieldLookup;

        public QueryOrderer()
        {
            orderFieldLookup = new Dictionary<string, LambdaExpression>();
        }

        public void AddOrderMapping<TProp>(string fieldName, Expression<Func<TEntity, TProp>> selector)
        {
            orderFieldLookup[fieldName] = selector;
        }

        public void SetDefaultSortExpression<TProp>(Expression<Func<TEntity, TProp>> selector)
        {
            defaultSortExpression = selector;
        }

        public IQueryable<TEntity> GetOrderedEntries(string field, bool isDescending, IQueryable<TEntity> entries)
        {
            return orderEntries(entries, field, isDescending);
        }

        private IQueryable<TEntity> orderEntries(IQueryable<TEntity> entries, string fieldName, bool isDescending)
        {
            dynamic lambda = getOrderByLambda(entries, fieldName);
            if (lambda == null)
            {
                return entries;
            }
            if (isDescending)
            {
                return Queryable.OrderByDescending(entries, lambda);
            }
            else
            {
                return Queryable.OrderBy(entries, lambda);
            }
        }

        private dynamic getOrderByLambda(IQueryable<TEntity> entries, string fieldName)
        {
            if (!String.IsNullOrWhiteSpace(fieldName) && orderFieldLookup.ContainsKey(fieldName))
            {
                return orderFieldLookup[fieldName];
            }
            else
            {
                return defaultSortExpression;
            }
        }
    }
}

您可以通过最初设置所有字段来使用此类:
QueryOrderer<User> orderer = new QueryOrderer<User>();
orderer.SetDefaultSortExpression(u => u.FullName);
orderer.AddOrderMapping("UserId", u => u.UserId);
orderer.AddOrderMapping("Name", u => u.FullName);
orderer.AddOrderMapping("Email", u => u.Email);
orderer.AddOrderMapping("CreatedOn", u => u.CreatedOn);

...

var users = orderer.GetOrderedEntries("CreatedOn", isDescending: false, context.Users);

我这段代码的一个很好的特点是它可以完美地处理查找值。例如,如果您尝试使用描述而不是键进行排序,则可以在构建排序表达式时使用外部上下文:
orderer.AddOrderMapping("UserType", 
    u => context.UserTypes
                .Where(t => t.UserTypeId == u.UserTypeId)
                .Select(t => t.Description)
                .FirstOrDefault());

Entity Framework 足够智能,可以将子查询直接折叠到外部查询中。

关于entity-framework - LINQ to Entities - 无法按顺序将 'System.DateTime' 转换为 'System.Object',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5175168/

相关文章:

c# - 强制 Entity Framework 6 查询使用正确的索引

c# - C#实体TableServiceContext.CreateQuery

c# - 使用 Linq 的多个复选框选择结果,无需硬编码

linq-to-entities - Dynamic Linq .Select() - 如何处理某些空值

c# - 使用 LINQ to Entities 向表中插入多条记录的正确方法

c# - 使用多个 DB 架构的 EF Core 迁移

c# - Entity Framework : get all entities with specific type

c# - 为什么 Asp.Net Identity IdentityDbContext 是黑盒?

c# - 使用 Linq-To-Entities 时可以创建嵌套类吗?

c# - 当我的 LINQ 查询将数据库记录作为 Enumerable 获取并在 foreach 循环中访问记录时会发生什么?