Опции для совместного использования кода в выражениях Linq2SQL - PullRequest
2 голосов
/ 01 сентября 2009

У меня есть пара запросов Linq to SQL, которые содержат одно и то же сложное предложение Where, а именно:

where ((range.MinimumFrequency <= minFreq &&  minFreq <= range.MaximumFrequency)
|| (range.MinimumFrequency <= maxFreq && maxFreq <= range.MaximumFrequency)
|| (range.MinimumFrequency <= minFreq && maxFreq <= range.MaximumFrequency)
|| (range.MinimumFrequency >= minFreq && maxFreq >= range.MaximumFrequency))

И вместо того, чтобы копировать и вставлять этот кусок кода повсюду, я хотел преобразовать его во что-то еще, что можно было бы использовать совместно. Я знаю, что не могу сделать это обычным методом, так как он не может быть переведен в SQL, но я также не могу получить

Выражение >

вещей , описанных здесь для работы либо.

Если я упросту предложение where в целях моего здравомыслия, я хочу включить

where (range.MinumumFrequency < minFreq) 

в выражение, поэтому я попытался:

public static Expression<Func<FreqRange, bool>> Overlaps(decimal minMHz, decimal maxMHz)
{
   return (range => range.MinimumFrequency <= minMHz);
}

Это похоже на компиляцию, но я не могу заставить оператор where работать, я попробовал следующее:

where FreqRange.Overlaps(minMHz, maxMHz)

но это дает мне ошибку времени компиляции:

Невозможно неявно преобразовать тип 'System.Linq.Expressions.Expression>' "bool"

Есть идеи? Кроме того, предполагая, что это работает, могу ли я просто расширить лямбда-выражение в выражении >, чтобы включить другие условия?

Ответы [ 2 ]

2 голосов
/ 01 сентября 2009

Если вы используете синтаксис LINQ для построения языка, вы неявно объявляете выражение lamba - и , что выражение lamba - Expression<Func <>> - поэтому вам не нужно выражение where для вернуть Выражение, вам нужно, чтобы было выражением.

1010 *, например *

var q = from row in myTable
        where row.a < aMax
        select row.b;

// which translates to

var q = myTable.Where(row => row.a < aMax).Select(row => row.b);

Теперь вам нужно «кешировать» row => row.a < aMax, а не просто значение из row.a < aMax, если хотите. Итак, если бы вы написали что-то вроде этого ...

Expression<Func<?,bool>> cachedExpression = row => row.a < aMax;

var q = from row in myTable
        where cachedExpression
        select row.b;

Ну, вы говорите: "где, для строки, верно, что (для строки верно, что row.a меньше, чем aMax)". Это нонсенс, и он не будет компилироваться, если cachedExpression имеет тип Expression<Func<?,bool>>, а myTable - это таблица, предоставленная LinqToSql. Это будет означать что-то вроде этого:

Expression<Func<?,bool>> cachedExpression = row => row.a < aMax;

//nonsense .Where:
var q = myTable.Where(row => cachedExpression).Select(row => row.b);
//effectively says this:
var q = myTable.Where(row => (row0 => row0.a < aMax)).Select(row => row.b);

Теперь, это допустимо в том смысле, что возможно для поставщика запросов linq реализовать выражение where с ненулевым значением, но это очень странная вещь делать; конечно, ни один из стандартных провайдеров linq (таких как Linq to Sql) не делает этого.

Так что должен делать? Что-то вроде:

//not .Where(row=>cachedExpression)!
var q = myTable.Where(cachedExpression).Select(row => row.b);

//or, alternatively:
var q = from filteredRow in myTable.Where(cachedExpression)
        select filteredRow.b;
1 голос
/ 01 сентября 2009

Вы также можете создать метод, который принимает и отправляет IQueryable. Я использовал подобные представления, но только в коде.

public class WithProps
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
    public override string ToString()
    {
        return string.Format("{0}-{1}", Prop1, Prop2);
    }
}

public static class Tools
{
    public static IQueryable<WithProps> MyFilter(this IQueryable<WithProps> props)
    {
        return props.Where(p => p.Prop1 == "hi");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var propList = new List<WithProps>()
        {
            new WithProps(){ Prop1="hi", Prop2="there"},
            new WithProps(){ Prop1="hi", Prop2="bye"},
            new WithProps(){ Prop1="hello", Prop2="world"},
            new WithProps(){ Prop1="bye", Prop2="friend"}
        };

        var filtered = propList.AsQueryable().MyFilter();

        Console.WriteLine("propList ===");
        foreach (var item in propList)
            Console.WriteLine(item.ToString());
        Console.WriteLine("filtered ===");
        foreach (var item in filtered)
            Console.WriteLine(item.ToString());
    }
}

... результаты ...

propList ===
hi-there
hi-bye
hello-world
bye-friend
filtered ===
hi-there
hi-bye
...