Jestem nowy w Dapper micro ORM. Do tej pory mogę go używać do prostych rzeczy związanych z ORM, ale nie jestem w stanie zmapować nazw kolumn bazy danych z właściwościami klasy.
Na przykład mam następującą tabelę bazy danych:
Table Name: Person
person_id int
first_name varchar(50)
last_name varchar(50)
i mam klasę o nazwie Osoba:
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Zwróć uwagę, że nazwy moich kolumn w tabeli różnią się od nazwy właściwości klasy, do której próbuję zmapować dane, które otrzymałem z wyniku zapytania.
var sql = @"select top 1 PersonId,FirstName,LastName from Person";
using (var conn = ConnectionFactory.GetConnection())
{
var person = conn.Query<Person>(sql).ToList();
return person;
}
Powyższy kod nie zadziała, ponieważ nazwy kolumn nie są zgodne z właściwościami obiektu (Person). Czy w tym scenariuszu jest coś, co mogę zrobić w Dapper, aby ręcznie mapować (np. person_id => PersonId
) Nazwy kolumn z właściwościami obiektu?
Odpowiedzi:
To działa dobrze:
Dapper nie ma funkcji, która pozwala określić atrybut kolumny , nie jestem przeciwny dodawaniu jej obsługi, pod warunkiem, że nie pobieramy zależności.
źródło
Dapper obsługuje teraz niestandardowe kolumny do mapowania właściwości. Robi to za pośrednictwem interfejsu ITypeMap . CustomPropertyTypeMap klasa jest przez Dapper że można zrobić większość tej pracy. Na przykład:
A model:
Należy zauważyć, że implementacja CustomPropertyTypeMap wymaga, aby atrybut istniał i pasował do jednej z nazw kolumn, w przeciwnym razie właściwość nie zostanie zmapowana. DefaultTypeMap klasa zapewnia standardową funkcjonalność i może być użyta do zmiany tego zachowania:
Dzięki temu łatwo jest utworzyć niestandardowy program odwzorowujący typy, który automatycznie użyje atrybutów, jeśli są obecne, ale w przeciwnym razie powróci do standardowego zachowania:
Oznacza to, że możemy teraz łatwo obsługiwać typy, które wymagają mapowania przy użyciu atrybutów:
Oto streszczenie pełnego kodu źródłowego .
źródło
Przez jakiś czas powinny działać:
źródło
MatchNamesWithUnderscores
opcji. W najlepszym przypadku, gdybyśmy zmienili konfigurację API, zostawiłbymMatchNamesWithUnderscores
członka na miejscu (to nadal działa, idealnie) i dodałbym[Obsolete]
znacznik, aby wskazać ludziom nowe API.Oto proste rozwiązanie, które nie wymaga atrybutów, które pozwalają utrzymać kod infrastruktury z dala od POCO.
To jest klasa do obsługi mapowań. Słownik działałby, gdybyś zmapował wszystkie kolumny, ale ta klasa umożliwia określenie tylko różnic. Ponadto zawiera odwrócone mapy, dzięki czemu można pobrać pole z kolumny i kolumnę z pola, co może być przydatne podczas wykonywania takich czynności, jak generowanie instrukcji sql.
Skonfiguruj obiekt ColumnMap i powiedz Dapperowi, aby użył mapowania.
źródło
Wykonuję następujące czynności przy użyciu dynamicznego i LINQ:
źródło
Prostym sposobem osiągnięcia tego jest użycie aliasów w kolumnach w zapytaniu. Jeśli twoja kolumna bazy danych jest
PERSON_ID
i obiekt ma właściwośćID
, możesz po prostu wykonaćselect PERSON_ID as Id ...
zapytanie, a Dapper odbierze go zgodnie z oczekiwaniami.źródło
Zaczerpnięte z Dapper Tests, które są obecnie na Dapper 1.42.
Klasa pomocnicza, aby uzyskać nazwę z atrybutu Description (osobiście użyłem kolumny jak przykład @kalebs)
Klasa
źródło
GetDescriptionFromAttribute
doreturn (attrib?.Description ?? member.Name).ToLower();
i dodałem.ToLower()
docolumnName
na mapie, aby nie uwzględniać wielkości liter.Zamieszanie z mapowaniem to graniczne przejście do prawdziwej krainy ORM. Zamiast walczyć z nim i utrzymywać Dapper w jego prawdziwej prostej (szybkiej) formie, po prostu zmodyfikuj swój SQL w taki sposób:
źródło
Zanim otworzysz połączenie z bazą danych, wykonaj ten fragment kodu dla każdej z klas poco:
Następnie dodaj adnotacje danych do swoich klas poco w następujący sposób:
Potem wszystko jest gotowe. Po prostu wykonaj zapytanie, na przykład:
źródło
Jeśli używasz .NET 4.5.1 lub nowszego, wyewidencjonuj Dapper.FluentColumnMapping do mapowania stylu LINQ. Pozwala w pełni oddzielić mapowanie db od modelu (bez adnotacji)
źródło
To jest świnka wycofująca się z innych odpowiedzi. To tylko myśl, którą miałem do zarządzania ciągami zapytań.
Person.cs
Metoda API
źródło
dla wszystkich, którzy używają Dapper 1.12, oto, co musisz zrobić, aby to zrobić:
i skomentuj to.
źródło
Rozwiązanie Kaleba Pedersona zadziałało dla mnie. Zaktualizowałem ColumnAttributeTypeMapper, aby zezwolić na niestandardowy atrybut (wymagał dwóch różnych mapowań w tym samym obiekcie domeny) i zaktualizowałem właściwości, aby umożliwić ustawianie prywatne w przypadkach, gdy trzeba było wyprowadzić pole, a typy różniły się.
źródło
Wiem, że to stosunkowo stary wątek, ale pomyślałem, że wyrzucę tam to, co zrobiłem.
Chciałem, aby mapowanie atrybutów działało globalnie. Albo dopasujesz nazwę właściwości (aka domyślną), albo dopasujesz atrybut kolumny do właściwości klasy. Nie chciałem też konfigurować tego dla każdej klasy, do której mapowałem. W związku z tym utworzyłem klasę DapperStart, którą wywołuję przy starcie aplikacji:
Dość proste. Nie jestem pewien, jakie problemy napotkam, gdy właśnie to napisałem, ale działa.
źródło
CreateChatRequestResponse
zostanie zastąpione przez to, wT
jaki sposób iteruje przez wszystkie obiekty Entity. Proszę, popraw mnie jeśli się mylę.Prostym rozwiązaniem problemu, który Kaleb próbuje rozwiązać, jest po prostu zaakceptowanie nazwy właściwości, jeśli atrybut kolumny nie istnieje:
źródło