簡體   English   中英

如何重用Linq To Sql查詢中的where子句

[英]How to reuse where clauses in Linq To Sql queries

我有用戶搜索記錄類型的記錄。 他們在文本框中鍵入搜索詞,然后通過將多個字段與搜索詞匹配來搜索記錄。

我的查詢如下:

var results = from record in DataContext.Records
              where
                   record.Field1.ToLower().Contains(term) ||
                   record.Field2.ToLower().Contains(term) ||
                   record.Field3.ToLower().Contains(term)
              select record;

我有許多查詢都使用相同的過濾器,因此我想提取過濾,以便可以重復使用。 就像是:

var filter = new Func<Record, string, bool>(
                (record, term) =>
                    record.Field1.ToLower().Contains(term) ||
                    record.Field2.ToLower().Contains(term) ||
                    record.Field3.ToLower().Contains(term)
             );

var results = from record in DataContext.Records
              where filter(record, term)
              select record;

但是,它不起作用,因為:

方法'System.Object DynamicInvoke(System.Object [])'沒有支持的SQL轉換。

如何跨查詢重用where where條件?

您需要構建表達式而不是函數:

Expression<Func<Record, bool>> filter = 
  record => record.Field1.ToLower().Contains(term);  // rest omitted

lambda表達式保持不變,但是你需要將它返回到Expression<Func<Record, bool>>類型的變量中 - 這將使C#編譯器將其編譯為表達式而不是委托,允許它被傳遞到LINQ to SQL。

但是,您將無法將表達式變量與C#-syntax where子句一起使用:您需要使用Where擴展方法:

var results = DataContext.Records.Where(filter);

編輯添加:如果您希望能夠在不同的條件上創建過濾器,您只需要一個方法來從術語生成表達式:

private static Expression<Func<Record, bool>> Filter(string term)
{
  return r => r.Field1.ToLower().Contains(term);
}

var results = DataContext.Records.Where(Filter(term));

如果您希望將filter保留為目前的lambda,則可以這樣做,但泛型有點嵌套:

Func<string, Expression<Func<Record, bool>>> filter =
  term => (r => r.Field1.ToLower().Contains(term));

var results = DataContext.Records.Where(filter(term));

無論如何,重要的是Where子句中的內容必須是Expression<Func<Record, bool>> - 但是如上所示,您可以通過動態構建合適的表達式使表達式依賴於term 如果你在Where子句中詳細說明了過濾器,這正是LINQ to SQL所要做的。

使用CompiledQuery

var filter = CompiledQuery.Compile(
    (DatabaseDataContext dc, Record record, string term) =>
        record.Field1.ToLower().Contains(term) ||
        record.Field2.ToLower().Contains(term) ||
        record.Field3.ToLower().Contains(term)
);

var results = from record in DataContext.Records
              where filter(DataContext, record, term)
              select record;

有關更多信息,請參見如何:存儲和重用查詢

除了其他人指出的Expression<Func<Record, bool>>問題之外,我建議調查PredicateBuilder 這對於動態組合lambda表達式非常有用。

我想你需要把它變成Expression<Func<Record, bool>> 否則,它試圖將實際的C#方法調用轉換為SQL而不是它的描述。 這不能保證版本能夠正常運行; 我不確定哪些字符串函數可以轉換為SQL。

暫無
暫無

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

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