簡體   English   中英

LINQ-to-entities通用==解決方法

[英]LINQ-to-entities generic == workaround

我有以下LINQ到實體查詢

IQueryable<History<T>> GetFirstOperationsForEveryId<T>
    (IQueryable<History<T>> ItemHistory)
{
    var q = (from h in ItemHistory
             where h.OperationId ==
                (from h1 in ItemHistory
                 where h1.GenericId == h.GenericId
                 select h1.OperationId).Min()
             select h);
    return q;
}

ItemHistory是通用查詢。 可以通過以下方式獲得

var history1 = MyEntitiySet1.Select(obj =>
    new History<long>{ obj.OperationId, GenericId = obj.LongId });
var history2 = AnotherEntitiySet.Select(obj =>
    new History<string>{ obj.OperationId, GenericId = obj.StringId });

最后,我希望有一個通用查詢能夠與可轉換為History<T>任何實體集合一起使用。

問題是由於內部查詢中的GenericId比較,代碼無法編譯 (運算符'=='不能應用於類型'T'和'T'的操作數)。

如果我將==更改為h1.GenericId.Equals(h.GenericId)h1.GenericId.Equals(h.GenericId)得到以下NotSupportedException

無法將類型“ System.Int64”強制轉換為類型“ System.Object”。 LINQ to Entities僅支持轉換實體數據模型原語類型。

我試圖做分組而不是子查詢並加入結果。

IQueryable<History<T>> GetFirstOperationsForEveryId<T>
    (IQueryable<History<T>> ItemHistory)
{
    var grouped = (from h1 in ItemHistory
                   group h1 by h1.GenericId into tt
                   select new
                   {
                        GenericId = tt.Key,
                        OperationId = tt.Min(ttt => ttt.OperationId)
                   });

    var q = (from h in ItemHistory
             join g in grouped
                on new { h.OperationId, h.GenericId }
                equals new { g.OperationId, g.GenericId }
             select h);
    return q;
}

之所以進行編譯,是因為將GenericId與equals關鍵字進行了比較,並且可以正常工作,但是帶有真實數據的查詢速度太慢(它已經在專用的postgresql服務器上運行了11個小時)。

有一個選項可以為外部where語句構建整個表達式。 但是代碼太長且不清楚。

是否有任何簡單的變通辦法,可以與LINQ-to-entities中的泛型進行相等性比較?

試試這個,我認為它應該完成您想要的,而無需額外的查詢/加入

IQueryable<History<T>> GetFirstOperationsForEveryId<T>
    (IQueryable<History<T>> ItemHistory)
{
  var q = from h in ItemHistory
          group h by h.GenericId into tt
          let first = (from t in tt
                        orderby t.GenericId
                        select t).FirstOrDefault()
          select first;

  return q;
}
IQueryable<History<T>> GetFirstOperationsForEveryId<T>
(IQueryable<History<T>> ItemHistory)
{
var grouped = (from h1 in ItemHistory
               group t by h1.GenericId into tt
               select new
               {
                    GenericId = tt.Key,
                    OperationId = tt.Min(ttt => ttt.OperationId)
               });

var q = (from h in ItemHistory
         join g in grouped
            on new { h.OperationId, h.GenericId }
            equals new { g.OperationId, g.GenericId }
         select h);
return q;
}

您還可以在I上為實現GenericId和OperationId屬性的IItemHistory接口設置通用約束。

我的問題已經包含解決方案。 如果表已正確索引,則使用group + join的第二種方法效果很好。 從數據庫表檢索370k行需要3.28秒。 實際上,在非泛型變量中,第一個查詢在postgresql上比第二個查詢慢。 26.68秒和4.75秒

暫無
暫無

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

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