簡體   English   中英

將方法轉換為Linq表達式以進行查詢

[英]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.

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