2009-09-02 14 views
29

Próbuję zrobić kwerendę jak tak ...składnia LINQ, gdzie wartość ciągu nie jest zerowy lub pusty

query.Where(x => !string.IsNullOrEmpty(x.PropertyName)); 

ale nie ...

więc teraz mam wdrożyła następujący, który działa ...

query.Where(x => (x.PropertyName ?? string.Empty) != string.Empty); 

czy istnieje lepszy (bardziej natywny?) sposób, w jaki LINQ to obsługuje?

EDIT

przeprosić! nie uwzględnił dostawcy ... Używa LINQ do SQL

+0

Jaki dostawca LINQ? SQL, Entity, Object, ...? –

+0

Zakładam, że Twój dostawca LINQ nie obsługuje String.IsNullOrEmpty() powodującego wyjątek NotSupportedException. –

+0

Czy możesz wyjaśnić, dlaczego zawodzi? Jakie wartości przechodzą przez to, czego się nie spodziewasz. Nie widzę niczego złego w tym konkretnym kodzie (lub co odróżniałoby go od drugiego przykładu). – JaredPar

Odpowiedz

37

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=367077

komunikat Problem
Jest możliwe, aby napisać LINQ to SQL, który pobiera wszystkie wiersze, które mają albo null lub pusty ciąg w danej dziedzinie, ale to nie jest możliwe użycie string.IsNullOrEmpty zrobić to, mimo że wiele innych metod łańcuchowych odwzorowuje LINQ na SQL. Proponowane rozwiązanie Pozwól string.IsNullOrEmpty w LINQ to SQL gdzie klauzuli tak, że te dwie kwerendy mają ten sam wynik:

var fieldNullOrEmpty = 
from item in db.SomeTable 
where item.SomeField == null || item.SomeField.Equals(string.Empty) 
select item; 

var fieldNullOrEmpty2 = 
from item in db.SomeTable 
where string.IsNullOrEmpty(item.SomeField) 
select item; 

Inne Reading:
1. DevArt
2. Dervalp.com
3.StackOverflow Post

2

To zadziała dobrze z Linq do Objects. Jednak niektórzy dostawcy LINQ mają trudności z uruchomieniem metod CLR w ramach zapytania. Jest to szczególnie ważne w przypadku niektórych dostawców baz danych.

Problem polega na tym, że dostawcy DB próbują przenieść i skompilować zapytanie LINQ jako zapytanie do bazy danych, aby zapobiec przeciąganiu wszystkich obiektów przez przewód. To dobrze, ale czasami ogranicza elastyczność w swoich predykatach.

Niestety, bez sprawdzania dokumentacji dostawcy, trudno jest zawsze dokładnie wiedzieć, co będzie lub nie będzie obsługiwane bezpośrednio u dostawcy. Wygląda na to, że Twój dostawca umożliwia porównania, ale nie sprawdza łańcucha. Sądzę, że w twoim przypadku jest to prawdopodobnie tak dobre podejście, jak tylko możesz. (To naprawdę nie różni się od sprawdzania IsNullOrEmpty, poza tworzeniem instancji "string.Empty" dla porównania, ale to jest niewielkie.)

14

To nie zawiedzie na Linq2Objects, ale nie powiedzie się dla Linq2SQL, więc Zakładam, że mówisz o dostawcy SQL lub czymś podobnym.

Przyczyna ma związek ze sposobem, w jaki dostawca SQL obsługuje wyrażenie lambda. Nie przyjmuje go jako funkcji Func<P,T>, ale wyrażenie Expression<Func<P,T>>. Pobiera to drzewo wyrażeń i tłumaczy je tak, aby była faktyczną instrukcją SQL, którą wysyła do serwera.

Translator wie, jak obsługiwać podstawowe operatory, ale nie wie, jak obsługiwać metody na obiektach. Nie wie, że IsNullOrEmpty(x) tłumaczy się na return x == null || x == string.empty. Trzeba to zrobić wyraźnie, aby umożliwić tłumaczenie na język SQL.

+1

Świetne wyjaśnienie - dzięki! –

Powiązane problemy