为什么 SQL Server CLR 过程在对 Web 服务的 GetResponse() 调用中挂起

发布于 2024-10-03 14:43:42 字数 2103 浏览 6 评论 0原文

环境:C#、.Net 3.5、Sql Server 2005

我有一种在独立 C# 控制台应用程序项目中工作的方法。它根据数据库中的数据创建 XMLElement,并使用私有方法将其发送到本地网络上的 Web 服务。当在这个测试项目中从VS运行时,它运行在< 5秒。

我将该类复制到 CLR 项目中,构建它,并将其安装在 SQL Server 中(WITH PERMISSION_SET = EXTERNAL_ACCESS)。唯一的区别是我添加用于调试的 SqlContext.Pipe.Send() 调用。

我正在通过从 SSMS 查询窗口使用 EXECUTE 命令一个存储过程(在 CLR 中)来测试它。它永远不会回来。当我在一分钟后停止执行调用时,显示的最后一件事是“使用 http: //服务器名称:53694/odata.svc/Customers/”。关于为什么 GetResponse() 调用在 SQL Server 中执行时不返回的任何想法?

private static string SendPost(XElement entry, SqlString url, SqlString entityName)
{
    // Send the HTTP request
    string serviceURL = url.ToString() + entityName.ToString() + "/";
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceURL);
    request.Method = "POST";
    request.Accept = "application/atom+xml,application/xml";
    request.ContentType = "application/atom+xml";
    request.Timeout = 20000;
    request.Proxy = null;

    using (var writer = XmlWriter.Create(request.GetRequestStream()))
    {
        entry.WriteTo(writer);
    }

    try
    {
        SqlContext.Pipe.Send("Calling GetResponse() using " + request.RequestUri);
        WebResponse response = request.GetResponse();
        SqlContext.Pipe.Send("Back from GetResponse()");

        /*
        string feedData = string.Empty;

        Stream stream = response.GetResponseStream();
        using (StreamReader streamReader = new StreamReader(stream))
        {
            feedData = streamReader.ReadToEnd();
        }
        */

        HttpStatusCode StatusCode = ((HttpWebResponse)response).StatusCode;
        response.Close();

        if (StatusCode == HttpStatusCode.Created /* 201 */ )
        {
            return "Created @ Location= " + response.Headers["Location"];
        }

        return "Creation failed; StatusCode=" + StatusCode.ToString();
    }
    catch (WebException ex)
    {
        return ex.Message.ToString();
    }
    finally
    {
        if (request != null)
            request.Abort();

    }
}

Environment: C#, .Net 3.5, Sql Server 2005

I have a method that works in a stand-alone C# console application project. It creates an XMLElement from data in the database and uses a private method to send it to a web service on our local network. When run from VS in this test project, it runs in < 5 seconds.

I copied the class into a CLR project, built it, and installed it in SQL Server (WITH PERMISSION_SET = EXTERNAL_ACCESS). The only difference is the SqlContext.Pipe.Send() calls that I added for debugging.

I am testing it by using an EXECUTE command one stored procedure (in the CLR) from an SSMS query window. It never returns. When I stop execution of the call after a minute, the last thing displayed is "Calling GetResponse() using http://servername:53694/odata.svc/Customers/". Any ideas as to why the GetResponse() call doesn't return when executing within SQL Server?

private static string SendPost(XElement entry, SqlString url, SqlString entityName)
{
    // Send the HTTP request
    string serviceURL = url.ToString() + entityName.ToString() + "/";
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceURL);
    request.Method = "POST";
    request.Accept = "application/atom+xml,application/xml";
    request.ContentType = "application/atom+xml";
    request.Timeout = 20000;
    request.Proxy = null;

    using (var writer = XmlWriter.Create(request.GetRequestStream()))
    {
        entry.WriteTo(writer);
    }

    try
    {
        SqlContext.Pipe.Send("Calling GetResponse() using " + request.RequestUri);
        WebResponse response = request.GetResponse();
        SqlContext.Pipe.Send("Back from GetResponse()");

        /*
        string feedData = string.Empty;

        Stream stream = response.GetResponseStream();
        using (StreamReader streamReader = new StreamReader(stream))
        {
            feedData = streamReader.ReadToEnd();
        }
        */

        HttpStatusCode StatusCode = ((HttpWebResponse)response).StatusCode;
        response.Close();

        if (StatusCode == HttpStatusCode.Created /* 201 */ )
        {
            return "Created @ Location= " + response.Headers["Location"];
        }

        return "Creation failed; StatusCode=" + StatusCode.ToString();
    }
    catch (WebException ex)
    {
        return ex.Message.ToString();
    }
    finally
    {
        if (request != null)
            request.Abort();

    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深爱成瘾 2024-10-10 14:43:42

问题出在从 XML 创建请求内容的过程中。原件:

using (var writer = XmlWriter.Create(request.GetRequestStream()))
{
    entry.WriteTo(writer);
}

工作替代品:

    using (Stream requestStream = request.GetRequestStream())
    {
        using (var writer = XmlWriter.Create(requestStream))
        {
            entry.WriteTo(writer);
        }
    }

The problem turned out to be the creation of the request content from the XML. The original:

using (var writer = XmlWriter.Create(request.GetRequestStream()))
{
    entry.WriteTo(writer);
}

The working replacement:

    using (Stream requestStream = request.GetRequestStream())
    {
        using (var writer = XmlWriter.Create(requestStream))
        {
            entry.WriteTo(writer);
        }
    }
心作怪 2024-10-10 14:43:42

您需要处置 WebResponse。否则,几次调用后就会超时。

You need to dispose the WebResponse. Otherwise, after a few calls it goes to timeout.

鲸落 2024-10-10 14:43:42

您是在 CLR 中执行此操作时遇到麻烦。你说你是从触发器中调用这个的?这属于应用层。

类似这样的事情就是为什么当 CLR 功能出现时,DBA 非常担心它会如何被滥用。

You are asking for trouble doing this in the CLR. And you say you are calling this from a trigger? This belongs in the application tier.

Stuff like this is why when the CLR functionality came out, DBAs were very concerned about how it would be misused.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文