2016-06-14 1 views
0

私の問題はこれです。
enter image description hereダイナミックタイプはウェブAPIから返ることはできません。常に異なる列のセット

私は、テーブル内の項目のリストでピボットすることによって常に変化する列のセットを持っています。基本的には、上記の図の各列はデータベーステーブルの行です。私はフロントエンドに1行の行を表示したい。コントローラやAPIからこの動的な型を返すにはどうしたらいいですか?

私はこのようなコードを使用しようとしています。

List<dynamic> items = repository.GetAll(); 
foreach(var item in items){ 
var properties = item.GetType().GetProperties(BindingFlags.Public); 
    foreach (var property in properties) { 
     var PropertyName = property.Name; 
     var PropertyValue = item.GetType().GetProperty(property.Name).GetValue(item, null); 
     model.Add(PropertyName, PropertyValue); 
    } 
} 

しかし、GetProperties()は動的な「アイテム」から何も返しません。私もitem.GetType()を使って試してみました。GetFields()を無駄に使いました。
どうすればその列の名前がわからないときに、C#の動的データ型から列名と値を取得できますか?または、APIから動的オブジェクトを返すだけですか?ありがとう。

ここにリポジトリコードがあります。

public IEnumerable<dynamic> GetAll() 
{ 
var items = context.Database.SqlQuery<dynamic>(
        "DECLARE @cols NVARCHAR(MAX), @sql NVARCHAR(MAX)" + 

     "SET @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(FormDetails.Name)" + 
       "  from Value" + 
     " left join ValueDetails" + 
     " on Value.Id = ValueDetails.ValueId" + 
     " left" + 
       " join FormDetails" + 


       " on ValueDetails.FormDetailsId = FormDetails.Id" + 
       "   ORDER BY 1" + 
       " FOR XML PATH(''), TYPE" + 
       " ).value('.', 'NVARCHAR(MAX)'), 1, 1, '')" + 

       " SET @sql = 'SELECT Id, FormId, CreatedDateTime, ' + @cols + '" + 
       "  FROM" + 
       " (" + 
        " select Value.Id, Value.FormId, FormDetails.Name, ValueDetails.Value, Value.CreatedDateTime" + 

        "  from Value" + 
        "  left join ValueDetails" + 

        "  on Value.Id = ValueDetails.ValueId" + 

        " left" + 
        "  join FormDetails" + 

       " on ValueDetails.FormDetailsId = FormDetails.Id" + 
        " ) s" + 
       " PIVOT" + 
        "(" + 
         "MAX(Value) FOR Name IN(' + @cols + ')" + 
        ") p order by CreatedDateTime desc '" + 

     " EXECUTE(@sql)").ToList(); 
     return items; 
} 

ここにもう少し詳しい情報があります。基本的に私のリポジトリはこのページの一番上にある最初のイメージからデータを返します。しかし、私はフロントエンドにそのデータを返すとき、これはそれがどのように見えるのですか?オブジェクトがあるが、無プロパティ...

enter image description here

enter image description here

答えて

1

彼らは本当にありませんので、あなたのコードの問題は、プロパティの空のリストを取得していません。 SqlQuery<T>は、タイプがTでない場合はプロパティを設定しません。 dynamicを渡すと、System.Objectに変換されます。これを解決するための

1つのトリックは、動的に列名を取得し、そこからExpandoObjectを構築することです。技術はhereと記載されています。 、あなたのリポジトリがExpandoObject秒を返す開始すると

using (var cmd = ctx.Database.Connection.CreateCommand()) { 
    ctx.Database.Connection.Open(); 
    cmd.CommandText = ...; // Your big SQL goes here 
    using (var reader = cmd.ExecuteReader()) { 
     return Read(reader).ToList(); 
    } 
} 

を呼び出して、プロパティを取得するためのコードがIDictionary<string,object>を照会コードに置き換えることができ

代わりに、この方法では
static IList<dynamic> Read(DbDataReader reader) { 
    var res= new List<Dictionary<string,object>>(); 
    foreach (var item in reader) { 
     IDictionary<string,object> expando = new ExpandoObject(); 
     foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(item)) { 
      var obj = propertyDescriptor.GetValue(item); 
      expando.Add(propertyDescriptor.Name, obj); 
     } 
     res.Add(expando); 
    } 
    return res; 
} 

ExpandoObjectによって実装されたインタフェース:

IDictionary<string,object> properties = item as IDictionary<string,object>; 
if (properties != null) { 
    foreach (var p in properties) { 
     model.Add(p.Key, p.Value); 
    } 
} 
+0

私はこれを打ち、何が起こるかを教えてもらいます。ありがとう。 – joel1618

+0

そのOmgは動作します。本当にありがとう。私の頭を壁に打つの2日間。読者は動的アイテムのプロパティを解釈できないと思いますか? – joel1618

+0

@ joel1618ボンネットの下には、「ダイナミック」というものはありません(それは、サービがヒントしていたものです)。 'dynamic'を書くと、C#は' object'をその場所に置きますが、実行時に実装を提供すると仮定すると、未知のメソッドとプロパティを使用するコードをコンパイルできます。 'SqlQuery 'を呼び出すと、返される列を決めるクエリーの列名と 'T'のプロパティの両方になります。たとえば、 'SqlQuery 'は 'FormId'を返すので、' T'の 'FormId'を探します。これは' dynamic'です。つまり 'object'です。 'FormId'はそこにはないので、スキップされます。 – dasblinkenlight

関連する問題