2017-08-08 3 views
1

Ich führe eine gespeicherte Prozedur mit QueryMultiple, um mehrere Datensätze zurückgeben.QueryMultiple Result Set Reihenfolge geändert

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

ich sehr leicht jeden Satz gegeben bekommen kann ich die Reihenfolge weiß, dass sie kommen wieder in.

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

Allerdings bin ich in einer Situation, in der Reihenfolge, wie sie wird im Mai wiederkommen. Ein anderer Entwickler könnte entscheiden, die Bestellung aus welchem ​​Grund auch immer zu ändern. Die gespeicherte Prozedur lautet nun:

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

Wie kann ich damit umgehen?

Mein erster Versuch war es, jedes Gitter zu iterieren und die Spaltennamen zu überprüfen. Dies schien zunächst gut zu funktionieren, aber ich war nicht in der Lage herauszufinden, wie ich dann das Raster in eine Klasse projizieren sollte, abgesehen von der manuellen Einstellung jedes Feldes. Der Hauptgrund, warum ich Dapper benutze, ist, dass es das für mich tun kann.

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")) { } 
} 

Meine zweite Idee war jedes Gitter in eine Klasse zu lesen, überprüfen Sie die einzigartigen Felder der Klasse für Nullen/Standardwerte, und versuchte, die nächste Klasse, wenn der Test nicht bestanden. Das wird natürlich nicht funktionieren. .Read() wird das nächste Ergebnisraster zurückgeben. Diese Lösung würde erfordern, dass ich das gleiche Raster immer wieder lesen könnte.

Antwort

1

Davmos's answer wies mich in die richtige Richtung. Benötigt, um eine Kombination von ADO.NET und Dapper zu verwenden. Verwenden Sie im Wesentlichen ADO.NET zum Abrufen und Durchlaufen der Daten, aber verwenden Sie Dapper, um die Zeilen in meine Objekte zu analysieren. Beachten Sie die Verwendung von FieldCount in der While-Schleife, falls ein Resultset tatsächlich 0 Zeilen zurückgibt. Wir wollen, dass es zur nächsten Ergebnismenge weitergeht, nicht aus der Schleife ausbricht.

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 bietet eine Erweiterungsmethode IDataReader.GetRowParser, die Typumschaltung pro Zeile ermöglicht. Aus dem Dapper docs here ...

Normalerweise sollten Sie alle Zeilen aus einer Tabelle als den gleichen Datentyp behandeln. Es gibt jedoch einige Umstände, in denen es sinnvoll ist, verschiedene Zeilen als unterschiedliche Datentypen zu analysieren ( ). Hier ist IDataReader.GetRowParser praktisch.

Imagine haben Sie eine Datenbank Tabelle mit dem Namen „Shapes“ mit den Spalten: ID, Typ und Daten, und Sie wollen ihre Zeilen in Kreis, Quadrat oder Dreieck Objekte analysieren, basierend auf dem Wert des Spalts Typen .

var shapes = new List<IShape>(); 
using (var reader = connection.ExecuteReader("select * from Shapes")) 
{ 
    // Generate a row parser for each type you expect. 
    // The generic type <IShape> is what the parser will return. 
    // The argument (typeof(*)) is the concrete type to parse. 
    var circleParser = reader.GetRowParser<IShape>(typeof(Circle)); 
    var squareParser = reader.GetRowParser<IShape>(typeof(Square)); 
    var triangleParser = reader.GetRowParser<IShape>(typeof(Triangle)); 

    var typeColumnIndex = reader.GetOrdinal("Type"); 

    while (reader.Read()) 
    { 
     IShape shape; 
     var type = (ShapeType)reader.GetInt32(typeColumnIndex); 
     switch (type) 
     { 
      case ShapeType.Circle: 
       shape = circleParser(reader); 
       break; 
      case ShapeType.Square: 
       shape = squareParser(reader); 
       break; 
      case ShapeType.Triangle: 
       shape = triangleParser(reader); 
       break; 
      default: 
       throw new NotImplementedException(); 
     } 

     shapes.Add(shape); 
    } 
} 

Sie erhalten Zugang zu den IDataReader erhalten müssen, dass die GridReader Wraps oder Code ändern, um die guten altmodischen ADO.NET SqlConnection & SqlCommand Objekte wie dies zu verwenden ...

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

Danke mich in die richtige Richtung für den Hinweis! Ich dachte, ich würde 'GetRowParser' irgendwie brauchen, aber ich konnte es nicht richtig herausfinden. Die Kombination mit einem SqlDataReader hat es geschafft. –

+0

Gern geschehen :) Gut gemacht! – davmos

Verwandte Themen