Comment insérer un IEnumerable <T> collection avec dapper-dot-net

c# dapper insert vb.net

Question

Oui, il y a des questions ici et ici sur la façon d'insérer des enregistrements avec dapper-dot-net. Cependant, les réponses, bien qu’informatives, ne semblaient pas me diriger dans la bonne direction. Voici la situation: déplacer des données de SqlServer vers MySql. La lecture des enregistrements dans un IEnumerable<WTUser> est facile, mais je ne reçois que quelque chose sur l'insert. Tout d'abord, le «code des enregistrements mobiles»:

//  moving data
Dim session As New Session(DataProvider.MSSql, "server", _
                           "database")

Dim resources As List(Of WTUser) = session.QueryReader(Of WTUser)("select * from tbl_resource")


session = New Session(DataProvider.MySql, "server", "database", _
                      "user", "p@$$w0rd")

//    *edit* - corrected parameter notation with '@'
Dim strInsert = "INSERT INTO tbl_resource (ResourceName, ResourceRate, ResourceTypeID, ActiveYN) " & _
                "VALUES (@ResourceName, @ResourceRate, @ResourceType, @ActiveYN)"

Dim recordCount = session.WriteData(Of WTUser)(strInsert, resources)

//  session Methods
    Public Function QueryReader(Of TEntity As {Class, New})(ByVal Command As String) _
                                                            As IEnumerable(Of TEntity)
        Dim list As IEnumerable(Of TEntity)

        Dim cnn As IDbConnection = dataAgent.NewConnection
        list = cnn.Query(Of TEntity)(Command, Nothing, Nothing, True, 0, CommandType.Text).ToList()

        Return list
    End Function

    Public Function WriteData(Of TEntity As {Class, New})(ByVal Command As String, ByVal Entities As IEnumerable(Of TEntity)) _
                                                          As Integer
        Dim cnn As IDbConnection = dataAgent.NewConnection

        //    *edit* if I do this I get the correct properties, but no data inserted
        //Return cnn.Execute(Command, New TEntity(), Nothing, 15, CommandType.Text)

        //    original Return statement
        Return cnn.Execute(Command, Entities, Nothing, 15, CommandType.Text)
    End Function

cnn.Query et cnn.Execute appellent les méthodes d'extension dapper. Maintenant, la classe WTUser (note: le nom de la colonne est passé de «WindowsName» dans SqlServer à «ResourceName» dans MySql, donc les deux propriétés pointant vers le même champ):

Public Class WTUser
    //    edited for brevity - assume the following all have public get/set methods
    Public ActiveYN As String
    Public ResourceID As Integer
    Public ResourceRate As Integer
    Public ResourceType As Integer
    Public WindowsName As String
    Public ResourceName As String

End Class

Je reçois une exception de dapper: "Wapper n'est pas pris en charge par Dapper." Cette méthode dans DataMapper (dapper):

    private static Action<IDbCommand, object> CreateParamInfoGenerator(Type OwnerType)
    {
        string dmName = string.Format("ParamInfo{0}", Guid.NewGuid());
        Type[] objTypes = new[] { typeof(IDbCommand), typeof(object) };

        var dm = new DynamicMethod(dmName, null, objTypes, OwnerType, true); // << - here
        //    emit stuff

        //    dm is instanced, now ...
        foreach (var prop in OwnerType.GetProperties().OrderBy(p => p.Name))

À ce stade, OwnerType =

System.Collections.Generic.List`1 [[CRMBackEnd.WTUser, CRMBE, version = 1.0.0.0, Culture = neutre, PublicKeyToken = null]], mscorlib, version = 2.0.0.0, Culture = neutre, PublicKeyToken = b77a5c561934e089

Il semble que OwnerType devrait être CRMBackEnd.WTUser ... pas List<CRMBackEnd.WTUser> ... ??? car ce qui se passe, c'est que les propriétés de la collection sont itérées: nombre, capacité, etc. Que me manque-t-il?

Mettre à jour

Si j'ai modifié session.WriteData en tant que:

Public Function WriteData(Of TEntity As {Class, New})(ByVal Command As String, _
                                                      ByVal Entities As IEnumerable(Of TEntity)) _
                                                      As Integer
    Dim cnn As IDbConnection = dataAgent.NewConnection
    Dim records As Integer

    For Each entity As TEntity In Entities
        records += cnn.Execute(Command, entity, Nothing, 15, CommandType.Text)
    Next

    Return records
End Function

les enregistrements sont bien insérés ... mais je ne pensais pas que cela serait nécessaire étant donné des exemples comme:

connection.Execute(@"insert MyTable(colA, colB) values (@a, @b)",
    new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }
  ).IsEqualTo(3); // 3 rows inserted: "1,1", "2,2" and "3,3"  

... de dapper-dot-net

Réponse acceptée

Je viens d'ajouter un test pour ceci:

class Student
{
    public string Name {get; set;}
    public int Age { get; set; }
}

public void TestExecuteMultipleCommandStrongType()
{
    connection.Execute("create table #t(Name nvarchar(max), Age int)");
    int tally = connection.Execute(@"insert #t (Name,Age) values(@Name, @Age)", new List<Student> 
    {
        new Student{Age = 1, Name = "sam"},
        new Student{Age = 2, Name = "bob"}
    });
    int sum = connection.Query<int>("select sum(Age) from #t drop table #t").First();
    tally.IsEqualTo(2);
    sum.IsEqualTo(3);
}

Cela fonctionne comme annoncé. J'ai apporté quelques modifications à la manière dont fonctionne le multi-exec (donc c'est un peu plus rapide et supporte object []).

Je suppose que vous aviez des problèmes car il vous manquait une propriété de WTUser sur tous les champs de WTUser . Tous les paramètres doivent avoir des propriétés de lecteur, nous ne prenons pas en charge cette opération à partir des champs, cela nécessiterait une étape d'analyse complexe pour rester efficace.


Un autre point qui a causé un problème est de transmettre un paramètre avec un mappage non pris en charge.

Par exemple, la classe suivante n'est pas prise en charge en tant que paramètre:

class Test
{
   public int Id { get; set; }
   public User User {get; set;}
}

cnn.Query("select * from Tests where Id = @Id", new Test{Id = 1}); // used to go boom 

Le problème est que dapper n'a pas analysé le SQL, il a supposé que tous les accessoires étaient paramétrables en tant que paramètres mais qu'il était impossible de résoudre le type SQL pour l' User .

La dernière version résout ce problème




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