Как вставить коллекцию IEnumerable <T> с dapper-dot-net

Да, здесь есть вопросы и здесь о том, как вставлять записи с dapper-dot-net, Однако ответы, в то время как информативные, похоже, не указывали мне в правильном направлении. Вот ситуация: перемещение данных с SqlServer на MySql. Чтение записей в IEnumerable<WTUser> выполняется легко, но я просто ничего не получаю от вставки. Во-первых, "код движущихся записей":

//  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", "[email protected]$$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 и cnn.Execute вызовите методы расширения dapper. Теперь класс WTUser (обратите внимание: имя столбца изменилось с "WindowsName" на SqlServer на "ResourceName" в MySql, таким образом, два свойства указывали на одно и то же поле):

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

Я получаю исключение из dapper: "WTUser не поддерживается Dapper". Этот метод в 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))

В этот момент OwnerType =

System.Collections.Generic.List`1 [[CRMBackEnd.WTUser, CRMBE, версия = 1.0.0.0, Culture = нейтрально, PublicKeyToken = null]], mscorlib, Версия = 2.0.0.0, Культура = нейтральная, PublicKeyToken = b77a5c561934e089

Кажется, что OwnerType должен быть CRMBackEnd.WTUser... not List<CRMBackEnd.WTUser>...??? потому что происходит то, что свойства коллекции повторяются: Count, Capacity и т.д. Что мне не хватает?

Обновить

Если я изменил session.WriteData как:

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

записи вставляются красиво... но я не думал, что это было бы необходимо, если бы приведенные примеры, например:

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"  

... из dapper-dot-net

Ответы

Ответ 1

Я просто добавил тест для этого:

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

Он работает как рекламируемый. Я сделал несколько поправок к тому, как работает multi-exec (так что он немного быстрее и поддерживает объект []).

Я предполагаю, что у вас были проблемы, потому что у вас не было свойства getter во всех ваших полях на WTUser. Все параметры должны иметь свойства считывателя, мы не поддерживаем вытягивание этого из полей, для этого требуется комплексный синтаксический анализ.


Дополнительной точкой, вызвавшей проблему, является передача dapper параметра с неподдерживаемым отображением.

Например, следующий класс не поддерживается как параметр:

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 

Проблема в том, что dapper сделал не синтаксический анализ SQL, он предположил, что все реквизиты настраиваются как параметры, но не смогли разрешить тип SQL для User.

Последний rev разрешает это