Dapper multi insert renvoyant des objets insérés

dapper sql sql-insert

Question

En utilisant Dapper, je voudrais implémenter une méthode qui prend un IEnumberable d'objets de type User . Maintenant, l' User ressemble à ceci:

public class User
{
  public int UserId { get; internal set; }
  public DateTime DateCreated { get; internal set; }
  public DateTime DateChanged { get; internal set; }
  public string Username { get; set; }
}

Le point ici est que UserId , DateCreated et DateChanged ne doivent jamais être définis via un objet, donc le mot-clé internal . Au lieu de cela, la base de données remplira ces valeurs.

Les objets étant donc modifiés dans le cadre de l'opération d'insertion, je souhaite renvoyer un autre objet IEnumerable d'objets de type User mais cette fois avec les propriétés correspondantes renseignées.

Récemment, j'ai réalisé que je pouvais laisser Dapper en boucle à travers les objets User de l' IEnumerable comme suit:

public int Insert(IEnumerable<User> users)
{
  string sql = string.Format("INSERT INTO [User] (Username) VALUES (@Username)");
  return GetOpenConnection().Execute<User>(sql, users);
}

C'est sympa parce que je n'ai pas besoin d'écrire moi-même le foreach . Maintenant, le problème est que Execute ne retournera que le nombre de lignes réellement insérées.

Je l'ai donc essayé en utilisant Query comme suit:

public IEnumerable<User> Insert(IEnumerable<User> users)
{
  string sql = string.Format("INSERT INTO [User] (Username) VALUES (@Username) SELECT * FROM [User] WHERE UserId = scope_identity()");
  return GetOpenConnection().Query<User>(sql, users);
}

Cependant, cela génère simplement une exception InvalidOperationException avec le message "Une séquence énumérable de paramètres (tableaux, listes, etc.) n'est pas autorisée dans ce contexte".

Je suis coincé avec ça. Comment puis-je faire ce travail?

Dois-je parcourir mon entrée IEnumerable exécutant Query pour chaque objet à l'intérieur du corps de la boucle? De cette façon, le paramètre IDbTransaction de la méthode Query serait inutile si je souhaitais insérer tous User objets User dans la même transaction. Je devrais donc envelopper toute la boucle dans une transaction au lieu de transmettre la transaction à Query .

Quelle est la manière "appropriée" d'insérer plusieurs objets à l'aide de Dapper et de renvoyer les objets entièrement remplis à l'appelant?

Réponse acceptée

insérer ou mettre à jour la liste d'objets avec Dapper.Net vous ne pouvez pas utiliser la requête

 connection.Query<Object>("your_query",your_list) 
 //connection.Query<Object>: use to select IEnumrable<object> from db
 //connection.QueryMultiple: use to execut multiple query at once then read result one by one 

var sql = 
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";

using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
  var customer = multi.Read<Customer>().Single();
  var orders = multi.Read<Order>().ToList();
  var returns = multi.Read<Return>().ToList();
   ...
} 

vous devez utiliser uniquement Execute for multi insert ou update

Execute("your_query",your_list, your_transaction);

donc si vous avez besoin d'insérer et de retourner des identifiants pour les enregistrements insérés

// **using transaction depend on your needs**

// Exemple d'insertion multiple et de retour de l'enregistrement complet

  string query = @"Insert Into _TableName ( _columns) 
                                  OUTPUT INSERTED.* 
                                values ( _parameters )"; //parameters should be same as object properties name to let dapper do correct mapping 

[OUTPUT INSERTED. *] Retournera la ligne d'insertion complète avec id et vous êtes libre de retourner n'importe quelle propriété en remplaçant l'astérisque par propertyname [OUTPUT INSERTED.Id] ne retournera que l'identifiant

// sera bon pour une petite liste

 for (int i = 0; i < youList.Count-1; i++)
                {
                    youList[i] = DbConnection.Query<object>(query, youList[i]).FirstOrDefault();
                } // for loop is better for preformance

// pour Big List, vous pouvez utiliser SqlBulkCopy pour lire ce lien ici




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi