[英]Convert Method to Linq Expression for query
在我們的應用程序中,我們希望為數據庫中的各種條件提供標准方法。 例如,我們有不同類型的事務,我們希望創建標准方法以在其他查詢中檢索它們。 但是,這給了我們錯誤:
方法''沒有支持的SQL轉換
該方法可能如下所示:
public static bool IsDividend(this TransactionLog tl)
{
return tl.SourceTypeID == (int)JobType.Dividend || tl.SourceTypeID == (int)JobType.DividendAcct;
}
要這樣使用:
var dividends = ctx.TransactionLogs.Where(x => x.IsDividend());
當然,如果我將邏輯從IsDividend()
復制到Where
子句中,這樣可以正常工作,但我最終會將這個邏輯復制到很多地方,並且如果邏輯發生變化則難以追蹤。
我想如果我將它轉換為這樣的表達式它可以工作,但這不是一個優秀的設置,因為能夠使用方法:
public Expression<Func<TransactionLog, bool>> IsDividend = tl => tl.SourceTypeID == (int)JobType.Dividend || tl.SourceTypeID == (int)JobType.DividendAcct;
var dividends = ctx.TransactionLogs.Where(IsDividend);
有沒有辦法迫使Linq將方法評估為表達式? 或者將方法調用“轉換”為linq查詢中的表達式? 像這樣的東西:
var dividends = ctx.TransactionLogs.Where(tl => ToExpression(tl.IsDividend));
我們在我們的應用程序中使用Linq-to-SQL。
好吧,包含表達式的靜態屬性對我來說似乎很好。
使其與方法一起使用的唯一方法是創建一個返回此表達式的方法,然后在其中調用它:
public class TransactionLog
{
Expression<Func<TransactionLog, bool>> IsDividend() {
Expression<Func<TransactionLog, bool>> expression = tl => tl.SourceTypeID == (int)JobType.Dividend || tl.SourceTypeID == (int)JobType.DividendAcct;
return expression;
}
}
public class TransactionLogExtension
{
Expression<Func<TransactionLog, bool>> IsDividend(this TransactionLog log) {
Expression<Func<TransactionLog, bool>> expression = tl => tl.SourceTypeID == (int)JobType.Dividend || tl.SourceTypeID == (int)JobType.DividendAcct;
return expression;
}
}
並通過它使用它
var dividends = ctx.TransactionLogs.Where(TransactionLog.IsDividend());
或作為擴展方法
var dividends = ctx.TransactionLogs.Where(x.IsDividend());
但是沒有一個能用於var dividends = ctx.TransactionLogs.Where(x => x.IsDividend());
因為x => x.IsDividend();
本身是一個表達式樹,您的數據庫提供程序無法將“IsDividend”轉換為SQL語句。
但是其他兩個選項至少允許您傳入參數(如果將表達式存儲為實例或靜態屬性,則這些參數不起作用)。
我認為LINQ to SQL並不完全支持常見和內置函數。 (至少EF沒有這樣做)。 而且 - 當它處理用戶定義的方法時。 我預測,除非在枚舉后調用它(ToList或類似方法),否則帶表達式的變體將與使用方法調用的變量一樣下降。 我建議保持1)存儲過程在服務器之間的平衡,2)在C#中的Where
子句中硬編碼的常見條件,3)在C#中生成表達式樹。 所有這些都是相對復雜的,當然(在我看來,沒有簡單和通用的解決方案)。
嘗試使用擴展方法,如下所示:
public static class TransactionLogExtensions {
public static IQueryable<TransactionLog> OnlyDividends(this IQueryable<TransactionLog> tl)
{
return tl.Where(t=>t.SourceTypeID == (int)JobType.Dividend || t.SourceTypeID == (int)JobType.DividendAcct);
}
}
這樣稱呼它:
var dividends=db.TransactionLogs.OnlyDividends();
要么
var dividends=db.TransactionLogs.OnlyDividends().OrderBy(...);
對於這種情況,您可以使用Func。 Linq對那些非常好。 以下是在Linq查詢中使用Func的簡單示例。 隨意修改和使用。
Func<int,bool> isDivident = x => 3==x;
int[] values = { 3, 7, 10 };
var result = values.Select (isDivident );
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.