Suche…


Parameter

Parameter Einzelheiten
this cnn Die zugrunde liegende Datenbankverbindung - this bezeichnet eine Erweiterungsmethode; Die Verbindung muss nicht geöffnet sein - wenn sie nicht geöffnet ist, wird sie automatisch geöffnet und geschlossen.
<T> / Type (optional) Der Typ des zurückzugebenden Objekts. Wenn die nicht generische / nicht- Type API verwendet wird, wird pro Zeile ein dynamic Objekt zurückgegeben, das eine Eigenschaft simuliert, die pro Spaltennamen benannt wird, der von der Abfrage zurückgegeben wird (dieses dynamic Objekt implementiert auch IDicionary<string,object> ).
sql Die auszuführende SQL
param (optional) Die einzuschließenden Parameter.
transaction (optional) Die dem Befehl zuzuordnende Datenbanktransaktion
buffered (optional) Gibt an, ob die Daten in einer Liste vorab verbraucht werden sollen (Standardeinstellung), IEnumerable ein offenes IEnumerable über den Live-Reader IEnumerable machen
commandTimeout (optional) Die für den Befehl zu verwendende Zeitüberschreitung. Wenn nicht angegeben, wird SqlMapper.Settings.CommandTimeout angenommen (falls angegeben).
commandType Die Art des Befehls, der ausgeführt wird; Der Standardwert ist CommandText

Bemerkungen

Die Syntax zum Ausdrücken von Parametern variiert zwischen RDBMS. Alle obigen Beispiele verwenden die SQL Server-Syntax, dh @foo . Allerdings sollten ?foo und :foo auch gut funktionieren.

Basic Parametrisierte SQL

Dapper macht es einfach, Best Practices mithilfe von vollständig parametrisiertem SQL zu befolgen.

Bobby-Tische

Parameter sind wichtig, daher macht dapper es leicht, es richtig zu machen. Sie geben Ihre Parameter einfach wie üblich für Ihr RDBMS aus (normalerweise @foo ?foo oder :foo ) und geben dapper ein Objekt mit einem Member namens foo . Dies geschieht am häufigsten mit einem anonymen Typ:

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

Und das ist es. Dapper fügt die erforderlichen Parameter hinzu und alles sollte funktionieren.

Verwenden Sie Ihr Objektmodell

Sie können auch Ihr vorhandenes Objektmodell als Parameter verwenden:

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

Dapper verwendet den Befehlstext, um zu bestimmen, welche Member des Objekts hinzugefügt werden sollen. In der Regel werden keine unnötigen IsActive wie Description , IsActive oder CreationDate IsActive , da der von uns ausgegebene Befehl sie eindeutig nicht IsActive Dies könnte beispielsweise der Fall sein, wenn Ihr Befehl Folgendes enthält:

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

Es wird nicht versucht herauszufinden, dass das obige nur ein Kommentar ist.

Gespeicherte Prozeduren

Parameter für gespeicherte Prozeduren funktionieren genau gleich, mit der Ausnahme, dass dapper nicht feststellen kann, was nicht eingeschlossen werden soll / soll. Alle verfügbaren Daten werden als Parameter behandelt. Aus diesem Grund werden anonyme Typen normalerweise bevorzugt:

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

Wert Inlining

Manchmal kann die Bequemlichkeit eines Parameters (in Bezug auf die Wartung und Ausdruckskraft) durch seine Kosten in der Leistung aufgewogen werden, um ihn als Parameter zu behandeln. Zum Beispiel, wenn die Seitengröße durch eine Konfigurationseinstellung festgelegt wird. Oder ein Statuswert wird mit einem enum abgeglichen. Erwägen:

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 });

Der einzige echte Parameter hier ist customerId - die anderen beiden sind Pseudo-Parameter, die sich nicht wirklich ändern. Häufig kann das RDBMS eine bessere Arbeit leisten, wenn es diese als Konstanten erkennt. Dapper hat hierfür eine spezielle Syntax - {=name} anstelle von @name - die nur für numerische Typen gilt. (Dies minimiert jegliche Angriffsfläche durch SQL-Injection). Ein Beispiel ist wie folgt:

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

Dapper ersetzt Werte durch Literale, bevor SQL ausgegeben wird. Das RDBMS sieht also Folgendes:

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

