2017-08-08 41 views
1

我正在执行存储过程,使用QueryMultiple来返回多组数据。QueryMultiple Result Set Order Changed

var gridReader = db.QueryMultiple("sp", 
            parameters, 
            commandType: CommandType.StoredProcedure); 

我可以很轻松地获得各组给予我知道订单,他们会回去。

SELECT * FROM dbo.Set1; 
SELECT * FROM dbo.Set2; 
SELECT * FROM dbo.Set3; 
var set1 = gridReader.Read<Set1>(); 
var set2 = gridReader.Read<Set2>(); 
var set3 = gridReader.Read<Set3>(); 

不过,我在的情况下,他们的顺序会回来可能会改变。另一位开发人员可能因为任何原因决定更改订单。存储过程现在变为:

SELECT * FROM dbo.Set1; 
SELECT * FROM dbo.Set3; 
SELECT * FROM dbo.Set2; 

我该如何处理?

我最初的尝试是迭代每个网格,检查列名称。这似乎起初运作良好,但我无法弄清楚如何将网格投影到课程中,除了手动设置每个字段。我使用Dapper的主要原因是它可以为我做到这一点。

while (true) 
{ 
    var grid = gridReader.Read(); 
    IDictionary<string, object> row = grid.FirstOrDefault(); 

    if (row == null) 
     break; 

    if (row.Keys.Contains("Set1_UniqueColumnName")) 
    { 
     // Need something like grid.Read<Set1>(); 
    } 
    else if (row.Keys.Contains("Set2_UniqueColumnName")) { } 
    else if (row.Keys.Contains("Set3_UniqueColumnName")) { } 
} 

我的第二个想法是读每个网格成一个类,检查类的唯一字段空值/默认值,并试图在下次上课;如果测试失败。这显然不会工作。 .Read()将返回下一个网格的结果。这个解决方案需要我能够一遍又一遍地读取同一个网格。

回答

1

Davmos's answer指出我在正确的方向。需要使用ADO.NET和Dapper的组合。基本上使用ADO.NET来检索和遍历数据,但使用Dapper将行解析到我的对象中。注意在结果集实际上返回0行的情况下,在while循环中使用FieldCount。我们希望它移动到下一个结果集,而不是跳出循环。

Set1 set1 = null; 
var set2 = new List<Set2>(); 
Set3 set3 = null; 

using (var command = new SqlCommand("sp", conn)) 
{ 
    command.CommandType = CommandType.StoredProcedure; 
    command.Parameters.AddRange(parameters); 
    command.Connection.Open(); 

    using (var reader = command.ExecuteReader()) 
    { 
     while (reader.FieldCount > 0) 
     { 
      var set1Parser = reader.GetRowParser<Set1>(); 
      var set2Parser = reader.GetRowParser<Set2>(); 
      var set3Parser = reader.GetRowParser<Set3>(); 

      var isSet1 = HasColumn(reader, "Set1_UniqueColumnName"); 
      var isSet2 = HasColumn(reader, "Set2_UniqueColumnName"); 
      var isSet3 = HasColumn(reader, "Set3_UniqueColumnName"); 

      while (reader.Read()) 
      { 
       if (isSet1) 
       { 
        set1 = set1Parser(reader); 
       } 
       else if (isSet2) 
       { 
        set2.Add(set2Parser(reader)); 
       } 
       else if (isSet3) 
       { 
        set3 = set3Parser(reader); 
       } 
      } 

      reader.NextResult(); 
     } 
    } 
} 
public static bool HasColumn(IDataReader reader, string columnName) 
{ 
    for (var i = 0; i < reader.FieldCount; i++) 
    { 
     if (reader.GetName(i).Equals(columnName, StringComparison.InvariantCultureIgnoreCase)) 
     { 
      return true; 
     } 
    } 

    return false; 
} 
2

Dapper提供了一个IDataReader.GetRowParser扩展方法,可以实现每行的类型切换。从小巧精致的文档here ...

通常你想从一个给定的表来对待所有行一样 数据类型。但是,在某些情况下, 可以将不同的行解析为不同的数据类型。这是IDataReader.GetRowParser派上用场的地方。

假设你有一个名为“形状”与列的数据库表:ID, 类型和数据,并且要分析它的行成圆形,方形,或 三角物体基于该类型列的值。

​​

你需要获得访问IDataReaderGridReader包装或更改代码以使用老式的ADO.NET这样SqlConnection & SqlCommand对象...

using (command = new SqlCommand("sp", connection)) 
{ 
    command.CommandType = CommandType.StoredProcedure; 
    command.Parameters.AddRange(parameters); 

    using (var reader = command.ExecuteReader()) 
    { 
     while (reader.HasRows) 
     { 
      while(reader.Read()) 
      { 

      } 

      reader.NextResult(); 
     } 
    } 
} 
+0

谢谢你指着我在正确的方向!我想我会需要'GetRowParser',但我无法弄清楚。将它与SqlDataReader结合起来就是个诀窍。 –

+0

不客气:)干得好! – davmos