6 votes

Transmettre des paramètres en tant que Xml à une procédure stockée

J'ai besoin de passer des paramètres en tant que Xml à mes procédures stockées.

J'ai un service WCF au niveau intermédiaire qui fait des appels à ma couche de données qui, à son tour, transmet la requête à la procédure stockée appropriée.

La conception est que le service WCF est responsable de la construction du Xml à transmettre au référentiel.

Je me demande s'il faut garder le contrôle des paramètres contenus dans le Xml au niveau intermédiaire ou utiliser un dictionnaire construit par le client que je convertis ensuite en Xml au niveau intermédiaire.

Pour l'instant, j'ai opté pour cette dernière solution - par exemple :

 public TestQueryResponseMessage TestQuery(TestQueryRequestMessage message)
 {
        var result = Repository.ExecuteQuery("TestQuery", ParamsToXml(message.Body.Params));

        return new TestQueryResponseMessage
        {
            Body = new TestQueryResponse
            {
                TopicItems = result;
            }
        }
    }

private string ParamsToXml(Dictionary<string, string> nvc)
{
        //TODO: Refactor
        StringBuilder sb = new StringBuilder();

        sb.Append("<params>");
        foreach (KeyValuePair<string, string> param in nvc)
        {
            sb.Append("<param>");
            sb.Append("<" + param.Key + ">");
            sb.Append(param.Value);
            sb.Append("</" + param.Key + ">");
            sb.Append("</param>");
        }
        sb.Append("</params>");

        return sb.ToString();
}

Toutefois, il se peut que je doive procéder de la première manière. Par exemple

public TestQueryResponseMessage TestQuery(TestQueryRequestMessage message)
{
       string xml = string.Format("<params><TestParameter>{0}</TestParameter></params>",message.Body.TestParameter)

       var result = Repository.ExecuteQuery("TestQuery", xml);

      return new TestQueryResponseMessage
      {
          Body = new TestQueryResponse
          {
                    TopicItems = result;
          }
      }
}

Que recommande l'esprit de ruche ?

6voto

Marc Gravell Points 482669

Si vous devez utiliser xml, plutôt que de faire circuler un dictionnaire, j'utiliserais une classe qui représente ces données, et j'utiliserais XmlSerializer pour le récupérer au format xml :

[Serializable, XmlRoot("args")]
public class SomeArgs {
    [XmlElement("foo")] public string Foo { get; set; } 
    [XmlAttribute("bar")] public int Bar { get; set; }
}
...
SomeArgs args = new SomeArgs { Foo = "abc", Bar = 123 };
XmlSerializer ser = new XmlSerializer(typeof(SomeArgs));
StringWriter sw = new StringWriter();
ser.Serialize(sw, args);
string xml = sw.ToString();

Il est ainsi beaucoup plus facile de gérer quels arguments s'appliquent à quelles requêtes, d'une manière orientée objet. Cela signifie également que vous n'avez pas à faire votre propre échappement xml...

3voto

DBAndrew Points 2967

Une fois que vous avez utilisé la solution de Bob le concierge, vous avez votre XML.

Créez votre procédure stockée avec un paramètre XML. Ensuite, en fonction de la quantité de XML que vous avez et de ce que vous en faites, vous pouvez utiliser Xquery ou OpenXML pour déchiqueter le document XML. Extrayez les données et effectuez l'action appropriée. Cet exemple est basique et s'apparente à du pseudo-code, mais vous devriez comprendre l'idée.

CREATE PROCEDURE [usp_Customer_INS_By_XML]
@Customer_XML XML
AS
BEGIN
EXEC sp_xml_preparedocument @xmldoc OUTPUT, @Customer_XML

--OPEN XML example of inserting multiple customers into a Table.
INSERT INTO CUSTOMER
(
First_Name
Middle_Name
Last_Name
)
SELECT
First_Name
,Middle_Name
,Last_Name
FROM OPENXML (@xmldoc, '/ArrayOfCustomers[1]/Customer',2)
WITH(
 First_Name VARCHAR(50)
,Middle_Name VARCHR(50)
,Last_Name VARCHAR(50)
)

EXEC sp_xml_removedocument @xmldoc
END

1voto

Bob The Janitor Points 5526

Vous pouvez simplement utiliser une classe de sérialisation d'objets comme ceci

 public class Serialization
    {
        /// <summary>
        /// Serializes the object.
        /// </summary>
        /// <param name="myObject">My object.</param>
        /// <returns></returns>
        public static XmlDocument SerializeObject(Object myObject)
        {
            XmlDocument XmlObject = new XmlDocument();
            String XmlizedString = string.Empty;

            try
            {                
                MemoryStream memoryStream = new MemoryStream();
                XmlSerializer xs = new XmlSerializer(myObject.GetType());
                XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
                xs.Serialize(xmlTextWriter, myObject);
                memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
                XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());                
            }
            catch (Exception e)
            {
                System.Console.WriteLine(e);
            }
            XmlObject.LoadXml(XmlizedString);
            return XmlObject;            
        }

        /// <summary>
        /// Deserializes the object.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="XmlizedString">The p xmlized string.</param>
        /// <returns></returns>
        public static T DeserializeObject<T>(String XmlizedString)
        {
            XmlSerializer xs = new XmlSerializer(typeof(T));
            MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(XmlizedString));
            //XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
            Object myObject = xs.Deserialize(memoryStream);
            return (T)myObject;
        } 

        /// <summary>
        /// To convert a Byte Array of Unicode values (UTF-8 encoded) to a complete String.
        /// </summary>
        /// <param name="characters">Unicode Byte Array to be converted to String</param>
        /// <returns>String converted from Unicode Byte Array</returns>
        private static String UTF8ByteArrayToString(Byte[] characters)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            String constructedString = encoding.GetString(characters);
            return (constructedString);
        }

        /// <summary>
        /// Converts the String to UTF8 Byte array and is used in De serialization
        /// </summary>
        /// <param name="pXmlString"></param>
        /// <returns></returns>
        private static Byte[] StringToUTF8ByteArray(String pXmlString)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            Byte[] byteArray = encoding.GetBytes(pXmlString);
            return byteArray;
        } 
    }

vous n'avez pas besoin de construire le XML à la main, et vous pouvez l'utiliser avec n'importe quel élément pour le transformer à l'aide de XSLT

0voto

Gulzar Nazim Points 35342

Je placerais le code de construction xml à l'intérieur de l'objet domaine. De cette façon, vous pouvez simplement appeler obj.GetXML() à partir du service Web ou de la couche de données.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X