SQL调用Web Service

本文介绍了一个在SQL Server中定义的用户自定义函数,用于通过SOAP协议调用Web服务,展示了如何使用C#进行参数编码、请求构建及响应解析。
using Microsoft.SqlServer.Server;
using System;
using System.Collections;
using System.Data.SqlTypes;
using System.IO;
using System.Net;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

public class UserDefinedFunctionsz
{
    private static readonly Hashtable _xmlNamespaces = new Hashtable();

    [SqlFunction]
    public static string GetDataTable_P(string WSURL, string PName, string Values)
    {
        string result;
        try
        {
            Hashtable hashtable = new Hashtable();
            hashtable["PName"] = PName;
            hashtable["MaterialUse"] = Values;
            XmlDocument xmlDocument = UserDefinedFunctionsz.QuerySoapWebService(WSURL, PName, hashtable);
            result = xmlDocument.InnerText.ToString();
        }
        catch (Exception ex)
        {
            throw ex;
        }
        return result;
    }

    [SqlFunction]
    public static string GetDataTable_V(string WSURL, string PName, string Values)
    {
        string result;
        try
        {
            Hashtable hashtable = new Hashtable();
            hashtable["PName"] = PName;
            hashtable["MaterialUse"] = Values;
            XmlDocument xmlDocument = UserDefinedFunctionsz.QuerySoapWebService(WSURL, PName, hashtable);
            result = xmlDocument.InnerText.ToString();
        }
        catch (Exception ex)
        {
            throw ex;
        }
        return result;
    }

