2017-10-17 13 views
1

J'essaie de tirer des enregistrements à partir d'un db avec une commande optionnelle par. Pour que j'ai créé un proc stocké (quelques laissés colonnes pour une meilleure lisibilité):Processus stocké pour le chemin XML - ordre en ne fonctionnant pas

CREATE PROCEDURE [dbo].[sp_VendorOverview] (@sortCol nvarchar(50)=NULL) 

AS 

BEGIN 

    SET NOCOUNT ON; 
    select v.Vid, s.Salutation, v.LastName, CONVERT(varchar(100), CAST(v.VAT AS decimal(38,0))) AS VAT 
    from vendors v 
    inner join Salutations s 
    on v.salutation=s.anrede 

    order by 
     CASE WHEN @sortCol='LastName' THEN v.LastName 
      WHEN @sortCol='FirstName' THEN v.FirstName 
      ELSE NULL 
     END, 
     CASE WHEN @sortCol ='VendorNumber' THEN v.VendorNumber 
      ELSE v.Vid 
     END 
    for xml path('VendorBasic'), root('Vendors') 
END 

Lors de l'exécution de cette sp dans SSMS, tout va bien, les résultats sont comme prévu. Non, cependant, en essayant de lire à partir de C# application comme ceci:

var vendoren = new List<VendorBasic>(); 

using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["Vendor"].ConnectionString)) 
{ 
    var xml = string.Empty; 
    con.Open(); 
    using (var cmd = new SqlCommand("dbo.sp_VendorOverview", con)) 
    { 
     if (!string.IsNullOrEmpty(orderby)) 
      cmd.Parameters.AddWithValue("@sortCol", orderby); 

     using (XmlReader idr = cmd.ExecuteXmlReader()) 
     { 
      if (idr.Read()) 
      { 
       xml = idr.ReadOuterXml(); 
      } 
      idr.Close(); 
     } 
     con.Close(); 
    } 
    if (xml != string.Empty) 
    { 
     XmlRootAttribute xRoot = new XmlRootAttribute 
     { 
      ElementName = "Vendors", 
      IsNullable = true 
     }; 
     var engine = new XmlSerializer(typeof(List<VendorBasic>), xRoot); 
     vendoren = (List<VendorBasic>)engine.Deserialize(new StringReader(xml)); 
    } 
} 

désérialisation fonctionne très bien, attribut XmlRoot est défini pour la classe VendorBasic. J'obtiens des résultats. Ils ne sont jamais commandés par autre chose que Vid. J'ai mis un point d'arrêt pour vérifier si le paramètre est correctement appliqué au cas où je voudrais commander par n'importe quelle autre colonne. Il est:

enter image description here

Suis-je manque quelque chose? Est-ce que je fais quelque chose de mal?

+0

Pourquoi avez-vous deux expressions de cas dans la clause order by? une seule expression de cas devrait être très bien pour cela .... –

+0

@ZoharPeled J'ai besoin de deux, car ils se réfèrent à deux types de champs différents, nvarchar et int. CASE WHEN expressions tentent d'unifier les types de champ à l'ordre du plus élevé, ce qui signifie dans ce cas, il serait essayer de convertir "LastName" en type int si j'ai par exemple. VendorNumber également dans le même bloc CASE. J'ai dû apprendre cela à la dure d'abord. Vous avez besoin d'un bloc CAS pour chaque type de champ que vous voulez gérer. :-) – LocEngineer

+1

Peut-être que vous devriez faire 'cmd.CommandType = CommandType.StoredProcedure;'? – Evk

Répondre

1

Vous devez dire SqlCommand que vous exécutez la procédure stockée et non commande arbitraire, en faisant

cmd.CommandType = CommandType.StoredProcedure; 

Sans qu'il ignorera essentiellement tous vos paramètres et exécuter la procédure avec les paramètres par défaut (null dans ce cas) . Vous pourriez trouver plus d'informations à ce sujet dans cette question: When executing a stored procedure, what is the benefit of using CommandType.StoredProcedure versus using CommandType.Text?.

+0

Excellent lien, merci! – LocEngineer