动态类型无法从web api返回不同的列集

时间:2016-06-14 16:29:03

标签: c# dynamic

我的问题是这个。
enter image description here

由于在表格中的项目列表上进行了旋转,因此我有一组不断变化的列。基本上,您在上图中看到的每列都是数据库表中的一行。我想在前端显示一组线作为一行。如何从控制器或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()不会从动态&#34;项目&#34;中返回任何内容。我也尝试过使用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 个答案:

答案 0 :(得分:1)

您的代码的问题不在于获取一个空的属性列表,因为它们确实不存在。如果属性SqlQuery<T>上没有属性,T将不会填充该属性;您传递dynamic,转换为System.Object

解决此问题的一个技巧是动态检索列名,并从中构建ExpandoObject。该技术被描述为here

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

使用此方法,请致电

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

一旦您的存储库开始返回ExpandoObject,您的代码可以替换为代码查询IDictionary<string,object>,这是ExpandoObject实现的接口:

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