2011-06-17 7 views
29

ダッファドットネットでレコードを挿入する方法については、questions herehereがあります。しかし、答えは、有益ではありませんが、正しい方向に私を指すように見えませんでした。 SqlServerからMySqlにデータを移動する状況があります。レコードをIEnumerable<WTUser>に読み込むのは簡単ですが、私は挿入物に何かを得ていません。まず、「移動レコードコード」:dapper-dot-netでIEnumerable <T>コレクションを挿入する方法

// 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は、ダッパー拡張メソッドを呼び出します。さて、WTUserクラス(注:列名は、MySQLで「ResourceNameの」にのSQLServerの「を、WindowsName」から同じフィールドを指しているので、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、バージョン= 1.0.0.0、 文化=中立、 なPublicKeyToken = nullの]]、mscorlib、 バージョン= 2.0.0.0、文化=中立、 なPublicKeyToken = b77a5c561934e089

に思えますOwnerTypeのようにCRMBackEnd.WTUser ... 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

答えて

45

私はこのためのテストを追加しました:

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


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

例えば、以下のクラスはの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として設定可能であると仮定が、できませんでしたSQLタイプをUserに解決してください。

最新のリビジョンはこの

+0

編集WTUserを解決します: 'Public' *すべてのフィールドは、*ゲッター/セッター...私は簡潔のために編集されている:VBがひどく冗長です。私はそのポストを明確にするでしょう。 ;) – IAbstract

+1

@Samはこのソリューションは一般的ですか?つまり、Oracle上で動作しますか? – MaYaN

+0

私が挿入したエンティティのIDを取得するにはどうすればよいですか? –

関連する問題