2009-04-14 99 views
6

我有一个要求将参数作为Xml传递给我的存储过程。将参数作为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; 
      } 
     } 
} 

hivemind推荐什么?

+1

像string.Format这样的东西不适合创建xml,因为必须遵循复杂的转义规则。 XmlWriter对于Dictionary大小写来说是一个合理的选择,但请考虑下面讨论的面向对象的接口。 – 2009-04-15 13:00:19

回答

6
改造它

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

+0

我认为你是正确的感谢。我试图用最少的班级爆炸来迅速完成任务,但我可以看到这将变成一个难以维系的混乱。 – 2009-04-15 13:32:22

+0

@Marc Gravell:你会推荐与VS2010/.Net 4.0相同或不同的方法吗? – FMFF 2012-02-27 18:22:23

+0

@FMFF我试图避免在DB中的XML是诚实的 – 2012-02-27 19:09:52

0

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

+0

我没有发现“GetXml()”应该由“obj”直接调用。它不属于那里。 “obj”的类型应该做它应该做的,除非它是格式化和输出XML的工作。 – Sung 2009-04-14 16:30:55

+0

你可以用extender方法做同样的事情,这样你不用修改域对象 – 2009-04-15 04:18:01

1

你可以只使用一个对象序列化类这样

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

+2

那(MemoryStream,Encoding等)是构建xml的难办法;只是使用StringWriter ...更容易,更高效(无编码,无字节[]等) – 2009-04-15 12:58:30

3

一旦你使用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 
相关问题