2009-11-09 6 views
5
public static void MyFunction(MyErrorClass err) 
{ 
    var query = from filter in DataContext.ErrorFilters select filter; 
    query = query.Where(f => err.ErrorMessage.Contains(f.ErrorMessage)); 
    List<ErrorFilter> filters = query.ToList(); 
    //...more code 
} 

Występują problemy z powyższym kodem i otrzymuję błąd z wiersza tematu na linia z query.ToList(). Oto, co próbuję zrobić:"Tylko argumenty, które można ocenić na kliencie, są obsługiwane dla metody String.Contains"

Po pierwsze, mam niestandardową klasę błędów, MyErrorClass. Ilekroć wystąpi błąd w mojej witrynie, tworzę obiekt MyErrorClass z wyjątku, przechowuję wszystkie dane z wyjątku w tym obiekcie i zapisuję informacje w bazie danych.

Jedną z właściwości wyjątków, które śledzę, jest komunikat o błędzie (ErrorMessage). Mam bazę danych ErrorFilters skonfigurowaną w bazie danych, w której użytkownik może filtrować błędy na podstawie numeru ErrorMessage. Powiedzmy, że otrzymujesz mnóstwo błędów, które mówią: "System.Data.SqlClient.SqlException: Limit czasu minął, czas oczekiwania upłynął przed zakończeniem operacji lub serwer nie odpowiada.", I chcesz je zignorować. Po prostu dodajesz filtr do bazy danych z komunikatem ErrorMessage jako "timeout expired" i ustawiasz go na ignorowanie.

Teraz moja klasa powyżej jest ustawiona na błąd i decyduje, czy błąd powinien być filtrowany. Próbuję uzyskać listę wszystkich filtrów, które mają ErrorMessage pasujące do tego błędu.

Jestem pewien, że to łatwa łatka, po prostu nie wiem, jak to naprawić.

+0

Ta metoda powraca nieważne, co ma zrobić? Jeśli ma sprawdzić, czy błąd ma zostać wyświetlony, powinien zwrócić wartość boolean i znaleźć poprawkę. W innym przypadku, wyjaśnij nieco to pytanie. –

+1

Funkcja wykonuje wiele innych rzeczy, które nie są związane z błędem, wszystkie te trzy linie, w których próbuję uzyskać listę filtrów, które pasują do błędu. Wyjaśniłem wszystko, co musisz wiedzieć, o co jeszcze się zastanawiasz? –

Odpowiedz

0

Wygląda na to, że powinieneś używać f.ErrorMessage.Contains(err.ErrorMessage) - linq do sql powinien następnie przekonwertować to na WHERE ErrorFilter.ErrorMessage LIKE %err.ErrorMessage%. Problem w sposobie, w jaki je posiadasz, polega na tym, że wygenerowany kod SQL musiałby zawierać ciąg dynamiczny zgodny z klauzulą ​​where, a zatem mógł być filtrowany tylko na kliencie.

Incidently linia var query = from filter in DataContext.ErrorFilters select filter; nie jest wymagana i można po prostu zrobić:

var filters = DataContext.ErrorFilters.Where(f => f.ErrorMessage.Contains(err.ErrorMessage)).ToList();

EDIT:

Ok widzę, co próbujesz zrobić teraz, ale nie jestem na pewno, jeśli jest to możliwe w linq2sql. Można utworzyć procedurę przechowywaną i dodać, że do datacontext i zrobić mapowanie z wyjścia do sekwencji obiektów ErrorFilter:

create procedure GetMatchingFilters @message varchar(500) 
as 
begin 
    select * 
    from ErrorFilter 
    where @message LIKE '%'+ErrorMessage+'%' 
end 

Następnie w datacontext można zrobić:

DataContext 
    .GetMatchingFilters(err.ErrorMessage) 
    .Select(result => new ErrorFilter {...}) 
    .ToList(); 
+0

Problem polega na tym, że bardzo trudno byłoby odfiltrować na podstawie komunikatu ErrorMessage. ErrorMessage jest zwykle bardzo długi i powinieneś być w stanie stworzyć filtr, wpisując "timeout expired". Korzystając z tej metody, użytkownik musiałby mieć komunikat o błędzie dotyczący filtra dokładnie taki sam jak komunikat o błędzie błędu. –

+0

Nie, powinno działać tak, jak opisałeś, zapytanie będzie takie jak SELECT * FROM ErrorFilters WHERE ErrorMessage LIKE% someString%. Chyba że źle zrozumiałem problem ... – Lee

+0

Odwróć 'f.ErrorMessage.Contains (err.ErrorMessage))' na 'err.ErrorMessage.Contains (f.ErrorMessage))' –

4

Hmm. .. Wygląda na to, że tłumaczenie Linq2SQL IndexOf jest mądrzejsze niż w przypadku Contains. To powinno działać:

public static void MyFunction(MyErrorClass err) 
{ 
    var query = DataContext.ErrorFilters; 
    query = query.Where(f => err.ErrorMessage.IndexOf(f.ErrorMessage)>=0); 
    List<ErrorFilter> filters = query.ToList(); 
    //...more code 
} 

W LINQPad widać ten wykorzystuje CHARINDEX, ponieważ mamy prosić o więcej, niż tylko „zawiera”, a „gdzie to jest”, ale chętnie do pracy z server- wyrazy poboczne.

+1

To jest czysty blask. Ludzie szukają rozwiązania tego od lat !! . Wybierz (x => "text1 | text2 | text3" .IndexOf (x.column)> = 0) – benpage

+0

@benpage W obronie społeczności, po opublikowaniu tej odpowiedzi zauważyłem [other] (http: // stackoverflow. com/a/19791382/256431) [miejsca] (http://stackoverflow.com/a/7574433/256431) na SO, które już wspomniało tę koncepcję lata temu. –

Powiązane problemy