Dies ist besonders nützlich, wenn RDBMS-Systeme nicht nur bessere Entscheidungen treffen, sondern auch Abfragepläne öffnen können, die durch tatsächliche Parameter verhindert werden. Wenn zum Beispiel ein Spaltenprädikat einen Parameter betrifft, kann ein gefilterter Index mit bestimmten Werten für diese Spalten nicht verwendet werden. Dies liegt daran, dass die nächste Abfrage einen Parameter außer einem dieser angegebenen Werte enthalten kann.

Mit Literalwerten kann das Abfrageoptimierungsprogramm die gefilterten Indizes verwenden, da es weiß, dass sich der Wert in zukünftigen Abfragen nicht ändern kann.

Erweiterungen auflisten

Ein häufiges Szenario in Datenbankabfragen ist IN (...) bei dem die Liste hier zur Laufzeit generiert wird. Den meisten RDBMS fehlt dafür eine gute Metapher - und dafür gibt es keine universelle Cross-RDBMS- Lösung. Stattdessen sorgt dapper für eine sanfte automatische Befehlserweiterung. Es ist IEnumerable ein angegebener Parameterwert erforderlich, der IEnumerable . Ein Befehl mit @foo wird zu (@foo0,@foo1,@foo2,@foo3) (für eine Sequenz von 4 Elementen). Die gebräuchlichste Verwendung davon wäre IN :

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

Dies wird dann automatisch erweitert, um die entsprechende SQL für den mehrzeiligen Abruf auszugeben:

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

Die Parameter @orderIds0 usw. werden als Werte aus dem Arrray hinzugefügt. Beachten Sie, dass die Tatsache, dass SQL ursprünglich nicht gültig ist, beabsichtigt ist, um sicherzustellen, dass diese Funktion nicht versehentlich verwendet wird. Diese Funktion funktioniert auch korrekt mit dem OPTIMIZE FOR / UNKNOWN in SQL Server. wenn du benutzt:

option (optimize for
    (@orderIds unknown))

es wird dies richtig erweitern auf:

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

Vorgänge gegen mehrere Eingabesätze ausführen

Manchmal möchten Sie dasselbe mehrmals tun. Dapper unterstützt dies für die Execute Methode, wenn der äußerste Parameter (normalerweise ein einzelner anonymer Typ oder eine Domänenmodellinstanz) tatsächlich als IEnumerable Sequenz IEnumerable wird. Zum Beispiel:

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

Hier führt dapper nur eine einfache Schleife mit unseren Daten durch, im Wesentlichen genauso, als ob wir dies getan hätten:

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

Diese Verwendung wird besonders interessant, wenn sie mit der async API für eine Verbindung kombiniert wird, die explizit für alle "Multiple Active Results Sets" konfiguriert ist. Bei dieser Verwendung leitet dapper die Operationen automatisch weiter, sodass Sie die Latenzkosten pro Zeile nicht bezahlen. Dies erfordert eine etwas kompliziertere Verwendung.

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

Beachten Sie jedoch, dass Sie möglicherweise auch Tabellenwertparameter untersuchen möchten.

Pseudopositionsparameter (für Anbieter, die benannte Parameter nicht unterstützen)

Einige ADO.NET-Anbieter (vor allem: OleDB) unterstützen benannte Parameter nicht. Parameter werden stattdessen nur nach Position angegeben , mit der ? Platzhalter. Dapper würde nicht wissen, welches Mitglied für diese verwendet werden soll, also erlaubt Dapper eine alternative Syntax, ?foo? ; dies würde das gleiche wie sein @foo oder :foo in anderen SQL - Varianten, außer dass adrett mit dem Parameter - Token vollständig ersetzen ? bevor Sie die Abfrage ausführen.

Dies funktioniert in Kombination mit anderen Funktionen wie der Listenerweiterung, daher gilt Folgendes:

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

Die Mitglieder .region und .users werden entsprechend verwendet, und die ausgegebene SQL lautet (z. B. mit 3 Benutzern):

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

Beachten Sie jedoch, dass sich adrett nicht der gleiche Parameter erlauben mehrfach verwendet werden , wenn diese Funktion verwendet wird ; Dies verhindert, dass derselbe Parameterwert (der groß sein kann) mehrmals hinzugefügt werden muss. Wenn Sie mehrmals auf denselben Wert verweisen müssen, sollten Sie eine Variable deklarieren. Beispiel:

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

Wenn keine Variablen verfügbar sind, können Sie doppelte Elementnamen in den Parametern verwenden. Dies macht auch deutlich, dass der Wert mehrmals gesendet wird:

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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow