2011-11-26 6 views
5

Jestem całkiem nowy w LINQ i nie mogę pogodzić się z pewną niekonsekwencją w zachowaniu. Każdy cenny wkład byłby bardzo doceniany. Widzę podobne problemy na SO i gdzie indziej, ale wydaje się, że nie pomagają.LINQ - "Nie można przetłumaczyć wyrażenia" z poprzednio używanym i sprawdzonym warunkiem zapytania

Mam bardzo prostą konfigurację - tabelę firmową i tabelę adresów. Każda firma może mieć 0 lub więcej adresów, a jeśli> 0 należy podać adres główny. Próbuję obsłużyć przypadki, w których jest 0 adresów, używając zewnętrznego sprzężenia i zmieniając odpowiednio instrukcję select.

Uwaga: Aktualnie wiążę dane wyjściowe bezpośrednio z GridView, więc chciałbym zachować wszystkie przetwarzanie w zapytaniu.

Poniższy CZY pracy

IQueryable query = 
    from comp in context.Companies 
    join addr in context.Addresses on comp.CompanyID equals addr.CompanyID into outer // outer join companies to addresses table to include companies with no address 
    from addr in outer.DefaultIfEmpty() 
    where (addr.IsMain == null ? true : addr.IsMain) == true // if a company has no address ensure it is not ruled out by the IsMain condition - default to true if null 
    select new { 
     comp.CompanyID, 
     comp.Name, 
     AddressID = (addr.AddressID == null ? -1 : addr.AddressID), // use -1 to represent a company that has no addresses 
     MainAddress = String.Format("{0}, {1}, {2} {3} ({4})", addr.Address1, addr.City, addr.Region, addr.PostalCode, addr.Country) 
    }; 

ale ten wyświetla pusty adres w GridView jako ", ,()"

Więc aktualizowane pole MainAddress być

MainAddress = (addr.AddressID == null ? "" : String.Format("{0}, {1}, {2} {3} ({4})", addr.Address1, addr.City, addr.Region, addr.PostalCode, addr.Country)) 

i teraz otrzymuję błąd Could not translate expression i kilka automatycznie wygenerowanych kodów spewey w pliku erro r co oznacza dla mnie bardzo mało.

Warunek dodany do MainAddress nie różni się od warunków pracy na AddressID, więc czy ktoś może mi powiedzieć, co się tutaj dzieje?

Każda pomoc bardzo ceniona.

+2

może chcieć dodać "spewey automatycznie wygenerowany kod" na pytanie. – Bert

Odpowiedz

6

Błąd, który otrzymujesz, mówi ci, że LinqToSql nie może przetłumaczyć Twojego zerowego czeku, a następnie napisać wyrażenie.Format na SQL. Jeśli spojrzeć na SQL Twoja pierwsza zapytania generującego (przy użyciu LINQPad lub SQL Profiler), zobaczysz coś takiego:

SELECT [t0].[CompanyID], [t0].[Name], 
    (CASE 
     WHEN [t1].[AddressID] IS NULL THEN @p0 
     ELSE [t1].[AddressID] 
    END) AS [AddressID], 
    [t1].[Address1] AS [value], 
    [t1].[City] AS [value2], 
    [t1].[Region] AS [value3], 
    [t1].[PostalCode] AS [value4], 
    [t1].[Country] AS [value5] 
FROM [Company] AS [t0] 
LEFT OUTER JOIN [Address] AS [t1] ON [t0].[CompanyID] = [t1].[CompanyID] 
WHERE ([t1].[IsMain] IS NULL) OR ([t1].[IsMain] = 1) 

Dla danej dziedzinie AddressID, widać, że używa CASE-WHEN do obsługi warunek, gdy AddressID ma wartość null. Kiedy dodajesz CASE-WHEN dla MainAddress, to próbuje zrobić to samo dla tego pola, ale nie ma odpowiednika SQL dla string.Format, którego może użyć w odniesieniu do klauzuli ELSE, więc ulega awarii.

Łatwym sposobem obejścia tego problemu jest użycie metody formatowania ciągu znaków. Wywołując metodę prywatną, LinqToSql nie będzie próbował przetłumaczyć string.Format na SQL, a zamiast tego zwróci wszystkie pola niezbędne do wypełnienia obiektu Address. Metoda może następnie zająć się formatowaniem.

Na przykład:

LINQ:

.... 
select new { 
    comp.CompanyID, 
    comp.Name, 
    AddressID = (addr.AddressID == null ? -1 : addr.AddressID), 
    MainAddress = FormatAddress(addr) 
}; 

Metoda:

private static string FormatAddress(Address addr) 
{ 
    return (addr == null ? "" : 
      string.Format("{0}, {1}, {2} {3} ({4})", 
         addr.Address1, addr.City, 
         addr.Region, addr.PostalCode, addr.Country)); 
} 
+0

Niesamowite dzięki za pomoc i wyjaśnienie. Nie zdawałem sobie sprawy z tego, które części LINQ spróbują przekazać do bazy danych. Przez cały czas uczę się więcej o tych szalonych rzeczach ... – tomfumb

+0

Fajnie, cieszę się, że mogę pomóc. – rsbarro

Powiązane problemy