Recherche…


Paramètres

Paramètre Détails
this cnn La connexion à la base de données sous-jacente - this indique une méthode d’extension; la connexion n'a pas besoin d'être ouverte - si elle n'est pas ouverte, elle est ouverte et fermée automatiquement.
<T> / Type (facultatif) Type d'objet à renvoyer; Si l'API non-générique / non- Type est utilisée, un objet dynamic est renvoyé par ligne, simulant une propriété nommée par nom de colonne renvoyée par la requête (cet objet dynamic implémente également IDicionary<string,object> ).
sql Le SQL à exécuter
param (facultatif) Les paramètres à inclure.
transaction (facultatif) La transaction de base de données à associer à la commande
buffered (facultatif) Indique s'il faut pré-consommer les données dans une liste (valeur par défaut) plutôt que d'exposer un IEnumerable ouvert sur le lecteur actif
commandTimeout (facultatif) Le délai à utiliser sur la commande; SqlMapper.Settings.CommandTimeout n’est pas spécifié, SqlMapper.Settings.CommandTimeout est supposé (si spécifié)
commandType Le type de commande en cours d'exécution; par défaut à CommandText

Remarques

La syntaxe pour exprimer les paramètres varie entre les SGBDR. Tous les exemples ci-dessus utilisent la syntaxe SQL Server, à savoir @foo ; Cependant ?foo et :foo devraient également fonctionner correctement.

SQL paramétré de base

Dapper facilite le suivi des meilleures pratiques grâce à un SQL entièrement paramétré.

Tables Bobby

Les paramètres sont importants, donc dapper facilite la tâche. Vous venez d'exprimer vos paramètres de la manière habituelle pour votre SGBDR (généralement @foo ?foo ou :foo ) et donnez à dapper un objet qui a un membre appelé foo . La méthode la plus courante consiste à utiliser un type anonyme:

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

Et c'est tout. Dapper ajoutera les paramètres requis et tout devrait fonctionner.

Utiliser votre modèle d'objet

Vous pouvez également utiliser votre modèle d'objet existant en tant que paramètre:

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

Dapper utilise le texte de commande pour déterminer les membres de l'objet à ajouter - il n'ajoutera généralement pas de choses inutiles telles que Description , IsActive , CreationDate car la commande que nous avons publiée ne les implique pas - bien qu'il y ait des cas où pourrait le faire, par exemple si votre commande contient:

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

Il ne tente pas de comprendre que ce qui précède n'est qu'un commentaire.

Procédures stockées

Les paramètres des procédures stockées fonctionnent exactement de la même manière, sauf que Dapper ne peut pas tenter de déterminer ce qui doit / ne doit pas être inclus - tout ce qui est disponible est traité comme un paramètre. Pour cette raison, les types anonymes sont généralement préférés:

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

Valeur Inlining

Parfois, la commodité d'un paramètre (en termes de maintenance et d'expressivité) peut être compensée par son coût en termes de performances pour le traiter en tant que paramètre. Par exemple, lorsque la taille de la page est fixée par un paramètre de configuration. Ou une valeur de statut correspond à une valeur enum . Considérer:

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

Le seul paramètre réel ici est customerId - les deux autres sont des pseudo-paramètres qui ne changeront pas réellement. Souvent, le SGBDR peut faire un meilleur travail s'il les détecte comme des constantes. Dapper a une syntaxe spéciale pour ceci - {=name} au lieu de @name - qui ne s'applique qu'aux types numériques. (Cela minimise toute surface d'attaque de l'injection SQL). Voici un exemple:

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

Dapper remplace les valeurs par des littéraux avant d’émettre le code SQL. Le SGBDR voit donc quelque chose comme:

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

Ceci est particulièrement utile lorsque vous autorisez les systèmes SGBDR non seulement à prendre de meilleures décisions, mais aussi à ouvrir des plans de requête que les paramètres réels empêchent. Par exemple, si un prédicat de colonne est associé à un paramètre, un index filtré avec des valeurs spécifiques sur ces colonnes ne peut pas être utilisé. Cela est dû au fait que la requête suivante peut avoir un paramètre différent de l'une de ces valeurs spécifiées.

