首先:我們是而不是正在執行TPH(每個層次的表),這將使這更簡單很多。在SQL Server上過濾實體框架結果
我有大約20個POCO在某些情況下都具有相似的屬性。我關心的類似房產是___.CreatedDate
和___.UpdatedDate
。對於一些POCO,UpdatedDate
沒有意義,所以他們沒有這個屬性。 CreatedDate
將始終存在,UpdatedDate
可能爲空。有時候還有第三個領域。
無論我正在查詢的20個POCO中的哪一個,從數據庫中檢索對象的查詢總是看起來相同。但是,查詢重複了20次,每種類型的對象都有一次。我能夠將檢索部分分解爲擴展方法(關閉IDbSet<T>
)以執行初始查找和連接,將日期範圍篩選作爲鍛鍊留給消費者。我現在想要將20個幾乎完全相同的日期範圍過濾器合併爲一個,但遇到查詢理解問題。
每個POCO的日期過濾邏輯是應該檢查UpdatedDate,並將其值與閾值進行比較。如果UpdatedDate爲null(或者該屬性不存在),則應該使用CreatedDate。
< /背景>
我開始通過創建每個POCO,我命名爲 「DateFields」 靜態屬性獲取。它的類型爲,看起來像這樣:
get
{
yield return x => x.UpdatedDate;
yield return x => x.CreatedDate;
yield return x => x.Date;
}
這些字段中,我希望他們檢查,並各自獨有的POCO順序返回。
然後,我創建了一個謂詞來對抗高和低量程檢查每個值:
public static bool DatesBetween<T> (T value, IEnumerable<Expression<Func<T, DateTime?>>> dates, DateTime? dateFrom, DateTime? dateTo)
{
var firstDate = dates
.Select(expression => expression.Compile())
.FirstOrDefault(func => func(value) != null);
if (firstDate == null)
return false;
var minDate = dateFrom.GetValueOrDefault(SqlDateTime.MinValue.Value);
var maxDate = dateTo.GetValueOrDefault(SqlDateTime.MaxValue.Value);
var actualDate = firstDate(value);
return (minDate <= actualDate && actualDate <= maxDate);
}
然而,正如所料,當我嘗試在我的IQueryable
利用這一點,我得到一個運行時異常,因爲有沒有翻譯到SQL中的DatesBetween。我希望通過保留表達樹,我可以......我不知道......讓EF快樂。整個事情是這樣使用:
return Entities
.GetEntitiesBySomeField(field := "magic value")
.Where(entity => RepositoryExtensions.DatesBetween(entity, MyPOCO.MyDates, dateFrom, dateTo));
是我要問清楚,有沒有辦法來完成這種通用的過濾,而不做一個AsEnumerable()(它的工作,但不完成我在數據庫上過濾的目標)。
我可以改變實施。我試圖用我的'DatesBetween'方法來構建SQL。問題是我的謂詞比正常情況更復雜,因爲它的條件是基於哪些屬性存在或不存在。我一直沒有想出一種方法來通用化這個決定,而沒有EF對此做出反應。 –
我在回答中添加了一個代碼塊,它可以解決您的問題。它使用反射檢查類型上是否存在屬性。 – doogle