IEnumerableを挿入する方法 dapper-dot-netでのコレクション

c# dapper insert vb.net

質問

はい、dapper-dot-netでレコードを挿入する方法についてはここここで 質問しています 。しかし、答えは、有益ではありませんが、正しい方向に私を指すように見えませんでした。 SqlServerからMySqlにデータを移動する状況があります。レコードをIEnumerable<WTUser>は簡単ですが、挿入物には何も表示されません。まず、 'moving records code':

//  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およびcnn.Executeは、ダッパー拡張メソッドを呼び出します。今、WTUserクラス(注:列名はSqlServerの 'WindowsName'からMySqlの 'ResourceName'に変更されているため、2つのプロパティが同じフィールドを指しています)。

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、Version = 1.0.0.0、Culture =ニュートラル、PublicKeyToken = null]]、mscorlib、バージョン= 2.0.0.0、Culture =ニュートラル、PublicKeyToken = b77a5c561934e089

OwnerTypeがCRMBackEnd.WTUser ... not List<CRMBackEnd.WTUser> ...である必要が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

受け入れられた回答

私はちょうどこれのためのテストを追加しました:

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

広告されたとおりに動作します。マルチ・エグゼクティブ・ワークのやり方にいくつかの修正を加えました(そのために、より速く、オブジェクト[]をサポートしています)。

私の推測では、 WTUserすべてのフィールドにゲッタープロパティがないために問題が発生しています。すべてのパラメータにはリーダのプロパティが必要ですが、フィールドから引き出すことはサポートされていません。効率的に行うには複雑な解析ステップが必要です。


問題を引き起こした追加のポイントは、サポートされていないマッピングを持つparamをdapperに渡すことです。

たとえば、次のクラスはparamとしてサポートされていません。

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を解析しなかったことです。すべての小道具がparamsとして設定可能であると仮定していましたが、 User SQL型を解決できませんでした。

最新版でこれを解決



ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