Szukaj…


Parametry

Parametr Detale
this cnn Połączenie podstawowe bazy danych - w this oznacza metodę rozszerzenia; połączenie nie musi być otwarte - jeśli nie jest otwarte, jest otwierane i zamykane automatycznie.
<T> / Type (opcjonalnie) Typ obiektu do zwrócenia; jeśli używany jest interfejs API inny niż ogólny / inny niż Type , obiekt dynamic jest zwracany na wiersz, symulując właściwość o nazwie na nazwę kolumny zwróconą z zapytania (ten obiekt dynamic również implementuje IDicionary<string,object> ).
sql SQL do wykonania
param (opcjonalnie) Parametry do uwzględnienia.
transaction (opcjonalnie) Transakcja bazy danych do skojarzenia z poleceniem
buffered (opcjonalnie) Określa, czy wstępnie zużyć dane na listę (domyślnie), a nie wyświetlać otwartą IEnumerable w czytniku na żywo
commandTimeout (opcjonalnie) Limit czasu do użycia w poleceniu; jeśli nie jest określony, SqlMapper.Settings.CommandTimeout (jeśli określono)
commandType Rodzaj wykonywanej komendy; domyślnie jest to CommandText

Uwagi

Składnia wyrażania parametrów różni się w zależności od RDBMS. Wszystkie powyższe przykłady używają składni SQL Server, tj. @foo ; Jednak ?foo i :foo powinny również działać poprawnie.

Podstawowy sparametryzowany SQL

Dapper ułatwia stosowanie najlepszych praktyk dzięki w pełni sparametryzowanemu SQL.

Stoły Bobby'ego

Parametry są ważne, więc eleganckie ułatwia prawidłowe ustawienie. Po prostu wyrażasz swoje parametry w normalny sposób dla swojego RDBMS (zwykle @foo ?foo lub :foo ) i nadajesz obiektowi, który ma element o nazwie foo . Najczęstszym sposobem na to jest anonimowy typ:

int id = 123;
string name = "abc";
connection.Execute("insert [KeyLookup](Id, Name) values(@id, @name)",
    new { id, name });

I to wszystko. Dapper doda wymagane parametry i wszystko powinno działać.

Korzystanie z modelu obiektowego

Możesz również użyć istniejącego modelu obiektowego jako parametru:

KeyLookup lookup = ... // some existing instance
connection.Execute("insert [KeyLookup](Id, Name) values(@Id, @Name)", lookup);

Dapper używa tekstu polecenia do określenia, którzy członkowie obiektu mają IsActive - zwykle nie dodaje niepotrzebnych rzeczy, takich jak Description , IsActive , CreationDate ponieważ wydane przez nas polecenie wyraźnie ich nie dotyczy - chociaż zdarzają się przypadki, gdy może to zrobić, na przykład jeśli twoje polecenie zawiera:

// TODO - removed for now; include the @Description in the insert

Nie próbuje dowiedzieć się, że powyższe to tylko komentarz.

Procedury przechowywane

Parametry procedur przechowywanych działają dokładnie tak samo, z tym, że elegancki nie może próbować określić, co powinno / nie powinno być uwzględnione - wszystko dostępne jest traktowane jako parametr. Z tego powodu zwykle preferowane są typy anonimowe:

connection.Execute("KeyLookupInsert", new { id, name },
    commandType: CommandType.StoredProcedure);

Inlining wartości

Czasami wygoda parametru (pod względem konserwacji i ekspresji) może być przeważona kosztem wydajności, aby traktować go jako parametr. Na przykład, gdy rozmiar strony jest ustalony przez ustawienie konfiguracji. Lub wartość statusu jest dopasowywana do wartości enum . Rozważać:

