Eu fiz uma pesquisa leve sobre esse tópico e gostaria de saber quais são todos os prós e contras ou habilitar/registrar esse .dll específico no SQL Server?
Voltar informações - estamos integrando com um aplicativo de terceiros (não minha decisão, infelizmente) que requer este .dll para alguns outros .dlls. O que eu preciso da função CLR é poder escrever consultas SQL no SSMS e enviar esses dados para a API do aplicativo de terceiros que, por sua vez, faria o carregamento/alterações de dados corretos (inserções e exclusões de/para este aplicativo têm a ser feito através de sua API).
EDIT - talvez eu devesse ter incluído esse detalhe
Ao tentar registrar minha classe c#, obviamente recebi o erro "system.web não registrado blah blah blah" que, por sua vez, levou minha pesquisa sobre esse tópico.
terminar edição
Então, meu enigma é que para poder registrar minha classe C#/.dll, eu tenho que registrar todos os .dll's dependentes, no entanto, com base em minha pesquisa, sei que esse em particular pode ser bastante problemático.
Então, vendo como eu não estou muito familiarizado com as armadilhas fora da minha pesquisa no Google, eu queria saber se um de vocês pode me ajudar a entender como tomar a melhor decisão em relação a isso.
Além disso, o que mais posso adicionar a este post para que seja mais fácil fornecer insights? Eu não tinha certeza de que o código C# era relevante? Eu entendo que isso pode ser um pouco amplo, mas eu esperava que fosse específico o suficiente para não ser sinalizado?
Para ser mais específico sobre o que está ocorrendo aqui (por solicitação de Salomão)
O aplicativo de terceiros usa uma "API" (usada vagamente porque me disseram que não é uma ótima API) para enviar dados de um lado para o outro. Você notará que ele chama uma função Importer que recebe apenas uma tabela de dados ou um arquivo do Excel que converte. Não tenho outra opção, pois a empresa me disse que inserções e exclusões via XML normal são terrivelmente lentas e têm um comportamento inesperado.
A .DLL que faz referência a System.Web é referenciada em minha classe C#, que é necessária para poder enviar dados em primeiro lugar.
Em relação a:
Por que você não seria capaz de usar os métodos que mencionei? Eles já existem no host CLR do SQL Server. Isso é para um serviço da web, certo
Não tenho certeza se sei o suficiente sobre APIs em geral para responder a isso. Eu poderia e só falta o conhecimento e experiência para fazê-lo. Também pode ser devido ao fato de eu ter limitações sobre como posso interagir com essa API específica e não tenho certeza de como essas limitações se aplicam a esses métodos. (Vou investigar mais e ver se posso responder a esta pergunta eu mesmo).
Embora quanto mais eu penso sobre isso, eu poderia criar uma classe "intermediário" que o SQL Server pode chamar, que então chamaria outra classe, que teria todas as referências corretas e isso poderia me fazer passar pela minha situação atual. Eu ainda, no entanto, estou interessado no feedback específico para que eu possa aprender com isso.
aqui está minha classe c#:
using Perfion.Api; -- this .DLL references System.Web.
using Perfion.Api.Import;
using System;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace PerfInsert
{
public static class PerfionInsert
{
public static bool CreateCommand(string tblString, string featureName, string connectionString, string perfionConnectionString, string logFile)
{
StringBuilder logInfo = new StringBuilder();
try
{
var wList = new Regex(@"[^0-9a-z\.\[\]_]#", RegexOptions.IgnoreCase);
if (wList.IsMatch(tblString))
{
logInfo.AppendLine($"{DateTime.UtcNow} - Regex Validation Failed for Table Name!");
return false;
}
using (SqlConnection connection = new SqlConnection(connectionString))
{
var qryString = "SELECT * FROM " + tblString;
using (SqlCommand command = new SqlCommand(qryString, connection))
{
connection.Open();
using (var dataReader = command.ExecuteReader())
using (var dataTable = new DataTable())
{
dataTable.Load(dataReader);
PerfionApi api = new PerfionApi(perfionConnectionString);
Importer importer = new Importer(api.Connection);
importer.Status += (sender, e) => { logInfo.AppendLine($"{DateTime.UtcNow} - {e.Title}"); };
importer.LoadData(dataTable);
importer.ImportToDatabase(featureName);
}
}
}
return true;
}
catch (Exception ex)
{
logInfo.AppendLine($"{DateTime.UtcNow} - {ex.ToString()}");
}
finally
{
File.AppendAllText(logFile, logInfo.ToString());
}
return false;
}
}
}
Que o software de terceiros requer a DLL não parece relevante aqui. Parece que a questão é simplesmente:
Acredito que suas duas melhores opções são:
Se esse processo é tão simples quanto você declarou, e você realmente deseja continuar com
System.Web
, por que não criar um aplicativo de console que faça a consulta e depois publique o que você precisar na API? Se isso precisar ser feito regularmente, ele pode ser agendado no Agendador de Tarefas do Windows ou no SQL Server Agent (por meio de uma etapa de trabalho "Sistema operacional (CmdExec)").Se esse processo for um pouco mais complexo e/ou você precisar da capacidade de fazer essas consultas de maneira mais dinâmica/ad hoc,
System.Web
não será necessário , apenas facilitará parte da codificação. Em vez disso, examine HttpWebRequest e HttpWebResponse . Esses dois estão incluídos noSystem.Net
, que é uma das bibliotecas do .NET Framework com suporte para SQLCLR. A principal diferença é que você precisará construir a solicitação XML manualmente. O mesmo vale para lidar com a resposta. Essa abordagem é mais estável e segura do que importarSystem.Web
.Nessa linha, para quem precisa dessa funcionalidade, mas não quer (ou pode) fazer a codificação dela, escrevi uma biblioteca de funções e procedimentos SQLCLR — SQL# — que inclui um procedimento armazenado, INET_GetWebPages , que implementa esses dois métodos. Embora exista uma versão gratuita, esse procedimento armazenado específico só está disponível na versão completa (ou seja, paga). No entanto, ele lida com uma variedade de opções/cenários, incluindo: configuração de vários cabeçalhos HTTP, autenticação básica opcional, servidor proxy, envio de dados GET vs POST, tratamento de solicitações PUT e opções para reduzir o impacto negativo potencial no desempenho.
SE você está dizendo que está usando a DLL do aplicativo de terceiros para fazer as chamadas de API por meio de seus métodos fornecidos, e é a DLL que faz referência e usa
System.Web
(e não seu código diretamente), então é difícil dizer com total certeza o que todos os impactos são. Mas aqui estão algumas coisas a considerar em relação a essa abordagem:System.Web
não está na lista de Bibliotecas do .NET Framework com suporte para SQLCLR. Isso significa, no mínimo:UNSAFE
. Isso não é inerentemente um problema, mas permite um comportamento que pode facilmente ser um problema. Por exemplo, se qualquer um dos caminhos de código usados por essa DLL de terceiros usar uma variável estática para armazenar informações em cache, se esse valor não for padrão (ou seja, ele pode mudar entre, ou mesmo durante, chamadas para esse código), então você pode entrar em uma condição de corrida, pois o SQL Server usa um domínio de aplicativo compartilhado e todas as sessões compartilham a mesma memória/dados estáticos.Há algum código que precisa ser carregado
UNSAFE
simplesmente por não estar na lista "Suportado" e contém algo que viola a política de segurança, mesmo que você nunca use esse caminho de código específico. Nesses casos, o código pode ser tecnicamente "SEGURO", mas sem ver o código-fonte, você não pode ter certeza. Portanto, você precisa testar, mas o teste requer mais de 1 pessoa clicando algumas vezes: requer várias sessões simultâneas atingindo esse código para ver se existem condições de corrida. Mas há outros cenários que são ainda mais difíceis de testar, como vazamentos de memória devido a exceções. Alguns métodos em bibliotecas com suporte são restritos devido a isso, mas provavelmente ninguém sabe se métodos em bibliotecas sem suporte têm esses problemas porque não acredito que tenham sido testados.Se essa funcionalidade não for voltada para o usuário (ou seja, processo do sistema, funcionalidade interna da empresa etc.), você poderá mitigar a maioria dos problemas (segurança, desempenho, estabilidade) girando uma instância do SQL Server Express e carregando seu projeto lá. Isso isolaria / colocaria em quarentena a funcionalidade SQLCLR não ideal do seu aplicativo de produção. Supondo que você já esteja usando uma conexão externa regular
SqlConnection
(não a conexão interna / confiável), isso não exigirá nenhuma alteração no seu código.O único risco que você não pode mitigar com essa abordagem (ou seja, carregar seu projeto SQLCLR em uma instância isolada) é o potencial de quebra de código se a Microsoft atualizar
System.Web
(ou qualquer uma de suas dependências que são sugadas ao carregá-lo no SQL Server) para ser uma biblioteca de modo misto. Isso pode nunca acontecer, mas se acontecer, você não poderá carregar essa DLL de terceiros, a menos que eles mudem para o uso deHttpWebRequest
, e eles quase não têm motivos para fazer essa alteração.ATUALIZAR
OP Respondeu a uma pergunta relacionada que eles escolheram alterar o tipo de projeto para o aplicativo de console e o agendarão provavelmente com o SQL Agent (mas também podem usar o Agendador de Tarefas do Windows
Posts relacionados (no StackOverflow):