Почему процедура CLR SQL Server зависает при вызове GetResponse() веб-службы

Среда: C#, .Net 3.5, Sql Server 2005

У меня есть метод, который работает в отдельном проекте консольного приложения C#. Он создает XMLElement из данных в базе данных и использует закрытый метод для отправки его в веб-службу в нашей локальной сети. При запуске из VS в этом тестовом проекте он выполняется за ‹ 5 секунд.

Я скопировал класс в проект CLR, построил его и установил в SQL Server (WITH PERMISSION_SET = EXTERNAL_ACCESS). Единственное отличие — вызовы SqlContext.Pipe.Send(), которые я добавил для отладки.

Я тестирую его, используя одну хранимую процедуру команды EXECUTE (в среде CLR) из окна запроса SSMS. Он никогда не возвращается. Когда я прекращаю выполнение вызова через минуту, последнее, что отображается, это «Вызов GetResponse() с использованием http://servername: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();

    }
}

person Mark Freeman    schedule 19.11.2010    source источник


Ответы (3)


Проблема оказалась в создании содержимого запроса из 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);
        }
    }
person Mark Freeman    schedule 23.11.2010

Вам нужно удалить файл WebResponse. В противном случае после нескольких вызовов происходит тайм-аут.

person Duray Akar    schedule 05.09.2017

Вы просите проблемы с этим в CLR. И вы говорите, что вызываете это из триггера? Это относится к уровню приложений.

Вот почему, когда появились функциональные возможности CLR, администраторы баз данных были очень обеспокоены тем, как они могут быть использованы не по назначению.

person Randy Knight    schedule 19.11.2010
comment
Я не знаю, как что-либо на прикладном уровне вызывается при срабатывании триггера базы данных. - person Mark Freeman; 22.11.2010