簡體   English   中英

僅日期時間對象實體框架上的動態LINQ OrderBy日期

[英]Dynamic LINQ OrderBy Date only on DateTime Object Entity Framework

我目前正在使用Dynamic LINQ原始Codeplex鏈接 )庫來實現動態搜索功能。 我有一個需要OrderBy DateTime? 字段僅考慮日期而不是時間。 我正在使用EntityFramework查詢SQL Azure數據庫。

這是示例實體。

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 Entities不支持它,因此引發了以下錯誤(可以理解)。 請記住,這必須在IQueryable上起作用( 我不能使用本文的答案 ),因為我需要在服務器端進行排序。

LINQ to Entities不支持指定的類型成員'Date'。 僅支持初始化程序,實體成員和實體導航屬性。

解決方案是使用此答案和其他答案中表示的DbFunctions.TruncateTime() 但是,這不適用於System.Linq.Dynamic

關於如何解決此問題的任何想法。 可能的解決方案是僅將DateCreated的Date部分添加到數據庫中的另一列,然后查詢該列。 但是,我寧願不這樣做,而是在尋找其他解決此問題的方法。 另一種方法是動態生成lambda表達式,並返回DbFunctions.TruncateTime,然后對數據庫執行該表達式。 任何輸入表示贊賞。

謝謝,

您可以使用從我的答案到Dynamic Linq + Entity Framework的方法:動態選擇的datetime修改 ,即使用自定義ExpressionVisitor對查詢表達式進行后處理,並用其DbFunctions等效項替換不受支持的方法。 在這種特殊情況下,用DbFunctions.TruncateTime方法調用替換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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM