2012-06-30 7 views
9

現在、私はこのようなものを使用しています:私の代わりにSQLクエリの結果をオブジェクトにマップするにはどうしたらいいですか?

try 
    { 
     dr = SQL.Execute(sql); 

     if(dr != null) { 
     while(dr.Read()) { 
      CustomObject c = new CustomObject(); 
      c.Key = dr[0].ToString(); 
      c.Value = dr[1].ToString(); 
      c.Meta = dr[2].ToString(); 
      customerInfo.CustomerList.Add(c); 
     } 
     } 
     else 
     { 
      customerInfo.ErrorDetails="No records found"; 
     } 

を手動でassigmentsをやって、直接このマッピングを行う方法がある(列名は、フィールド名と一致していることを前提とし)。

ただし、私はSQLクエリを使用する現在のアプローチではなく、純粋なLINQベースのアプローチを使用してこれを実行したいと考えています。 1つは、SQLのクエリは十分に大きく、複雑なJOINが関わっており、徹底的にテストされているため、現時点ではより多くのバグを導入したくありません。助言がありますか?

+2

カスタムSQLクエリでLINQを使用することができることに注意してください。クエリ結果のフィールドは、入力した汎用オブジェクトタイプに自動的にマップされます。 [** 'DataContext.ExecuteQuery' **](http://msdn.microsoft.com/en-us/library/bb361109.aspx)を参照してください。 – mellamokb

+0

@mellamokb:どのように表示できますか?または、少なくとも私はいくつかのリソースを指しているかもしれません。 – Legend

+0

あなたが必要とする具体的な方法である、私が追加したリンクを見てください。そのページにも例があります。 – mellamokb

答えて

4

あなたのCustomObjectのコンストラクタには、DataRowが必要です(この例では、別のクラスであれば修正してください)。

新しいコンストラクタでは、独自の例のように行います。

public CustomObject(DataRow row) 
{ 
    Key = row[0].ToString(); 
    // And so on... 
} 

もう一つの方法は、ジェネリックを導入すること、そしてあなたのSQLクラス

例では、新たな機能になるだろうが(Passing arguments to C# generic new() of templated typeからコードを取った):

// This function should reside in your SQL-class. 
public IEnumerable<T> ExecuteObject<T>(string sql) 
{ 
    List<T> items = new List<T>(); 
    var data = ExecuteDataTable(sql); // You probably need to build a ExecuteDataTable for your SQL-class. 
    foreach(var row in data.Rows) 
    { 
     T item = (T)Activator.CreateInstance(typeof(T), row); 
     items.Add(item); 
    } 
    return items; 
} 

使用例:

public IEnumerable<CustomObject> GetCustomObjects() 
{ 
    return SQL.ExecuteObject<CustomObject>("SELECT * FROM CustomObject"); 
} 

私はこのコードをLinqPadでテストしましたが、うまくいくはずです。

3

要件に合った汎用的な方法を作成することで実現できます。また、新しいメソッドをデータテーブルの拡張として作成することもできます。

public static List<T> ToList<T>(this DataTable table) where T : class, new() 
{ 
    try 
    { 
     List<T> list = new List<T>(); 

     foreach (var row in table.AsEnumerable()) 
     { 
      T obj = new T(); 

      foreach (var prop in obj.GetType().GetProperties()) 
      { 
       try 
       { 
        PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name); 
        propertyInfo.SetValue(obj, Convert.ChangeType(row[prop.Name], propertyInfo.PropertyType), null); 
       } 
       catch 
       { 
        continue; 
       } 
      } 

      list.Add(obj); 
     } 

     return list; 
    } 
    catch 
    { 
     return null; 
    } 
} 

}

使用法:

DataTable dtCustomer = GetCustomers(); 
    List<CustomObject> CustomObjectList = dtCustomer.ToList<CustomObject>(); 
2

あなたはMicroORMsになっているはずです。 MicroORMでは、通常のORMとは異なり、独自のSQLクエリを使用して、SQL結果セットからC#オブジェクトおよびC#オブジェクトからSQLパラメータへのマッピングのみを提供できます。

お気に入りはPetaPocoで、独自のSQLを使用するクエリビルダーも提供しますが、パラメータ番号の操作はきちんとしています。

0

次の関数はSQL文字列とオブジェクトを受け入れますが、オブジェクトにはselect文の各列のプロパティが必要です。オブジェクトはインスタンス化する必要があります。

パブリックオブジェクトSqlToSingleObject(文字列SSQL、オブジェクトo) {

 MySql.Data.MySqlClient.MySqlDataReader oRead; 
     using (ConnectionHelper oDb = new ConnectionHelper()) 
     { 
      oRead = oDb.Execute(sSql); 
      if (oRead.Read()) 
      { 

       for (int i = 0; i < oRead.FieldCount; i++) 
       { 

        System.Reflection.PropertyInfo propertyInfo = o.GetType().GetProperty(oRead.GetName(i)); 
        propertyInfo.SetValue(o, Convert.ChangeType(oRead[i], propertyInfo.PropertyType), null); 
       } 
       return o; 
      } 
      else 
      { 
       return null; 

      } 

     } 

    } 
+0

そのポイントは何ですか?すべてのポピュラリティを作成する場合は、オブジェクトを自分で構築するだけではいかがですか。 – MattE

1

仮定:あなただけのシリアル化または単純なアドホック出力のためのオブジェクトが必要な場合。

あなたはこのようExpandoObjectSqlDataReader.GetSchemaTable()を使用することができます。掲載速く解決策はありますが

private IEnumerable<dynamic> ReaderToAnonymmous(SqlCommand comm) { 
     using (var reader = comm.ExecuteReader()) { 
      var schemaTable = reader.GetSchemaTable(); 

      List<string> colnames = new List<string>(); 
      foreach (DataRow row in schemaTable.Rows) { 
       colnames.Add(row["ColumnName"].ToString()); 
      } 

      while (reader.Read()) { 
       var data = new ExpandoObject() as IDictionary<string, Object>; 
       foreach (string colname in colnames) { 
        var val = reader[colname]; 
        data.Add(colname, Convert.IsDBNull(val) ? null : val); 
       } 

       yield return (ExpandoObject)data; 
      } 
     } 
    } 

(私はアドホックSQL/Readerの結果/出力のための代替怠惰なアプローチとしての投稿です)。

+0

これは素晴らしい、まさに私が探していたものです。私はストアドプロシージャからExcelでレポートを生成するコンソールアプリケーションです。このコードでは、アプリケーション内のプロシージャをマップする必要はありません。ありがとうございました。 – v1n1akabozo

関連する問題