2009-11-02 12 views
7

Mam kwerendy Linq, który wygląda mniej więcej tak:LINQ: Prosta funkcja logiczna zwraca LINQ Wyjątek

var query = from x in table where SomeFunctionReturnsBool() select; 

private bool SomeFunctionReturnsBool() 
{ 
    return true; 
} 

to zwraca i wyjątku, który mówi „SomeFunctionReturnsBool ma obsługiwanego tłumaczenia do SQL”. Rozumiem, że to dlatego, że chce traktować "SomeFunctionReturnsBool" jako wyrażenie do oceny jako SQL, ale nie może.

Chociaż to zapytanie Linq nie jest skomplikowane, prawdziwe są. W jaki sposób mogę osiągnąć to, co próbuję tutaj zrobić, to jest rozbić fragmenty zapytania, aby mieć nadzieję, że będzie on bardziej czytelny?

Jeff

UPDATE dobre odpowiedzi. Staram się pracować z wyrażeń zamiast, ale ten kod robi mi „nie można rozwiązać metodą Gdzie (wyrażenie lambda)”:

var query = from x in table where SomeFunctionReturnsBool() select x; 

private Expression<Func<EligibilityTempTable, bool>> SomeFunctionReturnsBool 
{ 
    return (x) => true; 
} 
+0

odpowiedział na komentarz, pokazując (wątpliwą) sposób wykorzystania tego podejścia ze składni zapytań. –

Odpowiedz

7

Innym sposobem jest użycie Expression<Func<YourType, bool>> predykat ...

var query = from x in table where SomeFunctionReturnsBool() select; 

Edit: Zwykle nie zrobić go w sposób pokazany powyżej ja ... Ja tylko, że uzyskanie od kodu powyżej. Oto sposób, w jaki zwykle go realizuję. Ponieważ możesz wtedy zastosować dodatkowe metody Enumerable lub skomentować je podczas debugowania.

var results = table.Where(SomeFunctionReturnsBool()) 
    .OrderBy(yt => yt.YourProperty) 
    //.Skip(pageCount * pageSize) //Just showing how you can easily comment out parts... 
    //.Take(pageSize) 
    .ToList(); //Finally executes the query... 

private Expression<Func<YourType, boo>> SomeFunctionReturnsBool() 
{ 
    return (YourType yt) => yt.YourProperty.StartsWith("a") 
     && yt.YourOtherProperty == true; 
} 

Wolę używać PredicateBuilder który pozwala budować wyrażenia do wykorzystania w swojej Gdzie ...

+1

+1 dla PredicateBuilder. To fajnie. – Tinister

+0

Z jakiegoś powodu zrobienie tego powoduje błąd w miejscu "nie można rozwiązać metody, gdzie (wyrażenie lambda)" – jlembke

+0

Nie wiem, dlaczego mam -2, byłoby miło, gdybyś miał "czas" na wyjaśnienie swojego głosowania w dół ... – bytebender

3

Można to zrobić w LINQ-SQL poprzez tworzenie UDF odwzorowane do kontekst danych; wymaga to pisania TSQL i użycia ctx.SomeFunctionblah (...).

Alternatywą jest do pracy z drzew wyrażenie - na przykład może to być:

Expression<Func<Customer, bool>> SomeFunc() { 
    return c => true; // or whatever 
} 

i używać .Where(SomeFunc()) - jest wystarczająco blisko? Nie można użyć składni zapytań w tej sprawie, ale dostaje zadanie ...


Dodano podejrzanie Where sposób, aby pokazać, w jaki sposób może go używać w składni zapytania. I do not sugeruje, że jest to fantastyczne, ale może się przydać.

using System; 
using System.Linq; 
using System.Linq.Expressions; 

static class Program 
{ 
    static void Main() 
    { 
     using (var ctx = new NorthwindDataContext()) 
     { 
      ctx.Log = Console.Out; 
      // fluent API 
      var qry = ctx.Customers.Where(SomeFunc("a")); 
      Console.WriteLine(qry.Count()); 

      // custom Where - purely for illustration 
      qry = from c in ctx.Customers 
        where SomeFunc("a") 
        select c; 
      Console.WriteLine(qry.Count()); 
     } 
    } 
    static IQueryable<T> Where<T>(this IQueryable<T> query, 
     Func<T, Expression<Func<T, bool>>> predicate) 
    { 
     if(predicate==null) throw new ArgumentNullException("predicate"); 
     return query.Where(predicate(default(T))); 
    } 
    static Expression<Func<Customer, bool>> SomeFunc(string arg) 
    { 
     return c => c.CompanyName.Contains(arg); 
    } 
} 
+0

Wow, fajny Marc, nie wiedziałem o tym. Sprawdź moją odpowiedź poniżej ... jest przydatna, ale jest bardzo fajna. dzięki – andy

+0

Po prostu wyjaśnić, Marc. Jeśli używam drzewa wyrażeń, tak jak masz to tutaj, muszę użyć składni lambda, a nie składni zapytania? – jlembke

+0

Nice. Ok, będę z tym pracował. – jlembke

0

Nie używaj do tego składni zapytań.

var query = table.Where(x => SomeFunction(x)); 
+0

To nie pomoże w LINQ-SQL; nadal nie ma tłumaczenia dla 'SomeFunction'. –

+0

tak, nie ma różnicy między tym i składni zapytania – andy

+0

tak, to jest to samo .. – jlembke

1

Chciałbym po prostu złamać je tak:

Expression<Func<Table, bool>> someTreeThatReturnsBool = x => true; 

var query = from x in table where someTreeThatReturnsBool select x; 

Można było tworzyć funkcje, które przechodzą wokół drzew ekspresyjnych.

2

Zasadniczo, "po wyjęciu z pudełka", nie można wykonywać kwerend LINQ-SQL, które mają w nich niestandardowe funkcje. W rzeczywistości można użyć tylko niektórych natywnych metod, które można przetłumaczyć na SQL.

Najłatwiejszy sposób obejścia tego może niestety wpłynąć na wydajność w zależności od tego, ile danych zwracasz z DB.

Zasadniczo, można używać tylko funkcji niestandardowych w GDZIE statystyka, jeśli dane zostały już załadowane do pamięci, tj. SQL zostały już wykonane.

Najszybszy fix dla przykładu wyglądałby następująco:

var query = from x in table.ToList() where SomeFunctionReturnsBool() select; 

zauważy ToList(). Wykonuje SQL i umieszcza dane w pamięci. Możesz teraz robić, co chcesz, w instrukcji/metodzie WHERE.

+2

Prawda ... ale potem wycofujesz wszystkie rekordy, a następnie wykonujesz filtrowanie w pamięci a wykonujesz na serwerze bazy danych . – bytebender

+0

Uzgodnione (z J.13.L) - używanie 'ToList()' jest zwykle złym sposobem na zrobienie tego i działa tylko z małymi wolumenami danych. –

+0

Chciałbym uniknąć tego wszystkiego. Wiele danych. Dzięki Andy – jlembke