Eu gostaria de usar o código que desenvolvi em C # CLR para ser usado em todos os bancos de dados do sistema, para não precisar definir cada um como confiável e ativar o CLR e manter um monte do mesmo código dentro de cada um .
Existe uma maneira melhor de fazer isso do ponto de vista administrativo e de segurança? As funções CLR são muito básicas, como quebra de string, validação de e-mail, url en/decode, base64 e etc. Gostaria que apenas o esquema dbo em cada banco de dados pudesse acessar as funções.
- Existe alguma maneira simples de fazer isso?
- Também não estou claro se a dll CLR está incorporada e se eu mover o banco de dados, ele acompanha ou devo mover a dll também.
Obrigado
Em nossa empresa, temos essa configuração exata. Quando você cria um assembly CLR, uma representação binária do assembly é armazenada no banco de dados em que você o criou. Isso permite que você o leve com você (e até mesmo o script) caso mova o banco de dados a qualquer momento.
Alguns meses atrás, nosso data center foi inundado - enchendo vários servidores de água. Quando os reconstruí, usei apenas os backups do banco de dados que foram feitos na noite anterior. Até agora não tivemos problemas.. (toque na madeira!)
Não tenho certeza se isso é a coisa certa a fazer do ponto de vista da segurança, mas a maneira como concedemos acesso aos processos CLR, etc., é criar uma função no banco de dados compartilhado e adicionar usuários de outros bancos de dados a essa função. A função é então concedida para executar no processo CLR.
Pode haver problemas de acesso se o CLR estiver tentando fazer coisas como acessar recursos fora do banco de dados que está contido, mas você pode definir a permissão no assembly ao criá-lo. O link abaixo tem muito mais informações sobre permissões do que posso explicar aqui:
http://msdn.microsoft.com/en-us/library/ms345101.aspx
Espero que isso ajude você.
O binário do assembly é armazenado como um blob no banco de dados, portanto, é carregado para onde quer que o banco de dados vá. O CLR é ativado apenas na instância - não há configurações específicas do banco de dados para isso.
De qualquer forma, por que você está tentando fazer isso?
(Não estou tentando ser argumentativo; só quero ouvir os motivos envolvidos, porque talvez o problema possa ser resolvido de uma maneira diferente que atenda às suas necessidades.)
Não há como fazer isso facilmente, exceto colocar o assembly em um banco de dados compartilhado.
Dito isso, acho vantajoso adotar a arquitetura centrada no banco de dados, a menos que haja uma situação específica que tenha motivos muito convincentes para centralizar. A razão é que colocar o assembly (ou qualquer coisa) fora do banco de dados cria uma dependência em seu ambiente. Esta é precisamente a abordagem oposta que a Microsoft está construindo com os bancos de dados independentes a partir do SQL Server 2012.
Quando você começa a precisar usar recursos como replicação ou clustering, essa dependência pode adicionar uma enorme complexidade à implantação, mas também à solução de problemas e aos procedimentos de failover.
Essa arquitetura é muito menos óbvia para as pessoas não familiarizadas com o sistema (ou seja, é menos autodescobrível e menos autodocumentável).
Se você precisar de segurança diferente em bancos de dados diferentes, ou qualquer coisa que envolva variação, você está em um mundo de dor.
Se esses bancos de dados forem implantados para os clientes (parece que não, mas vou dizer isso para completar), isso aumenta a complexidade do procedimento de implantação, manutenção e solução de problemas.
Como todos os bancos de dados compartilhariam esse código, se algum bug fosse introduzido (ou corrigido!), isso poderia interromper todos os aplicativos que dependem dos bancos de dados. Testes de unidade abrangentes seriam uma necessidade absoluta.
Se você tiver vários bancos de dados que precisam da mesma funcionalidade, existem outras maneiras de reduzir a quantidade de duplicação envolvida, o que suponho ser o objetivo do exercício. Mesmo um assembly CLR bastante complexo não ocupará muito espaço de armazenamento físico em comparação com os dados no próprio banco de dados (quase sempre), então não vejo isso como um argumento válido, a menos que você tenha literalmente milhares de pequenos bancos de dados que precisam disso conjunto.
O que você pode fazer é modificar outras partes do procedimento de implantação desses bancos de dados para reduzir a duplicação de origem. Por exemplo, crie e implante o assembly do local comum do código CLR no controle do código-fonte. Ou crie um script que implanta o mesmo assembly nos bancos de dados. Automatize essa parte das coisas o máximo possível e não será grande coisa.
Concordo que o que estou sugerindo é uma troca, porque ainda haverá alguma duplicação, mas isso deve ser equilibrado com os aspectos negativos envolvidos na implementação de uma arquitetura que não segue o padrão prescrito. Só você pode decidir o que é certo para o seu ambiente.
Como as outras duas respostas afirmam corretamente, os assemblies são carregados em um banco de dados específico e não são de todo o sistema (embora eu tenha quase certeza de que o
assembly_id
valor é exclusivo de todo o sistema). Isso significa que eles são copiados e restaurados com cada banco de dados no qual são carregados.Além disso, a configuração
enabled
/disabled
deCLR Integration
(viasp_configure
) abrange todo o sistema. Como observação, essa configuração é apenas para a funcionalidade CLR criada pelo usuário ; Em um sentido geral, o CLR está sempre ativado, pois certas funcionalidades integradas dependem dele.Dito isso, embora as outras duas respostas aqui façam pontos válidos, esses pontos não são específicos do SQLCLR e não há menção aos fatores na tomada dessa decisão que são específicos do código SQLCLR. Há problemas de memória a serem considerados se você implantar código em cada banco de dados individual (supondo que você tenha muitos bancos de dados), possíveis problemas de contenção de recursos, possíveis problemas relacionados à segurança, etc.
Forneci o que deveria ser uma lista abrangente de coisas a serem lembradas, especificamente para o código SQLCLR, ao decidir entre um banco de dados centralizado versus implantação de banco de dados individual. Em vez de duplicar a lista aqui, consulte a seguinte resposta (também aqui no DBA.SE):
Como usar melhor a função CLR do ponto de vista do desempenho (repita dentro de cada banco de dados ou tenha uma função geral)?
Além disso, em uma nota relacionada, eu questionaria por que qualquer banco de dados está sendo definido como
TRUSTWORTHY ON
. A funcionalidade observada na pergunta (ou seja, "separadores de string, validação de e-mail, url en/decode, base64, etc") é possível em umSAFE
Assembly. Você não deve usar os valoresEXTERNAL_ACCESS
ouUNSAFE
perission_set, a menos que seja absolutamente necessário. E se for necessário para um certo número de funções, elas devem estar em um Assembly separado que contenha apenasSAFE
código, de modo que quaisquer funções escalares que não façam acesso a dados e sejam marcadas comoIsDeterministic = true
possam fazer uso do benefício de desempenho de serem capaz de participar de planos paralelos.