    public static XmlDocument QueryPostWebService(string URL, string MethodName, Hashtable Pars)
    {
        HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(URL + "/" + MethodName);
        httpWebRequest.Method = "POST";
        httpWebRequest.ContentType = "application/x-www-form-urlencoded";
        UserDefinedFunctionsz.SetWebRequest(httpWebRequest);
        byte[] data = UserDefinedFunctionsz.EncodePars(Pars);
        UserDefinedFunctionsz.WriteRequestData(httpWebRequest, data);
        return UserDefinedFunctionsz.ReadXmlResponse(httpWebRequest.GetResponse());
    }
    public static XmlDocument QueryGetWebService(string URL, string MethodName, Hashtable Pars)
    {
        HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(string.Concat(new string[]
        {
            URL,
            "/",
            MethodName,
            "?",
            UserDefinedFunctionsz.ParsToString(Pars)
        }));
        httpWebRequest.Method = "GET";
        httpWebRequest.ContentType = "application/x-www-form-urlencoded";
        UserDefinedFunctionsz.SetWebRequest(httpWebRequest);
        return UserDefinedFunctionsz.ReadXmlResponse(httpWebRequest.GetResponse());
    }
    public static XmlDocument QuerySoapWebService(string URL, string MethodName, Hashtable Pars)
    {
        if (UserDefinedFunctionsz._xmlNamespaces.ContainsKey(URL))
        {
            return UserDefinedFunctionsz.QuerySoapWebService(URL, MethodName, Pars, UserDefinedFunctionsz._xmlNamespaces[URL].ToString());
        }
        return UserDefinedFunctionsz.QuerySoapWebService(URL, MethodName, Pars, UserDefinedFunctionsz.GetNamespace(URL));
    }
    private static XmlDocument QuerySoapWebService(string URL, string MethodName, Hashtable Pars, string XmlNs)
    {
        UserDefinedFunctionsz._xmlNamespaces[URL] = XmlNs;
        HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(URL);
        httpWebRequest.Method = "POST";
        httpWebRequest.ContentType = "text/xml; charset=utf-8";
        httpWebRequest.Headers.Add("SOAPAction", string.Concat(new string[]
        {
            "\"",
            XmlNs,
            XmlNs.EndsWith("/") ? "" : "/",
            MethodName,
            "\""
        }));
        UserDefinedFunctionsz.SetWebRequest(httpWebRequest);
        byte[] data = UserDefinedFunctionsz.EncodeParsToSoap(Pars, XmlNs, MethodName);
        UserDefinedFunctionsz.WriteRequestData(httpWebRequest, data);
        XmlDocument xmlDocument = new XmlDocument();
        XmlDocument xmlDocument2 = new XmlDocument();
        xmlDocument = UserDefinedFunctionsz.ReadXmlResponse(httpWebRequest.GetResponse());
        XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(xmlDocument.NameTable);
        xmlNamespaceManager.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
        string innerXml = xmlDocument.SelectSingleNode("//soap:Body/*/*", xmlNamespaceManager).InnerXml;
        xmlDocument2.LoadXml("<root>" + innerXml + "</root>");
        UserDefinedFunctionsz.AddDelaration(xmlDocument2);
        return xmlDocument2;
    }
    private static string GetNamespace(string URL)
    {
        HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(URL + "?WSDL");
        UserDefinedFunctionsz.SetWebRequest(httpWebRequest);
        WebResponse response = httpWebRequest.GetResponse();
        StreamReader streamReader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.LoadXml(streamReader.ReadToEnd());
        streamReader.Close();
        return xmlDocument.SelectSingleNode("//@targetNamespace").Value;
    }
    private static byte[] EncodeParsToSoap(Hashtable Pars, string XmlNs, string MethodName)
    {
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.LoadXml("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"></soap:Envelope>");
        UserDefinedFunctionsz.AddDelaration(xmlDocument);
        XmlElement xmlElement = xmlDocument.CreateElement("soap", "Body", "http://schemas.xmlsoap.org/soap/envelope/");
        XmlElement xmlElement2 = xmlDocument.CreateElement(MethodName);
        xmlElement2.SetAttribute("xmlns", XmlNs);
        if (Pars != null)
        {
            foreach (string text in Pars.Keys)
            {
                XmlElement xmlElement3 = xmlDocument.CreateElement(text);
                xmlElement3.InnerXml = UserDefinedFunctionsz.ObjectToSoapXml(Pars[text]);
                xmlElement2.AppendChild(xmlElement3);
            }
        }
        xmlElement.AppendChild(xmlElement2);
        xmlDocument.DocumentElement.AppendChild(xmlElement);
        return Encoding.UTF8.GetBytes(xmlDocument.OuterXml);
    }
    private static string ObjectToSoapXml(object o)
    {
        XmlSerializer xmlSerializer = new XmlSerializer(o.GetType());
        MemoryStream memoryStream = new MemoryStream();
        xmlSerializer.Serialize(memoryStream, o);
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.LoadXml(Encoding.UTF8.GetString(memoryStream.ToArray()));
        if (xmlDocument.DocumentElement != null)
        {
            return xmlDocument.DocumentElement.InnerXml;
        }
        return o.ToString();
    }
    private static void SetWebRequest(HttpWebRequest request)
    {
        request.Credentials = CredentialCache.DefaultCredentials;
        request.Timeout = 100000;
    }
    private static void WriteRequestData(HttpWebRequest request, byte[] data)
    {
        request.ContentLength = (long)data.Length;
        Stream requestStream = request.GetRequestStream();
        requestStream.Write(data, 0, data.Length);
        requestStream.Close();
    }
    private static byte[] EncodePars(Hashtable Pars)
    {
        return Encoding.UTF8.GetBytes(UserDefinedFunctionsz.ParsToString(Pars));
    }
    private static string ParsToString(Hashtable Pars)
    {
        StringBuilder stringBuilder = new StringBuilder();
        if (Pars != null)
        {
            foreach (string text in Pars.Keys)
            {
                if (stringBuilder.Length > 0)
                {
                    stringBuilder.Append("&");
                }
                stringBuilder.Append(text + "=" + Pars[text].ToString());
            }
        }
        return stringBuilder.ToString();
    }
    private static XmlDocument ReadXmlResponse(WebResponse response)
    {
        StreamReader streamReader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
        string xml = streamReader.ReadToEnd();
        streamReader.Close();
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.LoadXml(xml);
        return xmlDocument;
    }
    private static void AddDelaration(XmlDocument doc)
    {
        XmlDeclaration newChild = doc.CreateXmlDeclaration("1.0", "utf-8", null);
        doc.InsertBefore(newChild, doc.DocumentElement);
    }
}

 

<think>我们正在讨论SQL Server调用Web Service的方法。根据提供的引用,有两种主要方法:一种是通过sp_OACreate等存储过程直接调用(如引用[1]),另一种是通过自定义函数如fnpbWebServiceInvoke来调用(如引用[2])。 由于用户明确询问实现方法,我将重点整理这两种方法,并给出清晰的步骤和示例。 方法一:使用OLE Automation存储过程(sp_OA*系列) 这种方法利用SQL Server提供的OLE自动化存储过程来发送HTTP请求。但需要注意: - 需要启用Ole Automation Procedures(默认禁用):通过sp_configure 'Ole Automation Procedures', 1 来启用。 - 这种方法在安全性、性能方面存在一定风险,且可能不适合复杂的SOAP请求。 示例步骤(基于引用[1]): 1. 声明变量(包括URL、发送数据、返回文本等) 2. 创建OLE对象:sp_OACreate 'Msxml2.ServerXMLHTTP.3.0' 或 'Msxml2.ServerXMLHTTP.6.0' 3. 打开连接:sp_OAMethod @Object, 'open', 参数包括方法(POST/GET)、URL、异步标志(通常false同步) 4. 设置请求头(如Content-Type) 5. 发送数据:sp_OAMethod @Object, 'send', 数据 6. 获取响应:sp_OAMethod @Object, 'responseText', 输出变量 7. 销毁对象:sp_OADestroy 方法二:使用自定义函数(如引用[2]中的fnpbWebServiceInvoke) 这种方法需要先创建一个CLR函数或者使用T-SQL编写的函数来封装Web Service调用。引用[2]中使用了dbo.fnpbWebServiceInvoke函数,它接受URL、SOAP内容等参数,返回XML结果。 这种方法通常更灵活,但需要预先部署函数。如果用户没有现成函数,可能需要自行创建。创建方法可以通过CLR集成(编写.NET代码)或者使用T-SQL实现HTTP请求(需要启用OLE Automation,但封装后更方便)。 考虑到用户可能没有自定义函数,我将提供两种方法的示例代码。 另外,引用[2]中还展示了如何构建SOAP请求(XML格式)以及如何处理返回结果(字符串替换)。这提示我们,对于SOAP Web Service,我们需要构造符合SOAP标准的XML请求体。 因此,我将分两部分回答: 第一部分:使用OLE Automation存储过程(适用于简单调用,尤其是RESTful API或简单Web Service) 第二部分:使用自定义函数(推荐,但需要额外部署,这里将提供一个简易的自定义函数实现思路,或者建议使用现成的CLR函数) 由于在SQL Server中编写HTTP请求较为繁琐,且需要处理XML,所以对于复杂的SOAP调用,推荐使用CLR集成方法(需要启用CLR,并编写C#代码)。 但由于问题要求展示实现方法,我将展示OLE Automation方法的完整示例,并简要说明如何创建CLR函数。 注意:在SQL Server 2012及以后版本,可以考虑使用内置的JSON功能处理返回的JSON,但XML处理则需要使用T-SQL的XML类型。 下面给出具体的实现步骤和代码示例。 </think>### SQL Server调用Web Service的实现方法 在SQL Server中调用Web Service主要有两种方法,以下分别说明实现步骤和注意事项: #### 方法一:使用OLE Automation存储过程(推荐简单调用) ```sql -- 启用OLE Automation(需sysadmin权限) EXEC sp_configure 'Ole Automation Procedures', 1; RECONFIGURE; DECLARE @ServiceUrl VARCHAR(1000) = 'http://example.com/Service.asmx/Method' DECLARE @PostData VARCHAR(MAX) = 'param1=value1&param2=value2' DECLARE @Object INT DECLARE @ResponseText VARCHAR(8000) -- 创建HTTP对象 EXEC sp_OACreate 'MSXML2.ServerXMLHTTP.6.0', @Object OUT -- 配置请求 EXEC sp_OAMethod @Object, 'Open', NULL, 'POST', @ServiceUrl, 'false' EXEC sp_OAMethod @Object, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded' EXEC sp_OAMethod @Object, 'send', NULL, @PostData -- 获取响应 EXEC sp_OAMethod @Object, 'responseText', @ResponseText OUTPUT -- 清理资源 EXEC sp_OADestroy @Object SELECT @ResponseText AS API_Response ``` **特点**: 1. 使用内置存储过程`sp_OACreate`/`sp_OAMethod` 2. 支持GET/POST方法 3. 需启用`Ole Automation Procedures`配置[^1] 4. 适用于简单HTTP请求 #### 方法二:使用CLR集成(推荐复杂SOAP调用) ```sql -- 步骤1:创建C# CLR存储过程 /* [Microsoft.SqlServer.Server.SqlProcedure] public static void CallWebService(SqlString url, SqlString soapXml) { using (WebClient client = new WebClient()) { client.Headers.Add("Content-Type", "text/xml; charset=utf-8"); string response = client.UploadString(url.Value, soapXml.Value); SqlContext.Pipe.Send(response); } } */ -- 步骤2:部署程序集后调用 DECLARE @SOAP XML = ' <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <Method xmlns="http://tempuri.org/"> <param>value</param> </Method> </soap:Body> </soap:Envelope>' EXEC dbo.CallWebService @url = 'http://example.com/SoapService.asmx', @soapXml = @SOAP ``` **优势**: 1. 支持复杂SOAP头和WS-Security 2. 性能优于OLE Automation 3. 可直接处理XML响应[^2] #### 关键注意事项 1. 🔒 **权限配置**: - OLE方式需开启`sp_configure` - CLR方式需启用`clr enabled`配置 2. ️ **错误处理**: ```sql DECLARE @Error INT EXEC sp_OAGetErrorInfo @Object, @Error OUT IF @Error <> 0 PRINT 'Error: ' + CAST(@Error AS VARCHAR) ``` 3. 🔄 **异步调用**: 在`Open`方法第三个参数设为`true`可实现异步请求 4. 📦 **数据处理**: - 使用`CAST(@ResponseText AS XML)`解析XML响应 - JSON响应需SQL Server 2016+版本 建议简单调用使用OLE方法,复杂SOAP服务推荐CLR集成方案以获得更好的类型安全和性能。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值