Perché la procedura di SQL Server CLR blocco a GetResponse () chiamata al servizio web
-
26-09-2019 - |
Domanda
Ambiente: C #, .Net 3.5, SQL Server 2005
Ho un metodo che funziona in un progetto stand-alone C # applicazione console. Si crea un XmlElement dai dati nel database e utilizza un metodo privato per inviarlo a un servizio Web sulla nostra rete locale. Quando viene eseguito da VS in questo progetto di test, viene eseguito in <5 secondi.
Ho copiato la classe in un progetto CLR, costruito e installato in SQL Server (CON PERMISSION_SET = EXTERNAL_ACCESS). L'unica differenza è lo SqlContext.Pipe.Send () chiama che ho aggiunto per il debug.
Sono test che utilizzando un comando EXECUTE una stored procedure (nel CLR) dalla finestra di uno SSMS query. E non ritorna mai. Quando mi fermo l'esecuzione della chiamata dopo un minuto, l'ultima cosa che appare è "Calling GetResponse () utilizzando http: //servername:53694/odata.svc/Customers/ ". Tutte le idee sul perché il () chiamata GetResponse non restituisce quando si esegue in 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();
}
}
Soluzione
Il problema si è rivelato essere la creazione del contenuto richiesta del XML. L'originale:
using (var writer = XmlWriter.Create(request.GetRequestStream()))
{
entry.WriteTo(writer);
}
La sostituzione di lavoro:
using (Stream requestStream = request.GetRequestStream())
{
using (var writer = XmlWriter.Create(requestStream))
{
entry.WriteTo(writer);
}
}
Altri suggerimenti
È necessario smaltire il WebResponse. In caso contrario, dopo un paio di telefonate va a timeout.
Si cerca di guai fare questo in CLR. E tu dici che si sta chiamando questo da un grilletto? Appartiene nello strato applicativo.
Roba come questo è il motivo per cui quando la funzionalità CLR è uscito, gli amministratori di database sono stati molto preoccupati per come sarebbe essere oggetto di abuso.