Передача параметров в виде Xml хранимой процедуре

у меня есть требование передать параметры в виде Xml в мои хранимые процедуры.

у меня есть служба WCF на среднем уровне, которая вызывает мой уровень данных, который, в свою очередь, перенаправляет запрос в соответствующую хранимую процедуру.

дизайн заключается в том, что служба WCF отвечает за построение Xml для передачи в репозиторий.

мне просто интересно, нужно ли контролировать, какие параметры содержатся в XML на среднем уровне или использовать словарь, созданный клиентом, который я затем конвертирую в Xml на среднем уровне?

на данный момент я пошел на последнее - например:

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

однако мне, возможно, придется сделать это первым способом. Е. Г.

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;
          }
      }
}

что рекомендует hivemind?

4 ответов


Если вы должны использовать xml; то вместо того, чтобы передавать словарь, я бы использовал класс, который представляет эти данные, и использовать XmlSerializer чтобы получить его как 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();

Это значительно упрощает управление аргументами, применяемыми к запросам, объектно-ориентированным способом. Это также означает, что вы не должны сделать свой собственный побег из XML...


Как только вы используете решение Боба уборщика, и у вас есть XML.

создайте хранимую процедуру с параметром XML. Затем в зависимости от того, сколько XML у вас есть и что вы с ним делаете, вы можете использовать Xquery или OpenXML для измельчения XML-документа. Извлеките данные и выполните правильное действие. Этот пример является базовым и псевдокодом, но вы должны понять идею.

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

вы можете просто использовать класс сериализации объектов, как это

 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;
        } 
    }

тогда вам не нужно создавать XML вручную, плюс вы можете использовать это с любым элементом, чтобы преобразовать его с помощью XSLT


Я бы поместил код построения xml внутри объекта домена. Таким образом, вы можете просто позвонить obj.GetXML () из веб-службы или слоя данных.