【问题标题】:How to return dynamic object from SQL query如何从 SQL 查询返回动态对象
【发布时间】:2019-09-09 05:35:24
【问题描述】:

我有一个storeprocdure返回集合的情况,但我不知道对象结构如何,因为查询非常动态。

一个查询可以返回:

标识 |位置 |市场细分 | ... n 列

另一个可以返回

标识 |销售代表 |位置 |地区 | ... n 列

我只是返回一个“对象”,如下面的代码所示。我知道这行不通,但我该如何设置它呢?

using (DbContext db = new Context())
{

    var items = db.Database.SqlQuery<object>(
        "SP @Param1, @Param2",
        new SqlParameter("Param1", ped),
        new SqlParameter("Param2", 25)
    ).ToList();

    return Request.CreateResponse<List<object>>(HttpStatusCode.OK, items);
}

编辑:

我不知道显示 SP 是否会有所帮助,除非我能解释得更多。

每列都表示为自定义字段。用户可以创建 n 个自定义字段。因此,如果您为 User1 运行 SP 并且他有 5 个自定义字段,那么每个自定义字段将在 Columns 中表示,但如果 User2 有 3 个自定义字段,则只会表示 3 个列。我无法控制的是自定义字段名称和自定义字段的数量。

【问题讨论】:

  • 请告诉我们SP是什么。
  • 请查看已编辑的评论。

标签: c# sql entity-framework asp.net-web-api dbcontext


【解决方案1】:

您不能将SqlQuery&lt;T&gt; 用于自定义字段。

创建一个原始 SQL 查询,该查询将返回给定泛型的元素 类型。类型可以是任何具有与 从查询返回的列的名称,或者可以是一个简单的 原始类型。 - MSDN

但是,您可以使用ExecuteReader 来实现。

using (var db = new Context())
{
    db.Database.Connection.Open();

    var cmd = db.Database.Connection.CreateCommand();
    cmd.CommandText = "SP @Param1, @Param2";
    cmd.Parameters.Add(new SqlParameter("Param1", ped));
    cmd.Parameters.Add(new SqlParameter("Param2", 25));

    List<List<object>> items = new List<List<object>>();
    var reader = cmd.ExecuteReader();
    while (reader.Read())
    {
        var item = new List<Object>();
        items.Add(item);

        for (int i = 0; i < reader.FieldCount ; i++)
            item.Add(reader[i]);
    }

    return Request.CreateResponse<List<object>>(HttpStatusCode.OK, items);
}

【讨论】:

    【解决方案2】:

    如果在 SQL 2016 或更高版本上,请在查询中添加“FOR JSON AUTO”以返回为 JSON,例如:

    var json = db.Database.SqlQuery<string>("Select x, y, z FROM tbl FOR JSON AUTO").First();
    

    然后使用Json.Net创建一个动态对象使用

    var myDynamic = JObject.Parse(json)
    

    【讨论】:

      【解决方案3】:

      如果您知道可以返回所有可能的列,那么使用具有比您需要的更多属性的类就没有问题。

      public class Data
      {
      public int ID {get;set;}
      public string SalesRep {get;set;}//Simply will be empty in the first example, but populated in the second.
      public string Location {get;set;}
      }
      

      【讨论】:

      • 可悲的是,这不是真的(痛苦的经验之声)。这样做会导致在 System.Data.dll 中抛出 Exception: 'System.IndexOutOfRangeException' 如果你发现错误并继续,那么它仍然可以工作,但性能变得很糟糕。我有一个案例,它将执行时间从 290 毫秒增加到 4 秒。
      猜你喜欢
      • 1970-01-01
      • 2023-01-25
      • 2021-08-16
      • 2014-01-09
      • 2018-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多