2008-11-27 14 views
3

Je voudrais trier une colonne dans le résultat d'une procédure stockée sans avoir à ajouter la clause Order By dans la procédure stockée. Je ne veux pas que les données soient triées après que j'ai exécuté la requête, le tri devrait faire partie de la requête si possible. J'ai le code suivant:Tri du résultat d'une procédure stockée

 

     public static DataTable RunReport(ReportQuery query) 
     { 
      OffertaDataContext db = new OffertaDataContext(); 
      Report report = (from r in db.Reports where r.Id == (int)query.ReportId select r).Single(); 
      //???: check security clearance. 

      DataSet dataSet = new DataSet(); 

      /* 
      doesn't work, I guess the "Result" table hasn't been created yet; 
      if(!string.IsNullOrEmpty(query.SortField)) 
      { 
       dataSet.DefaultViewManager.DataViewSettings["Result"].Sort = query.SortField + " " + (query.SortAscending ? "ASC" : "DESC"); 
      } 
      */ 

      using (SqlConnection conn = new SqlConnection(Config.ConnectionString)) 
      { 
       conn.Open(); 
       using (SqlCommand exec = conn.CreateCommand()) 
       { 
        using (SqlDataAdapter adapter = new SqlDataAdapter()) 
        { 
         exec.Connection = conn; 
         exec.CommandType = CommandType.StoredProcedure; 
         exec.CommandText = report.ReportProc; 

         adapter.SelectCommand = exec; 
         try 
         { 

          adapter.Fill(dataSet, query.Skip, query.Take, "Result"); 
         } 
         catch (Exception e) 
         { 
          throw e; 
         } 
         finally 
         { 
          conn.Close(); 
         } 
         return dataSet.Tables["Result"]; 
        } 
       } 
      } 
     } 

Comment ajouter un tri?

Merci! /Niels

+0

vous dites « Je voudrais trier sur une colonne dans le résultat d'une procédure stockée sans avoir à ajouter la clause Order By dans la procédure stockée "et ensuite" le tri devrait faire partie de la requête si possible "! –

Répondre

2

Récupérez le DataTable que vous remplissez dans le jeu de données ("Résultat"). Maintenant, il n'y a aucun moyen de trier le DataTable, sauf via la requête, la vue ou la procédure stockée qui le remplit.

Puisque vous ne voulez pas le faire dans le SP, vous pouvez trier le DefaultView du DataTable , ou n'importe quel DataView associé au DataTable.

Vous pouvez le réaliser en utilisant la propriété Sort du DataView. C'est une chaîne qui spécifie la colonne (ou les colonnes) à trier, et l'ordre (ASC ou DESC).

Exemple:

myTable.DefaultView.Sort = "myColumn DESC"; 

Vous pouvez maintenant utiliser la DefaultView pour faire ce que vous voulez (le lier à quelque chose ou autre)

1

Pour être honnête, puisque vous utilisez DataTable, vous pouvez tout aussi bien trier sur le client.

Le tri dynamique (au niveau du serveur) via les SP, etc. est toujours pénible; Pour le faire en TSQL pur, vous avez besoin soit d'un bloc CASE horriblement inefficace à la fin du SELECT, soit d'un SQL dynamique (par exemple via sp_ExecuteSQL), en manipulant ORDER BY dans la requête finale. La seule autre option (dans TSQL brut) serait EXEC/INTO pour obtenir les données dans une variable de table (ou une table temporaire), puis SELECT à partir de ceci avec un ORDER BY.

S'il s'agit d'une option, LINQ-to-SQL fonctionne correctement; il prend en charge l'interrogation (et la composition) des fonctions UDF - donc plutôt que d'un SP, codez la requête dans un UDF (le SP peut toujours sélectionner simplement depuis l'UDF si vous avez besoin de prendre en charge les anciens appelants). Ensuite, vous pouvez utiliser « commande par » etc dans une requête LINQ:

var qry = from row in ctx.SomeMethod(args) 
      order by row.Name, row.Key 
      select row; 

(ou il existe différentes méthodes permettant d'ajouter une sorte dynamique à une requête LINQ - ce qui précède est juste un exemple simple)

la TSQL final sera quelque chose comme:

SELECT blah FROM theudf(args) ORDER BY blah 

par exemple, il va bien faire, et faire le "ORDER BY" sur le serveur. Ceci est particulièrement utile lorsqu'il est utilisé avec Skip() et Take() pour obtenir des données paginées.