【问题标题】:Passing Parameters as Xml to a Stored Procedure将参数作为 Xml 传递给存储过程
【发布时间】:2010-10-19 09:14:12
【问题描述】:

我需要将参数作为 Xml 传递给我的存储过程。

我在中间层有一个 WCF 服务,它调用我的数据层,然后将请求转发到适当的存储过程。

设计是WCF服务负责构建Xml传递给Repository。

我只是想知道是要控制中间层的 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;
          }
      }
}

主脑推荐什么?

【问题讨论】:

  • string.Format 之类的东西不适合创建 xml,因为必须遵循复杂的转义规则。 XmlWriter 将是 Dictionary 案例的合理替代方案,但请考虑下面讨论的面向对象方法。

标签: c# xml tsql soa


【解决方案1】:

如果必须使用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 转义...

【讨论】:

  • 我认为你是对的,谢谢。我试图以最小的班级爆炸来让它快速发展,但我可以看到它会变成这样一个无法维护的混乱。
  • @Marc Gravell:您会推荐与 VS2010/.Net 4.0 相同或不同的方法吗?
  • @FMFF 老实说,我尽量避免在数据库中使用 XML
【解决方案2】:

一旦您使用 Bob The Janitor 的解决方案并拥有您的 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

【讨论】:

    【解决方案3】:

    你可以像这样使用对象序列化类

     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 对其进行转换

    【讨论】:

    • 那(MemoryStream、Encoding 等)是构建 xml 的艰难方式;只需使用 StringWriter... 更简单、更高效(无编码、无字节 [] 等)
    【解决方案4】:

    我会将 xml 构造代码放在域对象中。这样,您就可以从 Web 服务或数据层调用 obj.GetXML()。

    【讨论】:

    • 我没有发现“GetXml()”应该由“obj”直接调用。它不属于那里。 “obj”的类型应该做它应该做的事情,除非它是格式化和输出 XML 的工作。
    • 你可以用一个扩展方法来做同样的事情,这样你就不会修改域对象
    猜你喜欢
    • 2023-03-22
    • 1970-01-01
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 2016-04-05
    相关资源
    最近更新 更多