var orders = connection.Query<Order>(@"
select top (@count) * -- these brackets are an oddity of SQL Server
from Orders
where CustomerId = @customerId
and Status = @open", new { customerId, count = PageSize, open = OrderStatus.Open });

Jedynym prawdziwym parametrem jest tutaj identyfikator customerId - pozostałe dwa to pseudo-parametry, które tak naprawdę się nie zmienią. Często RDBMS może wykonać lepszą robotę, jeśli wykryje je jako stałe. Dapper ma do tego specjalną składnię - {=name} zamiast @name - która dotyczy tylko typów numerycznych. (Minimalizuje to wszelką powierzchnię ataku po wstrzyknięciu SQL). Przykład jest następujący:

var orders = connection.Query<Order>(@"
select top {=count} *
from Orders
where CustomerId = @customerId
and Status = {=open}", new { customerId, count = PageSize, open = OrderStatus.Open });

Dapper zastępuje wartości literałami przed wydaniem SQL, więc RDBMS faktycznie widzi coś takiego:

select top 10 *
from Orders
where CustomerId = @customerId
and Status = 3

Jest to szczególnie przydatne, gdy pozwala się systemom RDBMS nie tylko podejmować lepsze decyzje, ale także otwierać plany zapytań, którym zapobiegają rzeczywiste parametry. Na przykład, jeśli predykat kolumny jest zgodny z parametrem, wówczas nie można użyć filtrowanego indeksu z określonymi wartościami dla tych kolumn. Wynika to z faktu, że następne zapytanie może zawierać parametr oprócz jednej z tych określonych wartości.

Przy wartościach literalnych optymalizator zapytań może korzystać z filtrowanych indeksów, ponieważ wie, że wartość nie może się zmienić w przyszłych zapytaniach.

Rozszerzenia listy

Częstym scenariuszem w zapytaniach do baz danych jest IN (...) gdzie lista jest generowana w czasie wykonywania. Większość RDBMS nie ma na to dobrej metafory - i nie ma na to uniwersalnego rozwiązania między RDBMS . Zamiast tego program dapper zapewnia delikatne automatyczne rozszerzanie poleceń. Wszystko, czego wymaga to dostarczona wartość parametru, która jest IEnumerable . Polecenie obejmujące @foo jest rozwijane do (@foo0,@foo1,@foo2,@foo3) (dla sekwencji 4 elementów). Najczęstszym zastosowaniem tego byłoby IN :

int[] orderIds = ...
var orders = connection.Query<Order>(@"
select *
from Orders
where Id in @orderIds", new { orderIds });

Następnie automatycznie rozszerza się, aby wydać odpowiedni kod SQL dla pobierania wielu wierszy:

select *
from Orders
where Id in (@orderIds0, @orderIds1, @orderIds2, @orderIds3)

z parametrami @orderIds0 itd. dodawanymi jako wartości pobrane z tablicy. Zauważ, że fakt, że oryginalnie nie jest poprawnym SQL, jest celowy, aby upewnić się, że ta funkcja nie zostanie użyta błędnie. Ta funkcja działa również poprawnie z podpowiedzią OPTIMIZE FOR / UNKNOWN w programie SQL Server; Jeśli użyjesz:

option (optimize for
    (@orderIds unknown))

rozszerzy to poprawnie do:

option (optimize for
    (@orderIds0 unknown, @orderIds1 unknown, @orderIds2 unknown, @orderIds3 unknown))

Wykonywanie operacji na wielu zestawach danych wejściowych

Czasami chcesz zrobić to samo wiele razy. Dapper obsługuje to w metodzie Execute , jeśli najbardziej zewnętrzny parametr (który jest zwykle pojedynczym anonimowym typem lub instancją modelu domeny) jest faktycznie dostarczany jako sekwencja IEnumerable . Na przykład:

Order[] orders = ...
// update the totals
connection.Execute("update Orders set Total=@Total where Id=@Id", orders);

Tutaj dapper robi prostą pętlę na naszych danych, zasadniczo tak samo, jakbyśmy to zrobili:

Order[] orders = ...
// update the totals
foreach(Order order in orders) {
    connection.Execute("update Orders set Total=@Total where Id=@Id", order);
}

To użycie staje się szczególnie interesujące w połączeniu z async interfejsem API w połączeniu, które jest jawnie skonfigurowane dla wszystkich „wielu aktywnych zestawów wyników” - w tym zastosowaniu dapper automatycznie potokuje operacje, więc nie płacisz kosztu opóźnienia za wiersz. Wymaga to nieco bardziej skomplikowanego użycia,

await connection.ExecuteAsync(
    new CommandDefinition(
        "update Orders set Total=@Total where Id=@Id", 
         orders, flags: CommandFlags.Pipelined))

Pamiętaj jednak, że możesz również chcieć zbadać parametry wyceniane w tabeli.

Parametry pseudo-pozycyjne (dla dostawców, którzy nie obsługują nazwanych parametrów)

Niektórzy dostawcy ADO.NET (w szczególności: OleDB) nie obsługują nazwanych parametrów; zamiast tego parametry są określane tylko według pozycji za pomocą ? uchwyt na miejsce. Dapper nie wiedziałby, którego członka użyć, więc dapper pozwala na alternatywną składnię, ?foo? ; byłoby to to samo co @foo lub :foo w innych wariantach SQL, z tym że dapper całkowicie zastąpi token parametru ? przed wykonaniem zapytania.

Działa to w połączeniu z innymi funkcjami, takimi jak rozwijanie listy, więc obowiązuje:

string region = "North";
int[] users = ...
var docs = conn.Query<Document>(@"
     select * from Documents
     where Region = ?region?
     and OwnerId in ?users?", new { region, users }).AsList();

Członkowie .region i .users są odpowiednio używane, a wydany SQL to (na przykład dla 3 użytkowników):

     select * from Documents
     where Region = ?
     and OwnerId in (?,?,?)

Zauważ jednak, że dapper nie pozwala na wielokrotne użycie tego samego parametru podczas korzystania z tej funkcji; Zapobiega to wielokrotnemu dodawaniu tej samej wartości parametru (która może być duża). Jeśli chcesz wielokrotnie odwoływać się do tej samej wartości, rozważ zadeklarowanie zmiennej, na przykład:

declare @id int = ?id?; // now we can use @id multiple times in the SQL

Jeśli zmienne nie są dostępne, możesz użyć zduplikowanych nazw członków w parametrach - to również sprawi, że będzie oczywiste, że wartość jest wysyłana wiele razy:

int id = 42;
connection.Execute("... where ParentId = $id0$ ... SomethingElse = $id1$ ...",
      new { id0 = id, id1 = id });


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow