Demonstra Passo a passo: Criação de um personalizado código análise regra Assembly estático para SQL
Este tópico passo a passo demonstra as etapas usadas para criar uma regra de análise de código de SQL. A regra criada nesta explicação é usada para evitar a instruções WAITFOR DELAY em procedimentos armazenados, disparadores e funções.
Esta explicação passo a passo, você irá criar uma regra personalizada para Transact-SQL a análise estática de código usando os seguintes processos:
Criar uma biblioteca de classe, habilitar a assinatura para o projeto e adicionar as referências necessárias.
Crie duas classes do auxiliar C#.
Crie uma classe de regra personalizada C#.
Crie um arquivo XML que é usado para registrar o assembly.
Copiar o arquivo DLL e o XML resultante criar para o diretório de extensões para registrá-lo.
Se a nova regra de análise de código está em vigor.
Pré-requisitos
Você deve ter um Visual Studio Premium ou Visual Studio Ultimate instalado para concluir esta explicação passo a passo.
Criando uma regra de análise de código personalizado para SQL
Primeiro, você irá criar uma biblioteca de classe.
Para criar uma biblioteca de classe
Sobre o arquivo menu, clique em novo e, em seguida, clique em projeto.
No Novo projeto caixa de diálogo, na lista de Modelos instalados, clique em Visual C#.
No painel de detalhes, selecione Biblioteca de classe.
No nome caixa de texto, digite SampleRules e clique em OK.
Em seguida, você se conectará o projeto.
Para ativar a autenticação para o projeto.
Com o SampleRules do nó do projeto selecionado no Solution Explorer, da projeto menu, clique em Propriedades (ou o botão direito do mouse no nó do projeto em Solution Explorer e, em seguida, clique em Propriedades).
Clique na guia Signing.
Marque a caixa de seleção Sign the assembly.
Especifique um novo arquivo de chave. Na lista suspensa Choose a strong name key file, selecione <New...>.
O Create Strong Name Key caixa de diálogo aparece. Para obter mais informações, consulte Criar a caixa de diálogo de chave de nome forte.
No Create Strong Name Key caixa de diálogo, digite SampleRulesKey na nome caixa de texto para o novo arquivo de chave. Não é necessário fornecer uma senha para esta explicação passo a passo. Para obter mais informações, consulte Gerenciando Assinatura de Assembly e Manifesto.
Em seguida, você adicionará as referências necessárias ao projeto.
Para adicionar referências aplicáveis ao projeto
Em Solution Explorer, selecione o projeto SampleRules.
No menu Project, escolha Add Reference.
A caixa de diálogo Add Reference é aberta. Para obter mais informações, consulte Como: Adicionar ou remover referências no Visual Studio.
Selecione o .NET guia.
No Nome do componente coluna, localize os seguintes componentes:
Observação Para selecionar vários componentes, pressione e mantenha a tecla CTRL enquanto clique em cada um deles.
Clique em OK depois que você tiver selecionado todos os componentes necessários.
As referências selecionadas aparecerão sob o referências o nó do projeto no Solution Explorer.
Criar a regra de análise de código personalizado suporte às Classes
Antes de criar a classe para a regra propriamente dito, você irá adicionar uma classe de visitante e uma classe auxiliar para o projeto.
Dica
Essas classes podem ser úteis para criar regras personalizadas adicionais.
A primeira classe, você deve definir é a classe WaitForDelayVisitor, derivada de TSqlConcreteFragmentVisitor . Essa classe fornece acesso às instruções WAITFOR DELAY no modelo.
Para definir a classe WaitForDelayVisitor
Em Solution Explorer, selecione o projeto SampleRules.
No menu Project selecione Add Class.
O Add New Item caixa de diálogo aparece.
No nome caixa de texto, digite WaitForDelayVisitor.cs e clique o Add botão.
O arquivo de WaitForDelayVisitor.cs é adicionado ao projeto no Solution Explorer.
Abra o arquivo WaitForDelayVisitor.cs e atualizar o conteúdo para coincidir com o código a seguir:
using System.Collections.Generic; using Microsoft.Data.Schema.ScriptDom.Sql; namespace SampleRules { class WaitForDelayVistor { } }
Na declaração da classe, alterar o modificador de acesso interno e derive a classe de TSqlConcreteFragmentVisitor:
internal class WaitForDelayVisitor : TSqlConcreteFragmentVisitor { }
Adicione o seguinte código para definir a variável de membro da lista:
private List<WaitForStatement> _waitForDelayStatments;
Defina o construtor da classe, adicionando o seguinte código:
#region ctor public WaitForDelayVisitor() { _waitForDelayStatments = new List<WaitForStatement>(); } #endregion
Defina a propriedade somente leitura do WaitForDelayStatements, adicionando o seguinte código:
#region properties public List<WaitForStatement> WaitForDelayStatements { get { return _waitForDelayStatments; } } #endregion
Substitua o método de ExplicitVisit, adicionando o seguinte código:
#region overrides public override void ExplicitVisit(WaitForStatement node) { // We are only interested in WAITFOR DELAY occurrences if (node.WaitForOption == WaitForOption.Delay) { _waitForDelayStatments.Add(node); } } #endregion
Este método visitas as declarações de WAITFOR no modelo e adiciona aqueles que têm a opção atraso especificada à lista de instruções de WAITFOR DELAY. A classe de chave referenciada aqui é WaitForStatement.
Sobre o arquivo menu, clique em Salvar.
A segunda classe é SqlRuleUtils.cs, que contém alguns métodos de utilitário que serão usados pela classe de regra de análise de código personalizada que você criará posteriormente nesta explicação, na criar a classe de regra de análise de código personalizado seção. Esses métodos incluem o seguinte:
GetElementName usado para obter o nome de escape, totalmente qualificado de um elemento de modelo
UpdateProblemPosition usado para calcular as informações de linha e coluna.
ReadFileContent usado para ler o conteúdo de um arquivo.
GetElementSourceFile usado para adquirir o arquivo de origem.
ComputeLineColumn usado para converter o deslocamento de ScriptDom de linha e coluna em arquivos de script.
Para adicionar o arquivo de SqlRuleUtils.cs para o projeto.
Em Solution Explorer, selecione o projeto SampleRules.
No menu Project selecione Add Class.
O Add New Item caixa de diálogo aparece.
No nome caixa de texto, digite SqlRuleUtils.cs e clique o Add botão.
O arquivo de SqlRuleUtils.cs é adicionado ao projeto no Solution Explorer.
Abra o arquivo SqlRuleUtils.cs e adicione o seguinte usando as instruções no arquivo:
using System; using System.Diagnostics; using System.IO; using Microsoft.Data.Schema.SchemaModel; using Microsoft.Data.Schema.Sql.SchemaModel; using Microsoft.Data.Schema.StaticCodeAnalysis; using Microsoft.Data.Schema; namespace SampleRules { }
Na declaração da classe SqlRuleUtils, altere o modificador de acesso ao membro estático público:
public static class SqlRuleUtils { }
Adicione o seguinte código para criar o método GetElementName, que usa SqlSchemaModel e ISqlModelElement como parâmetros de entrada:
/// <summary> /// Get escaped fully qualified name of a model element /// </summary> /// <param name="sm">schema model</param> /// <param name="element">model element</param> /// <returns>name of the element</returns> public static string GetElementName(SqlSchemaModel sm, ISqlModelElement element) { return sm.DatabaseSchemaProvider.UserInteractionServices.GetElementName(element, ElementNameStyle.EscapedFullyQualifiedName); }
Adicione o seguinte código para criar o método ReadFileContent:
/// <summary> /// Read file content from a file. /// </summary> /// <param name="filePath"> file path </param> /// <returns> file content in a string </returns> public static string ReadFileContent(string filePath) { // Verify that the file exists first. if (!File.Exists(filePath)) { Debug.WriteLine(string.Format("Cannot find the file: '{0}'", filePath)); return string.Empty; } string content; using (StreamReader reader = new StreamReader(filePath)) { content = reader.ReadToEnd(); reader.Close(); } return content; }
Adicione o seguinte código para criar o método GetElementSourceFile, que usa IModelElement como um parâmetro de entrada e String para recuperar o nome de arquivo. O método projeta o IModelElement como IScriptSourcedModelElement e, em seguida, usa ISourceInformation determinar o caminho do arquivo de script do elemento de modelo.
/// <summary> /// Get the corresponding script file path from a model element. /// </summary> /// <param name="element">model element</param> /// <param name="fileName">file path of the scripts corresponding to the model element</param> /// <returns></returns> private static Boolean GetElementSourceFile(IModelElement element, out String fileName) { fileName = null; IScriptSourcedModelElement scriptSourcedElement = element as IScriptSourcedModelElement; if (scriptSourcedElement != null) { ISourceInformation elementSource = scriptSourcedElement.PrimarySource; if (elementSource != null) { fileName = elementSource.SourceName; } } return String.IsNullOrEmpty(fileName) == false; }
Adicione o seguinte código para criar o método ComputeLineColumn:
/// This method converts offset from ScriptDom to line\column in script files. /// A line is defined as a sequence of characters followed by a carriage return ("\r"), /// a line feed ("\n"), or a carriage return immediately followed by a line feed. public static bool ComputeLineColumn(string text, Int32 offset, Int32 length, out Int32 startLine, out Int32 startColumn, out Int32 endLine, out Int32 endColumn) { const char LF = '\n'; const char CR = '\r'; // Setting the initial value of line and column to 0 since VS auto-increments by 1. startLine = 0; startColumn = 0; endLine = 0; endColumn = 0; int textLength = text.Length; if (offset < 0 || length < 0 || offset + length > textLength) { return false; } for (int charIndex = 0; charIndex < length + offset; ++charIndex) { char currentChar = text[charIndex]; Boolean afterOffset = charIndex >= offset; if (currentChar == LF) { ++endLine; endColumn = 0; if (afterOffset == false) { ++startLine; startColumn = 0; } } else if (currentChar == CR) { // CR/LF combination, consuming LF. if ((charIndex + 1 < textLength) && (text[charIndex + 1] == LF)) { ++charIndex; } ++endLine; endColumn = 0; if (afterOffset == false) { ++startLine; startColumn = 0; } } else { ++endColumn; if (afterOffset == false) { ++startColumn; } } } return true; }
Adicione o seguinte código para criar o método UpdateProblemPosition, que usa DataRuleProblem como um parâmetro de entrada:
/// <summary> /// Compute the start Line/Col and the end Line/Col to update problem info /// </summary> /// <param name="problem">problem found</param> /// <param name="offset">offset of the fragment having problem</param> /// <param name="length">length of the fragment having problem</param> public static void UpdateProblemPosition(DataRuleProblem problem, int offset, int length) { if (problem.ModelElement != null) { String fileName = null; int startLine = 0; int startColumn = 0; int endLine = 0; int endColumn = 0; bool ret = GetElementSourceFile(problem.ModelElement, out fileName); if (ret) { string fullScript = ReadFileContent(fileName); if (fullScript != null) { if (ComputeLineColumn(fullScript, offset, length, out startLine, out startColumn, out endLine, out endColumn)) { problem.FileName = fileName; problem.StartLine = startLine + 1; problem.StartColumn = startColumn + 1; problem.EndLine = endLine + 1; problem.EndColumn = endColumn + 1; } else { Debug.WriteLine("Could not compute line and column"); } } } } }
Sobre o arquivo menu, clique em Salvar.
Em seguida, você pode adicionar um arquivo de recurso que irá definir o nome da regra, a descrição da regra e a categoria na qual a regra serão exibidos na interface de configuração de regra.
Para adicionar um arquivo de recurso e três seqüências de recursos
Em Solution Explorer, selecione o projeto SampleRules.
No menu Project, selecione Add New Item.
O Add New Item caixa de diálogo aparece.
Na lista de Modelos instalados, clique em Geral.
No painel de detalhes, clique em O arquivo de recursos.
Em nome, tipo SampleRuleResource.resx.
O editor de recursos for exibida, sem recursos ainda definidos.
Defina três seqüências de recursos, como segue:
Nome
Valor
AvoidWaitForDelay_ProblemDescription
A instrução de WAITFOR DELAY foi encontrada em {0}.
AvoidWaitForDelay_RuleName
Evite usar instruções de WaitFor Delay em procedimentos armazenados, funções e disparadores.
CategorySamples
SamplesCategory
Sobre o arquivo menu, clique em Salvar SampleRuleResource.resx.
Em seguida, você define uma classe que faz referência os recursos no arquivo de recurso usadas pelo Visual Studio para exibir informações sobre a regra na interface de usuário.
Para definir a classe SampleConstants
Em Solution Explorer, selecione o projeto SampleRules.
No menu Project selecione Add Class.
O Add New Item caixa de diálogo aparece.
No nome caixa de texto, digite SampleRuleConstants.cs e clique o Add botão.
O arquivo de SampleRuleConstants.cs é adicionado ao projeto no Solution Explorer.
Abra o arquivo SampleRuleConstants.cs e adicione o seguinte usando as instruções no arquivo:
namespace SampleRules { internal class SampleConstants { public const string NameSpace = "SamplesRules"; public const string ResourceBaseName = "SampleRules.SampleRuleResource"; public const string CategorySamples = "CategorySamples"; public const string AvoidWaitForDelayRuleId = "SR1004"; public const string AvoidWaitForDelay_RuleName = "AvoidWaitForDelay_RuleName"; public const string AvoidWaitForDelay_ProblemDescription = "AvoidWaitForDelay_ProblemDescription"; } }
Sobre o arquivo menu, clique em Salvar.
Criando a classe de regra de análise de código personalizado
Agora que você adicionou as classes auxiliares que usará a regra de análise de código personalizada, você criará uma classe de regra personalizada e o nome AvoidWaitForDelayRule. A regra personalizada de AvoidWaitForDelayRule será usada para ajudar a evitar declarações de WAITFOR DELAY em procedimentos armazenados, disparadores e funções de desenvolvedores de banco de dados.
Para criar a classe AvoidWaitForDelayRule
Em Solution Explorer, selecione o projeto SampleRules.
Sobre o projeto menu, selecione Nova pasta.
Uma nova pasta aparece em Solution Explorer. Nomeie a pasta AvoidWaitForDelayRule.
Em Solution Explorer, verifique se a pasta AvoidWaitForDelayRule é selecionada.
No menu Project selecione Add Class.
O Add New Item caixa de diálogo aparece.
No nome caixa de texto, digite AvoidWaitForDelayRule.cs e clique o Add botão.
O arquivo AvoidWaitForDelayRule.cs é adicionado à pasta do projeto AvoidWaitForDelayRule em Solution Explorer.
Abra o arquivo AvoidWaitForDelayRule.cs e adicione o seguinte usando as instruções no arquivo:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using Microsoft.Data.Schema.Extensibility; using Microsoft.Data.Schema.SchemaModel; using Microsoft.Data.Schema.ScriptDom.Sql; using Microsoft.Data.Schema.Sql.SchemaModel; using Microsoft.Data.Schema.Sql; using Microsoft.Data.Schema.StaticCodeAnalysis; namespace SampleRules { public class AvoidWaitForDelayRule { } }
Observação Você deve alterar o nome do namespace de SampleRules.AvoidWaitForDelayRule para SampleRules.
Na declaração da classe AvoidWaitForDelayRule, altere o modificador de acesso ao público:
/// <summary> /// This is a SQL rule which returns a warning message /// whenever there is a WAITFOR DELAY statement appears inside a subroutine body. /// This rule only applies to SQL stored procedures, functions and triggers. /// </summary> public class AvoidWaitForDelayRule
Derivar a classe AvoidWaitForDelayRule a StaticCodeAnalysisRule classe base:
public class AvoidWaitForDelayRule : StaticCodeAnalysisRule
Adicionar o DatabaseSchemaProviderCompatibilityAttribute, DataRuleAttribute, e SupportedElementTypeAttribute para sua turma. Para obter mais informações sobre compatibilidade de extensão do recurso, consulte Estender os recursos de banco de dados de Visual Studio.
[DatabaseSchemaProviderCompatibility(typeof(SqlDatabaseSchemaProvider))] [DataRuleAttribute( SampleConstants.NameSpace, SampleConstants.AvoidWaitForDelayRuleId, SampleConstants.ResourceBaseName, SampleConstants.AvoidWaitForDelay_RuleName, SampleConstants.CategorySamples, DescriptionResourceId = SampleConstants.AvoidWaitForDelay_ProblemDescription)] [SupportedElementType(typeof(ISqlProcedure))] [SupportedElementType(typeof(ISqlTrigger))] [SupportedElementType(typeof(ISqlFunction))] public class AvoidWaitForDelayRule : StaticCodeAnalysisRule
O DataRuleAttribute Especifica as informações exibidas no Visual Studio Quando você configura regras de análise do banco de dados código. O SupportedElementTypeAttribute define os tipos de elementos aos quais esta regra será aplicada. Nesse caso, a regra será aplicada para funções, procedimentos armazenados e disparadores.
Adicionar uma substituição para o Analyze método, que usa DataRuleSetting e DataRuleExecutionContext como parâmetros de entrada. Esse método retorna uma lista de possíveis problemas.
O método obtém o IModelElement e TSqlFragment do parâmetro de contexto. O SqlSchemaModel e ISqlModelElement são obtidas do elemento de modelo. Então, a classe WaitForDelayVisitor é usada para obter uma lista de todos os extratos de WAITFOR DELAY no modelo.
Para cada WaitForStatement nessa lista, um DataRuleProblem é criado.
#region Overrides /// <summary> /// Analyze the model element /// </summary> public override IList<DataRuleProblem> Analyze(DataRuleSetting ruleSetting, DataRuleExecutionContext context) { List<DataRuleProblem> problems = new List<DataRuleProblem>(); IModelElement modelElement = context.ModelElement; // this rule does not apply to inline table-valued function // we simply do not return any problem if (modelElement is ISqlInlineTableValuedFunction) { return problems; } // casting to SQL specific SqlSchemaModel sqlSchemaModel = modelElement.Model as SqlSchemaModel; Debug.Assert(sqlSchemaModel!=null, "SqlSchemaModel is expected"); ISqlModelElement sqlElement = modelElement as ISqlModelElement; Debug.Assert(sqlElement != null, "ISqlModelElement is expected"); // Get ScriptDom for this model element TSqlFragment sqlFragment = context.ScriptFragment as TSqlFragment; Debug.Assert(sqlFragment != null, "TSqlFragment is expected"); // visitor to get the ocurrences of WAITFOR DELAY statements WaitForDelayVisitor visitor = new WaitForDelayVisitor(); sqlFragment.Accept(visitor); List<WaitForStatement> waitforDelayStatements = visitor.WaitForDelayStatements; // Create problems for each WAITFOR DELAY statement found foreach (WaitForStatement waitForStatement in waitforDelayStatements) { DataRuleProblem problem = new DataRuleProblem(this, String.Format(CultureInfo.CurrentCulture, this.RuleProperties.Description, SqlRuleUtils.GetElementName(sqlSchemaModel, sqlElement)), sqlElement); SqlRuleUtils.UpdateProblemPosition(problem, waitForStatement.StartOffset, waitForStatement.FragmentLength); problems.Add(problem); } return problems; } #endregion
Sobre o arquivo menu, clique em Salvar.
Em seguida, você criará o projeto.
Para construir o projeto.
- Do Build menu, clique em Build Solution.
Em seguida, você irá coletar informações de assembly geradas no projeto, incluindo a versão, cultura e PublicKeyToken.
Para coletar informações de assembly
No Exibir menu, clique em Other Windowse em seguida, clique em Janela de comando para abrir o comando janela.
No comando janela, digite o seguinte código. Para FilePath, substitua o caminho e o nome do arquivo. dll de compilado. Inclua as aspas ao redor do caminho e nome de arquivo.
Observação Por padrão, FilePath é Projects\SampleRules\SampleRules\bin\Debug\YourDLL ou Projects\SampleRules\SampleRules\bin\Release\YourDLL.
? System.Reflection.Assembly.LoadFrom(@"FilePath")
Pressione ENTER. A linha deverá ser semelhante a seguinte com seu PublicKeyToken específico:
"SampleRules, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nnnnnnnnnnnnnnnn"
Notificar ou copiar essas informações de assembly; ele será usado no próximo procedimento.
Em seguida, você criará um arquivo XML usando as informações de assembly reunidas no procedimento anterior.
Para criar o arquivo XML
Em Solution Explorer, selecione o projeto SampleRules.
No menu Project, selecione Add New Item.
No modelos de painel, localize e selecione o Arquivo XML item.
No nome caixa de texto, digite SampleRules.Extensions.xml e clique o Add botão.
O arquivo de SampleRules.Extensions.xml é adicionado ao projeto no Solution Explorer.
Abra o arquivo SampleRules.Extensions.xml e atualizá-lo para coincidir com o seguinte XML. Substitua a versão, cultura e PublicKeyToken valores com aqueles que você recuperou no procedimento anterior.
<?xml version="1.0" encoding="utf-8"?> <extensions assembly="" version="1" xmlns="urn:Microsoft.Data.Schema.Extensions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:Microsoft.Data.Schema.Extensions Microsoft.Data.Schema.Extensions.xsd"> <extension type="SampleRules.AvoidWaitForDelayRule" assembly="SampleRules, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b4deb9b383d021b0" enabled="true"/> </extensions>
Sobre o arquivo menu, clique em Salvar.
Em seguida, você irá copiar as informações de assembly e o arquivo XML para o diretório de extensões. Quando Visual Studio é iniciado, ele irá identificar quaisquer extensões no diretório de 10.0\VSTSDB\Extensions de Visual Studio da Microsoft e subdiretórios e registro-los para usam na sessão.
Para copiar as informações de assembly e o arquivo XML para o diretório de extensões
Crie uma nova pasta chamada CustomRules no diretório 10.0\VSTSDB\Extensions\ Visual Studio da Microsoft.
Copie o arquivo de montagem de SampleRules.dll a projetos\SampleRules\SampleRules\bin\Debug\ o diretório para o diretório de 10.0\VSTSDB\Extensions\CustomRules de Visual Studio da Microsoft que você criou.
Copiar o arquivo SampleRules.Extensions.xml do projetos\SampleRules\SampleRules\ o diretório para o diretório de 10.0\VSTSDB\Extensions\CustomRules de Visual Studio da Microsoft que você criou.
Observação Uma prática recomendada é colocar seus assemblies de extensão em uma pasta no diretório 10.0\VSTSDB\Extensions Visual Studio da Microsoft. Isso irá ajudá-lo a identificar quais extensões foram incluídas com o produto e quais são suas criações personalizadas. Pastas também são recomendadas para organizar suas extensões em categorias específicas.
Em seguida, inicie uma nova sessão do Visual Studio e crie um projeto de banco de dados.
Para iniciar uma nova sessão de Visual Studio e crie um projeto de banco de dados
Iniciar uma segunda sessão do Visual Studio.
Sobre o arquivo menu, clique em novo e, em seguida, clique em projeto.
No Novo projeto caixa de diálogo, na lista de Modelos instalados, expanda o Projetos de banco de dados nó e clique SQL Server.
No painel de detalhes, selecione Projeto de banco de dados de 2008 do SQL Server.
No nome caixa de texto, digite SampleRulesDB e clique em OK.
Finalmente, você verá a nova regra exibindo na SQL Server project.
Para exibir a nova regra de análise de código de AvoidWaitForRule
Em Solution Explorer, selecione o projeto SampleRulesDB.
No menu Project, clique em Properties..
A página de propriedades de SampleRulesDB é exibida.
Clique em código Analysis.
Você deve ver uma nova categoria chamada CategorySamples.
Expanda CategorySamples.
Você deve ver SR1004: Evitar a instrução WAITFOR DELAY em procedimentos armazenados, disparadores e funções.
Consulte também
Tarefas
Como: Registrar e gerenciar extensões de recurso
Como: Distribuir as extensões de recurso personalizadas para os membros da equipe
Referência
Conceitos
Estender os recursos de banco de dados de Visual Studio
Analisando o código do banco de dados para melhorar a qualidade do código
Analisando qualidade de código gerenciado usando a análise de código