C# DateTime对象实体框架上的动态LINQ OrderBy Date only
我目前正在使用该库实现动态搜索功能。我有一个要求,我需要按日期时间订购?字段只考虑日期而不考虑时间。 我正在使用EntityFramework查询SQL Azure数据库 这是示例实体C# DateTime对象实体框架上的动态LINQ OrderBy Date only,c#,entity-framework,linq,entity-framework-6,linq-to-entities,C#,Entity Framework,Linq,Entity Framework 6,Linq To Entities,我目前正在使用该库实现动态搜索功能。我有一个要求,我需要按日期时间订购?字段只考虑日期而不考虑时间。 我正在使用EntityFramework查询SQL Azure数据库 这是示例实体 public class SampleEntity { public DateTime? DateCreated { get; set; } public bool Flag { get; set; } } 下面是查询数据库的代码 var orderByString = "DateCreated
public class SampleEntity
{
public DateTime? DateCreated { get; set; }
public bool Flag { get; set; }
}
下面是查询数据库的代码
var orderByString = "DateCreated.Value.Date asc, Flag"; //This is a dynamic string
var query = _context.Set<SampleEntity>().OrderBy(orderByString);
System.Linq.Dynamic解析此表达式DateCreated.Value.Date时没有任何问题,但它抛出以下错误,这是可以理解的,因为Linq to实体不支持此表达式。
请记住,这必须在IQueryable上工作,因为我需要在服务器端完成排序
LINQ to实体中不支持指定的类型成员“日期”。仅支持初始值设定项、实体成员和实体导航属性
解决方案是使用DbFunctions.TruncateTime和其他表达式。但是,这在System.Linq.Dynamic中不起作用
关于如何解决这个问题有什么想法吗。可能的解决方案是向数据库中添加另一列,只包含DateCreated的日期部分,然后查询该列。然而,我宁愿不这样做,并且正在寻找解决这个问题的其他方法。
另一种方法是动态生成lambda表达式并返回DbFunctions.TruncateTime,然后对DB执行该表达式。
欢迎您的任何意见
谢谢,您可以使用我的答案中的方法,即使用自定义对查询表达式进行后期处理,并使用其DbFunctions等价物替换不受支持的方法。在这种特殊情况下,用方法调用替换DateTime.Date属性:
public static class QueryableExtensions
{
public static IQueryable<T> BindDbFunctions<T>(this IQueryable<T> source)
{
var expression = new DbFunctionsBinder().Visit(source.Expression);
if (expression == source.Expression) return source;
return source.Provider.CreateQuery<T>(expression);
}
public static IQueryable BindDbFunctions(this IQueryable source)
{
var expression = new DbFunctionsBinder().Visit(source.Expression);
if (expression == source.Expression) return source;
return source.Provider.CreateQuery(expression);
}
class DbFunctionsBinder : ExpressionVisitor
{
protected override Expression VisitMember(MemberExpression node)
{
if (node.Expression != null && node.Expression.Type == typeof(DateTime) && node.Member.Name == "Date")
{
var dateValue = Expression.Convert(Visit(node.Expression), typeof(DateTime?));
var methodCall = Expression.Call(typeof(DbFunctions), "TruncateTime", Type.EmptyTypes, dateValue);
return Expression.Convert(methodCall, typeof(DateTime));
}
return base.VisitMember(node);
}
}
}
示例用法:
var orderByString = "DateCreated.Value.Date asc, Flag"; //This is a dynamic string
var query = _context.Set<SampleEntity>().OrderBy(orderByString).BindDbFunctions();
您可以使用my answer to的方法,即使用custom对查询表达式进行后期处理,并使用其DbFunctions等价物替换不受支持的方法。在这种特殊情况下,用方法调用替换DateTime.Date属性:
public static class QueryableExtensions
{
public static IQueryable<T> BindDbFunctions<T>(this IQueryable<T> source)
{
var expression = new DbFunctionsBinder().Visit(source.Expression);
if (expression == source.Expression) return source;
return source.Provider.CreateQuery<T>(expression);
}
public static IQueryable BindDbFunctions(this IQueryable source)
{
var expression = new DbFunctionsBinder().Visit(source.Expression);
if (expression == source.Expression) return source;
return source.Provider.CreateQuery(expression);
}
class DbFunctionsBinder : ExpressionVisitor
{
protected override Expression VisitMember(MemberExpression node)
{
if (node.Expression != null && node.Expression.Type == typeof(DateTime) && node.Member.Name == "Date")
{
var dateValue = Expression.Convert(Visit(node.Expression), typeof(DateTime?));
var methodCall = Expression.Call(typeof(DbFunctions), "TruncateTime", Type.EmptyTypes, dateValue);
return Expression.Convert(methodCall, typeof(DateTime));
}
return base.VisitMember(node);
}
}
}
示例用法:
var orderByString = "DateCreated.Value.Date asc, Flag"; //This is a dynamic string
var query = _context.Set<SampleEntity>().OrderBy(orderByString).BindDbFunctions();
谢谢,如果一切正常,我们将尝试实现这一点,并将其标记为答案。谢谢,如果一切正常,我们将尝试实现这一点,并将其标记为答案。为什么这不能开箱即用?这个需求几乎存在于每个软件项目中。为什么它不能开箱即用呢?这一需求几乎存在于每个软件项目中。