2011-06-29 8 views
6

Używam kombinacji LINQ i Dapper w mojej pracy. Zamieniam mój kod LINQ na Dapper w miejscach ze względu na wydajność. Mam wiele obiektów danych LINQ utworzonych przez przeciągnięcie i upuszczenie na diagram bazy danych Visual Studio z SQL Server.Wywoływane parametrycznie zapytania z automatycznie wygenerowanymi typami LINQ

W poniższym przykładzie już mam obiekt LINQ w pamięci i chciałbym przekazać go do Dapper jako parametry dla zapytania. Na przykład:

Animal animal = con.Query<Animal>(" select * " + 
     " from animal " + 
     " where animalid = @AnimalId " + 
     " and animaltype = @AnimalType ", 
     cagedAnimal).SingleOrDefault(); 

cagedAnimal zawiera właściwości publiczne AnimalId i AnimalType z elementami pobierającymi i ustawiającymi.

Jednak na wykonanie tego kodu pojawia się następujący błąd:

The type : SMDApp.Models.Animal is not supported by dapper

Poniższy kod działa:

Animal animal = con.Query<Animal>(" select * " + 
      " from animal " + 
      " where animalid = @AnimalId " + 
      " and animaltype = @AnimalType ", 
      new 
      { 
      AnimalId = cagedAnimal.AnimalId, 
      AnimalType = cagedAnimal.AnimalType 
      } 
      ).SingleOrDefault(); 

Byłoby bardziej wygodne dla mnie do korzystania z istniejącego obiektu szczególnie tam, gdzie Używam więcej niż jednej właściwości obiektu jako parametru dla zapytania. Czy ktokolwiek może mi powiedzieć, dlaczego działa to w przypadku anonimowego obiektu, ale nie jest generowanym automatycznie obiektem LINQ?

Edytowane w odpowiedzi na odpowiedź Bena Robinsona.

Edytowane po raz drugi w odpowiedzi na odpowiedź Marca Gravell.

+1

czy jesteś * pewien * robisz "" ... ", cagedAnimal)'? może zamiast tego robisz '" ... ", nowe {cagedAnimal})? w zasadzie - to powinno już działać, chociaż jest trochę marnotrawstwem, że dodatkowe parametry mogą być niepotrzebnie dodawane/ –

+1

tylko po to, aby poinformować cię, że właśnie wysłałem poprawkę, która: zignoruje wszelkie właściwości, które nie są używane w zapytaniu, i b: dać znacznie lepszy komunikat o błędzie, gdy * nie * ma problemy. Nie wdrożyłem w Nuget, ale z nowym kodem powyższy przykład powinien zadziałać dobrze –

+0

Czekamy na to! –

Odpowiedz

4

Krótka wersja to , która powinna już działać; na podstawie błędu:

The type : SMDApp.Models.CagedAnimal is not supported by dapper

wnioskuję, że albo jesteś rzeczywiście przechodzącej new {cagedAnimal} zamiast cagedAnimal, lub, twój CagedAnimal ma własność (? Parent, chyba), który sam jest CagedAnimal i która elegancki możliwe 'nie rozumiem. Obecne zachowanie polega na tym, że parametr jest dodawany dla każdej publicznej właściwości dostarczonego obiektu parametru - a jeśli nie może dowiedzieć się, jak wysłać dowolną z właściwości do bazy danych, to narzeka. Powinieneś odkryć, że proste POCO z wartościowymi członkami działa dobrze.

Jednak! Zauważ, że nigdy nie próbuje parsować twojego SQL - w szczególności nie sprawdza parametrów w podanym zapytaniu. W związku z tym zastosowanie metody POCO będzie oznaczać, że dodajesz niepotrzebne właściwości do zapytania.

Używamy elegancki obszernie, a my po prostu użyć podejście:

new { obj.Foo, obj.Bar, id, key = "something else" } 
+0

Dzięki Marc to wszystko. Błędnie odczytałem komunikat o błędzie. Doh! Wciąż masz jakąś poprawną odpowiedź. W tej chwili edytowałem komunikat o błędzie w pytaniu. Klasa CagedAnimal miała właściwość typu Animal, której Dapper nie rozumiał. –

+1

@Giles planujemy zmienić komunikat o błędzie, aby dodać nazwę właściwości (parametr), który się dławi - więc twoje pytanie doprowadziło do pozytywnej zmiany/wyniku; p –

+1

@Giles jesteśmy * również * omawiamy czy lub nie do wstępnego filtrowania właściwości, które wysyłamy na podstawie polecenia, tj. wysyłaj tylko "param.foo", jeśli widzimy w tekście polecenia '@ foo' lub': foo', co usunie "niepotrzebne parametry" wydanie –

3

Marc właśnie popełnił zmiany do fix for this issue w szczególności:

  1. Wykonujemy trywialny walidację przed wysłaniem próbując tłumaczyć właściwości do params. Na przykład Dapper nie będzie wysyłał żadnych parametrów do serwera w tym przypadku: cnn.Query ("select 1", new {bla = 1}) powoduje, że "bla" nie istnieje w łańcuchu. Sprawdzanie poprawności jest pomijane dla przechowywanych procedur.

  2. Błąd, który był dość zagadkowy, został naprawiony i znacznie poprawiony.

-

Wytworny wykorzystywane do wykonywania żadnego parsowanie podstawowej SQL, więc na przykład:

@"select * 
from animal 
where animalid = @AnimalId" 

zawiera pojedynczy param nazywa @AnimalId.

Otrzymuje skomplikowaną przyczynę, aby być w 100% poprawnym, musisz obsługiwać przypadki brzegowe EG: @AnimalId w ciągu znaków select '@AnimalId' -- @AnimalId \* @AnimalId *\? Regex robi się nieco trudnym, nie przemyślałem każdego przypadku skrajnego. Na przykład: Oracle przedrostuje swoje parametry za pomocą :, co komplikuje wszystko.

Ponieważ firma dapper nie wiedziała nic o parametrach w łańcuchu znaków, zdecydowała się wysłać jako własność publiczną każdą właściwość publiczną. Niektórych twoich właściwości publicznych nie można zmapować na DbParameters, więc narzeka.

Powiązane problemy