Avec des valeurs littérales, l'optimiseur de requête peut utiliser les index filtrés car il sait que la valeur ne peut pas être modifiée dans les requêtes futures.

Extensions de liste

Un scénario courant dans les requêtes de base de données est IN (...) où la liste est générée au moment de l'exécution. La plupart des SGBDR ne possèdent pas une bonne métaphore pour cela - et il n’existe pas de solution universelle de RDBMS pour cela. Au lieu de cela, Dapper fournit une extension automatique des commandes en douceur. Tout ce qui est nécessaire est une valeur de paramètre fournie qui est IEnumerable . Une commande impliquant @foo est étendue à (@foo0,@foo1,@foo2,@foo3) (pour une séquence de 4 éléments). L'utilisation la plus courante serait IN :

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

Cela se développe ensuite automatiquement pour émettre le code SQL approprié pour l'extraction à plusieurs lignes:

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

les paramètres @orderIds0 etc. étant ajoutés en tant que valeurs extraites de l'array. Notez que le fait qu'il ne soit pas valide à l'origine est intentionnel, pour garantir que cette fonctionnalité n'est pas utilisée par erreur. Cette fonctionnalité fonctionne également correctement avec l'indicateur de requête OPTIMIZE FOR / UNKNOWN dans SQL Server; si tu utilises:

option (optimize for
    (@orderIds unknown))

il étendra ceci correctement à:

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

Effectuer des opérations contre plusieurs ensembles d'entrées

Parfois, vous voulez faire la même chose plusieurs fois. Dapper prend cela en charge sur la méthode Execute si le paramètre le plus à l' extérieur (qui est généralement un seul type anonyme ou une instance de modèle de domaine) est réellement fourni sous la forme d'une séquence IEnumerable . Par exemple:

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

Ici, dapper ne fait qu'une simple boucle sur nos données, essentiellement comme si nous l'avions fait:

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

Cette utilisation devient particulièrement intéressante lorsqu'elle est associée à l'API async sur une connexion explicitement configurée pour tous les "multiples ensembles de résultats actifs". Dans cette utilisation, dapper va automatiquement canaliser les opérations, vous ne payez donc pas le coût de latence par ligne. Cela nécessite une utilisation légèrement plus compliquée,

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

Notez, cependant, que vous pourriez également vouloir examiner des paramètres de valeur de table.

Paramètres pseudo-positionnels (pour les fournisseurs qui ne prennent pas en charge les paramètres nommés)

Certains fournisseurs ADO.NET (notamment: OleDB) ne prennent pas en charge les paramètres nommés ; les paramètres sont plutôt spécifiés uniquement par la position , avec le ? placeplace. Dapper ne saurait pas quel membre utiliser, Dapper permet donc une syntaxe alternative, ?foo? ; ce serait la même chose que @foo ou :foo dans d'autres variantes SQL, sauf que dapper remplacera complètement le jeton de paramètre par ? avant d'exécuter la requête.

Cela fonctionne en combinaison avec d'autres fonctionnalités telles que l'extension de la liste, de sorte que ce qui suit est valide:

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

Les membres .region et .users sont utilisés en conséquence et le .users SQL émis est (par exemple, avec 3 utilisateurs):

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

Notez cependant que dapper ne permet pas d' utiliser le même paramètre plusieurs fois lors de l'utilisation de cette fonctionnalité. Cela permet d'éviter d'avoir à ajouter plusieurs fois la même valeur de paramètre (qui pourrait être importante). Si vous devez vous référer à la même valeur plusieurs fois, envisagez de déclarer une variable, par exemple:

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

Si des variables ne sont pas disponibles, vous pouvez utiliser des noms de membres en double dans les paramètres - cela rendra également évident que la valeur est envoyée plusieurs fois:

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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow