Criar regras de análise de código personalizadas
Aplica-se a: SQL Server Banco de Dados SQL do Azure Instância Gerenciada de SQL do Azure Banco de Dados SQL no Microsoft Fabric
Este passo a passo demonstra as etapas usadas para criar uma regra de análise de código do SQL Server. A regra criada neste passo a passo é usada para evitar instruções WAITFOR DELAY
em procedimentos armazenados, gatilhos e funções.
Neste passo a passo, você criará uma regra personalizada para o Code Analysis estático do Transact-SQL ao usar as seguintes etapas:
- Crie um projeto de biblioteca de classes, habilite a assinatura para o projeto e adicione as referências necessárias.
- Criação de duas classes auxiliares em C#.
- Criação de uma classe de regra personalizada em C#.
- Compile o projeto de biblioteca de classes.
- Instale e teste a nova regra de análise de código.
Com exceção das instruções do Visual Studio (SQL Server Data Tools), o guia se concentra em projetos SQL no estilo SDK.
Pré-requisitos
Você precisará dos seguintes componentes para concluir este passo a passo:
- Uma versão do Visual Studio instalada, que inclui SQL Server Data Tools e fornece suporte ao desenvolvimento em C# do .NET Framework.
- Um projeto do SQL Server que contém objetos SQL Server.
- Uma instância do SQL Server ao qual você poderá implantar um projeto de banco de dados.
Este passo a passo é destinado a usuários que já estão familiarizados com os recursos de SQL Server do SQL Server Data Tools. Você deve ter familiaridade com os conceitos do Visual Studio, por exemplo, como criar uma biblioteca de classes, adicionar pacotes do NuGet e usar o editor de código para adicionar códigos a uma classe.
Observação
Devido às limitações de visualização do SQL Server Data Tools no estilo SDK, várias instalações do Visual Studio são necessárias para concluir este passo a passo. A primeira instalação é necessária para criar o projeto de biblioteca de classes, a segunda instalação é necessária para criar o projeto de banco de dados SQL no estilo SDK.
- SDK do .NET 8
- Visual Studio 2022 Community, Professional ou Enterprise
- SQL Server Data Tools, estilo SDK (versão prévia) instalado no Visual Studio 2022
- Uma versão do Visual Studio instalada, que fornece suporte ao desenvolvimento em C# do .NET.
- Um projeto do SQL Server que contém objetos SQL Server.
Este passo a passo é destinado a usuários que já estão familiarizados com os recursos de SQL Server do SQL Server Data Tools. Você deve ter familiaridade com os conceitos do Visual Studio, por exemplo, como criar uma biblioteca de classes, adicionar pacotes do NuGet e usar o editor de código para adicionar códigos a uma classe.
- Uma versão do Visual Studio Code instalada, que inclui a extensão de Projetos de Banco de Dados SQL.
- Um projeto do banco de dados SQL que contém objetos SQL.
- SDK do .NET 8
- Recomendado: extensão do Kit de Desenvolvimento do C# para VS Code
Este passo a passo destina-se a usuários que já estão familiarizados com a extensão de Projetos de Banco de Dados SQL no Visual Studio Code. Você deve ter familiaridade com os conceitos de desenvolvimento, por exemplo, como criar uma biblioteca de classes, adicionar pacotes e usar o editor de código para editar código.
- Um editor de textos, como o editor de arquivos no Visual Studio Code.
- Um projeto do banco de dados SQL que contém objetos SQL.
- SDK do .NET 8
Este passo a passo é destinado a usuários que já estão familiarizados com projetos SQL. Você deve ter familiaridade com os conceitos de desenvolvimento, por exemplo, como criar uma biblioteca de classes, adicionar pacotes e usar o editor de código para editar código.
Etapa 1: criar um projeto de biblioteca de classes
Em primeiro lugar, crie uma biblioteca de classes. Para criar um projeto de biblioteca de classes:
Crie um projeto de biblioteca de classes em C# (.NET Framework) chamado
SampleRules
.Renomeie o arquivo
Class1.cs
paraAvoidWaitForDelayRule.cs
.No Gerenciador de Soluções, clique com o botão direito do mouse no nó do projeto e, em seguida, selecione Adicionar e depois Referência.
Selecione
System.ComponentModel.Composition
na guia Assemblies\Estruturas.No Gerenciador de Soluções, clique com o botão direito do mouse no nó do projeto e, em seguida, selecione Gerenciar Pacotes do NuGet. Localize e faça a instalação do pacote do NuGet
Microsoft.SqlServer.DacFx
. A versão selecionada deve ser162.x.x
(por exemplo162.2.111
) com o Visual Studio 2022.
A seguir, você adicionará as classes de suporte que serão usadas pela regra.
Em primeiro lugar, crie uma biblioteca de classes. Para criar um projeto de biblioteca de classes:
Crie um projeto de biblioteca de classes em C# (.NET Framework) chamado
SampleRules
.Renomeie o arquivo
Class1.cs
paraAvoidWaitForDelayRule.cs
.No Gerenciador de Soluções, clique com o botão direito do mouse no nó do projeto e, em seguida, selecione Adicionar e depois Referência.
Selecione
System.ComponentModel.Composition
na guia Assemblies\Estruturas.No Gerenciador de Soluções, clique com o botão direito do mouse no nó do projeto e, em seguida, selecione Gerenciar Pacotes do NuGet. Localize e faça a instalação do pacote do NuGet
Microsoft.SqlServer.DacFx
. A versão selecionada deve ser162.x.x
(por exemplo162.2.111
) com o Visual Studio 2022.
A seguir, você adicionará as classes de suporte que serão usadas pela regra.
Inicie o Visual Studio Code e abra a pasta em que você deseja criar o projeto.
Abra uma janela Terminal no Visual Studio Code selecionando o menu Exibir, depois Terminal.
Em Terminal, digite os seguintes comandos para criar uma nova solução e projeto:
dotnet new sln dotnet new classlib -n SampleRules -o SampleRules dotnet sln add SampleRules/SampleRules.csproj
Altere para o diretório
SampleRules
:cd SampleRules
Adicionar o pacote NuGet necessário:
dotnet add package Microsoft.SqlServer.DacFx
A seguir, você adicionará as classes de suporte que serão usadas pela regra.
Abra um prompt de comando ou janela terminal e navegue até a pasta em que você deseja criar o projeto.
Em Terminal, digite os seguintes comandos para criar uma nova solução e projeto:
dotnet new sln dotnet new classlib -n SampleRules -o SampleRules dotnet sln add SampleRules/SampleRules.csproj
Altere para o diretório
SampleRules
:cd SampleRules
Adicionar o pacote NuGet necessário:
dotnet add package Microsoft.SqlServer.DacFx
Etapa 2: criar classes auxiliares de regras personalizadas
Antes de criar a classe para a regra em si, adicione uma classe de visitante e uma classe de atributos ao projeto. Essas classes podem ser úteis para criar mais regras personalizadas.
Etapa 2.1: definir a classe WaitForDelayVisitor
A primeira classe que você deve definir é a classe WaitForDelayVisitor
, derivada de TSqlConcreteFragmentVisitor. Essa classe fornece acesso às instruções WAITFOR DELAY
no modelo. As classes de visitante utilizam as APIs ScriptDom fornecidas pelo SQL Server. Nessa API, o código Transact-SQL é representado como uma árvore de sintaxe abstrata (AST) e as classes de visitantes podem ser úteis quando você deseja procurar por objetos de sintaxe específicos, como instruções WAITFOR DELAY
. Essas instruções podem ser difíceis de localizar ao usar o modelo de objeto, pois não estão associadas a uma propriedade ou a um relacionamento específico do objeto. Entretanto, é possível encontrá-las ao usar o padrão de visitante e a API ScriptDom.
No Gerenciador de Soluções, selecione o projeto
SampleRules
.No menu Projeto, selecione Adicionar classe. A caixa de diálogo Adicionar Novo Item aparecerá. Na caixa de texto Nome, digite
WaitForDelayVisitor.cs
e, em seguida, selecione o botão Adicionar. O arquivoWaitForDelayVisitor.cs
é adicionado ao projeto no Gerenciador de Soluções.
No Gerenciador de Soluções, selecione o projeto
SampleRules
.No menu Projeto, selecione Adicionar classe. A caixa de diálogo Adicionar Novo Item aparecerá. Na caixa de texto Nome, digite
WaitForDelayVisitor.cs
e, em seguida, selecione o botão Adicionar. O arquivoWaitForDelayVisitor.cs
é adicionado ao projeto no Gerenciador de Soluções.
Abra a exibição do Explorer no Visual Studio Code.
Crie um novo arquivo chamado
WaitForDelayVisitor.cs
na pastaSampleRules
.
- Navegue até o diretório
SampleRules
. - Crie um arquivo chamado
WaitForDelayVisitor.cs
.
Abra o arquivo
WaitForDelayVisitor.cs
e atualize o conteúdo para corresponder ao seguinte código:using System.Collections.Generic; using Microsoft.SqlServer.TransactSql.ScriptDom; namespace SampleRules { class WaitForDelayVisitor {} }
Na declaração da classe, altere o modificador de acesso para interno e derive a classe usando
TSqlConcreteFragmentVisitor
:internal class WaitForDelayVisitor : TSqlConcreteFragmentVisitor {}
Adicione o código a seguir para definir a variável de membro da Lista:
public IList<WaitForStatement> WaitForDelayStatements { get; private set; }
Defina o construtor da classe adicionando o seguinte código:
public WaitForDelayVisitor() { WaitForDelayStatements = new List<WaitForStatement>(); }
Substitua o método
ExplicitVisit
ao adicionar o seguinte código:public override void ExplicitVisit(WaitForStatement node) { // We are only interested in WAITFOR DELAY occurrences if (node.WaitForOption == WaitForOption.Delay) WaitForDelayStatements.Add(node); }
Esse método consulta as instruções
WAITFOR
no modelo e adiciona instruções que têm a opçãoDELAY
especificada à lista de instruçõesWAITFOR DELAY
. A classe chave referenciada é WaitForStatement.No menu Arquivo, selecione Salvar.
Etapa 2.2: adicionar um arquivo de recurso e três cadeias de caracteres de recurso
Em seguida, adicione um arquivo de recurso que defina o nome da regra, a descrição da regra e a categoria na qual a regra aparecerá na interface de configuração da regra.
No Gerenciador de Soluções, selecione o projeto
SampleRules
. No menu Projeto, selecione Adicionar e, em seguida, Novo Item. A caixa de diálogo Adicionar Novo Item aparecerá.Na lista de Modelos Instalados, selecione Geral. No painel Detalhes, selecione Arquivo de Recursos.
Em Nome, digite
RuleResources.resx
. O editor de recurso aparece sem recursos definidos.Defina quatro cadeias de caracteres de recurso da seguinte maneira:
Nome Valor AvoidWaitForDelay_ProblemDescription
WAITFOR DELAY statement was found in {0}.
AvoidWaitForDelay_RuleName
Avoid using WaitFor Delay statements in stored procedures, functions and triggers.
CategorySamples
SamplesCategory
CannotCreateResourceManager
Can't create ResourceManager for {0} from {1}.
No menu Arquivo, selecione Salvar RuleResources.resx.
No Gerenciador de Soluções, selecione o projeto
SampleRules
. No menu Projeto, selecione Adicionar e, em seguida, Novo Item. A caixa de diálogo Adicionar Novo Item aparecerá.Na lista de Modelos Instalados, selecione Geral. No painel Detalhes, selecione Arquivo de Recursos.
Em Nome, digite
RuleResources.resx
. O editor de recurso aparece sem recursos definidos.Defina quatro cadeias de caracteres de recurso da seguinte maneira:
Nome Valor AvoidWaitForDelay_ProblemDescription
WAITFOR DELAY statement was found in {0}.
AvoidWaitForDelay_RuleName
Avoid using WaitFor Delay statements in stored procedures, functions and triggers.
CategorySamples
SamplesCategory
CannotCreateResourceManager
Can't create ResourceManager for {0} from {1}.
No menu Arquivo, selecione Salvar RuleResources.resx.
No diretório
SampleRules
, crie um novo arquivo nomeadoRuleResources.resx
.Abra o arquivo
RuleResources.resx
e adicione o seguinte código:<?xml version="1.0" encoding="utf-8"?> <root> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:element name="root" msdata:IsDataSet="true"> <xsd:complexType> <xsd:choice maxOccurs="unbounded"> <xsd:element name="metadata"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" /> </xsd:sequence> <xsd:attribute name="name" use="required" type="xsd:string" /> <xsd:attribute name="type" type="xsd:string" /> <xsd:attribute name="mimetype" type="xsd:string" /> <xsd:attribute ref="xml:space" /> </xsd:complexType> </xsd:element> <xsd:element name="assembly"> <xsd:complexType> <xsd:attribute name="alias" type="xsd:string" /> <xsd:attribute name="name" type="xsd:string" /> </xsd:complexType> </xsd:element> <xsd:element name="data"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> <xsd:attribute ref="xml:space" /> </xsd:complexType> </xsd:element> <xsd:element name="resheader"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" /> </xsd:complexType> </xsd:element> </xsd:choice> </xsd:complexType> </xsd:element> </xsd:schema> <resheader name="resmimetype"> <value>text/microsoft-resx</value> </resheader> <resheader name="version"> <value>2.0</value> </resheader> <resheader name="reader"> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <resheader name="writer"> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <data name="AvoidWaitForDelay_ProblemDescription" xml:space="preserve"> <value>WAITFOR DELAY statement was found in {0}</value> </data> <data name="AvoidWaitFormDelay_RuleName" xml:space="preserve"> <value>Avoid using WaitFor Delay statements in stored procedures, functions and triggers.</value> </data> <data name="CategorySamples" xml:space="preserve"> <value>SamplesCategory</value> </data> <data name="CannotCreateResourceManager" xml:space="preserve"> <value>Can't create ResourceManager for {0} from {1}</value> </data> </root>
Salve o arquivo
RuleResources.resx
.Abra o arquivo
SampleRules.csproj
e adicione o seguinte código para atualizar e incluir o conteúdo do recurso no projeto:<ItemGroup> <Compile Update="RuleResources.Designer.cs"> <DesignTime>True</DesignTime> <AutoGen>True</AutoGen> <DependentUpon>RuleResources.resx</DependentUpon> </Compile> </ItemGroup> <ItemGroup> <EmbeddedResource Include="RuleResources.resx"> <Generator>PublicResXFileCodeGenerator</Generator> <LastGenOutput>RuleResources.Designer.cs</LastGenOutput> </EmbeddedResource> </ItemGroup>
Salve o arquivo
SampleRules.csproj
.
No diretório
SampleRules
, crie um novo arquivo nomeadoRuleResources.resx
.Abra o arquivo
RuleResources.resx
e adicione o seguinte código:<?xml version="1.0" encoding="utf-8"?> <root> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:element name="root" msdata:IsDataSet="true"> <xsd:complexType> <xsd:choice maxOccurs="unbounded"> <xsd:element name="metadata"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" /> </xsd:sequence> <xsd:attribute name="name" use="required" type="xsd:string" /> <xsd:attribute name="type" type="xsd:string" /> <xsd:attribute name="mimetype" type="xsd:string" /> <xsd:attribute ref="xml:space" /> </xsd:complexType> </xsd:element> <xsd:element name="assembly"> <xsd:complexType> <xsd:attribute name="alias" type="xsd:string" /> <xsd:attribute name="name" type="xsd:string" /> </xsd:complexType> </xsd:element> <xsd:element name="data"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> <xsd:attribute ref="xml:space" /> </xsd:complexType> </xsd:element> <xsd:element name="resheader"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" /> </xsd:complexType> </xsd:element> </xsd:choice> </xsd:complexType> </xsd:element> </xsd:schema> <resheader name="resmimetype"> <value>text/microsoft-resx</value> </resheader> <resheader name="version"> <value>2.0</value> </resheader> <resheader name="reader"> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <resheader name="writer"> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <data name="AvoidWaitForDelay_ProblemDescription" xml:space="preserve"> <value>WAITFOR DELAY statement was found in {0}</value> </data> <data name="AvoidWaitFormDelay_RuleName" xml:space="preserve"> <value>Avoid using WaitFor Delay statements in stored procedures, functions and triggers.</value> </data> <data name="CategorySamples" xml:space="preserve"> <value>SamplesCategory</value> </data> <data name="CannotCreateResourceManager" xml:space="preserve"> <value>Can't create ResourceManager for {0} from {1}</value> </data> </root>
Salve o arquivo
RuleResources.resx
.Abra o arquivo
SampleRules.csproj
e adicione o seguinte código para atualizar e incluir o conteúdo do recurso no projeto:<ItemGroup> <Compile Update="RuleResources.Designer.cs"> <DesignTime>True</DesignTime> <AutoGen>True</AutoGen> <DependentUpon>RuleResources.resx</DependentUpon> </Compile> </ItemGroup> <ItemGroup> <EmbeddedResource Include="RuleResources.resx"> <Generator>PublicResXFileCodeGenerator</Generator> <LastGenOutput>RuleResources.Designer.cs</LastGenOutput> </EmbeddedResource> </ItemGroup>
Salve o arquivo
SampleRules.csproj
.
Etapa 2.3: definir a classe LocalizedExportCodeAnalysisRuleAttribute
A segunda classe é LocalizedExportCodeAnalysisRuleAttribute.cs
. Esta é uma extensão do Microsoft.SqlServer.Dac.CodeAnalysis.ExportCodeAnalysisRuleAttribute
interno fornecido pela estrutura que oferece suporte à leitura de DisplayName
e de Description
que são usados pela regra com um arquivo de recursos. Essa é uma classe útil se você pretender ter suas regras usadas em vários idiomas.
No Gerenciador de Soluções, selecione o projeto
SampleRules
.No menu Projeto, selecione Adicionar classe. A caixa de diálogo Adicionar Novo Item aparecerá. Na caixa de texto Nome, digite
LocalizedExportCodeAnalysisRuleAttribute.cs
e, em seguida, selecione o botão Adicionar. O arquivo é adicionado ao projeto no Gerenciador de Soluções.
No Gerenciador de Soluções, selecione o projeto
SampleRules
.No menu Projeto, selecione Adicionar classe. A caixa de diálogo Adicionar Novo Item aparecerá. Na caixa de texto Nome, digite
LocalizedExportCodeAnalysisRuleAttribute.cs
e, em seguida, selecione o botão Adicionar. O arquivo é adicionado ao projeto no Gerenciador de Soluções.
- Navegue até o diretório
SampleRules
na exibição do Explorer no Visual Studio Code. - Crie um arquivo chamado
LocalizedExportCodeAnalysisRuleAttribute.cs
.
- Navegue até o diretório
SampleRules
. - Crie um arquivo chamado
LocalizedExportCodeAnalysisRuleAttribute.cs
.
Abra o arquivo e atualize o conteúdo para corresponder ao seguinte código:
using Microsoft.SqlServer.Dac.CodeAnalysis; using System; using System.Globalization; using System.Reflection; using System.Resources; namespace SampleRules { internal class LocalizedExportCodeAnalysisRuleAttribute : ExportCodeAnalysisRuleAttribute { private readonly string _resourceBaseName; private readonly string _displayNameResourceId; private readonly string _descriptionResourceId; private ResourceManager _resourceManager; private string _displayName; private string _descriptionValue; /// <summary> /// Creates the attribute, with the specified rule ID, the fully qualified /// name of the resource file that will be used for looking up display name /// and description, and the Ids of those resources inside the resource file. /// </summary> public LocalizedExportCodeAnalysisRuleAttribute( string id, string resourceBaseName, string displayNameResourceId, string descriptionResourceId) : base(id, null) { _resourceBaseName = resourceBaseName; _displayNameResourceId = displayNameResourceId; _descriptionResourceId = descriptionResourceId; } /// <summary> /// Rules in a different assembly would need to overwrite this /// </summary> /// <returns></returns> protected virtual Assembly GetAssembly() { return GetType().Assembly; } private void EnsureResourceManagerInitialized() { var resourceAssembly = GetAssembly(); try { _resourceManager = new ResourceManager(_resourceBaseName, resourceAssembly); } catch (Exception ex) { var msg = String.Format(CultureInfo.CurrentCulture, RuleResources.CannotCreateResourceManager, _resourceBaseName, resourceAssembly); throw new RuleException(msg, ex); } } private string GetResourceString(string resourceId) { EnsureResourceManagerInitialized(); return _resourceManager.GetString(resourceId, CultureInfo.CurrentUICulture); } /// <summary> /// Overrides the standard DisplayName and looks up its value inside a resources file /// </summary> public override string DisplayName { get { if (_displayName == null) { _displayName = GetResourceString(_displayNameResourceId); } return _displayName; } } /// <summary> /// Overrides the standard Description and looks up its value inside a resources file /// </summary> public override string Description { get { if (_descriptionValue == null) { _descriptionValue = GetResourceString(_descriptionResourceId); } return _descriptionValue; } } } }
Etapa 2.4: definir a classe SampleConstants
Em seguida, defina uma classe que faz referência aos recursos no arquivo de recursos que são usados pelo Visual Studio para exibir informações sobre a regra na interface do usuário.
No Gerenciador de Soluções, selecione o projeto
SampleRules
.No menu Projeto, selecione Adicionar e, em seguida, Classe. A caixa de diálogo Adicionar Novo Item aparecerá. Na caixa de texto Nome, digite
SampleRuleConstants.cs
e selecione o botão Adicionar. O arquivoSampleRuleConstants.cs
é adicionado ao projeto no Gerenciador de Soluções.
No Gerenciador de Soluções, selecione o projeto
SampleRules
.No menu Projeto, selecione Adicionar e, em seguida, Classe. A caixa de diálogo Adicionar Novo Item aparecerá. Na caixa de texto Nome, digite
SampleRuleConstants.cs
e selecione o botão Adicionar. O arquivoSampleRuleConstants.cs
é adicionado ao projeto no Gerenciador de Soluções.
- Navegue até o diretório
SampleRules
na exibição do Explorer no Visual Studio Code. - Crie um arquivo chamado
SampleRuleConstants.cs
.
- Navegue até o diretório
SampleRules
. - Crie um arquivo chamado
SampleRuleConstants.cs
.
Abra o arquivo
SampleRuleConstants.cs
e adicione as seguintes instruções using ao arquivo:namespace SampleRules { internal static class RuleConstants { /// <summary> /// The name of the resources file to use when looking up rule resources /// </summary> public const string ResourceBaseName = "SampleRules.RuleResources"; /// <summary> /// Lookup name inside the resources file for the select asterisk rule name /// </summary> public const string AvoidWaitForDelay_RuleName = "AvoidWaitForDelay_RuleName"; /// <summary> /// Lookup ID inside the resources file for the select asterisk description /// </summary> public const string AvoidWaitForDelay_ProblemDescription = "AvoidWaitForDelay_ProblemDescription"; /// <summary> /// The design category (should not be localized) /// </summary> public const string CategoryDesign = "Design"; /// <summary> /// The performance category (should not be localized) /// </summary> public const string CategoryPerformance = "Design"; } }
No menu Arquivo, selecione Salvar.
Etapa 3: criar uma classe de regra personalizada
Após adicionar as classes auxiliares que a regra de análise de código personalizada usará, crie uma classe de regra personalizada e nomeie-a como AvoidWaitForDelayRule
. A regra personalizada AvoidWaitForDelayRule
será usada para ajudar os desenvolvedores de banco de dados a evitar instruções WAITFOR DELAY
em procedimentos armazenados, gatilhos e funções.
Etapa 3.1: criar a classe AvoidWaitForDelayRule
No Gerenciador de Soluções, selecione o projeto
SampleRules
.No menu Projeto, selecione Adicionar e, em seguida, Classe. A caixa de diálogo Adicionar Novo Item aparecerá. Na caixa de texto Nome, digite
AvoidWaitForDelayRule.cs
e, em seguida, selecione Adicionar. O arquivoAvoidWaitForDelayRule.cs
é adicionado ao projeto no Gerenciador de Soluções.
No Gerenciador de Soluções, selecione o projeto
SampleRules
.No menu Projeto, selecione Adicionar e, em seguida, Classe. A caixa de diálogo Adicionar Novo Item aparecerá. Na caixa de texto Nome, digite
AvoidWaitForDelayRule.cs
e, em seguida, selecione Adicionar. O arquivoAvoidWaitForDelayRule.cs
é adicionado ao projeto no Gerenciador de Soluções.
- Navegue até o diretório
SampleRules
na exibição do Explorer no Visual Studio Code. - Crie um arquivo chamado
AvoidWaitForDelayRule.cs
.
- Navegue até o diretório
SampleRules
. - Crie um arquivo chamado
AvoidWaitForDelayRule.cs
.
Abra o arquivo
AvoidWaitForDelayRule.cs
e adicione as seguintes instruções using ao arquivo:using Microsoft.SqlServer.Dac.CodeAnalysis; using Microsoft.SqlServer.Dac.Model; using Microsoft.SqlServer.TransactSql.ScriptDom; using System; using System.Collections.Generic; using System.Globalization; namespace SampleRules { class AvoidWaitForDelayRule {} }
Na declaração de classe
AvoidWaitForDelayRule
, altere o modificador de acesso para público:/// <summary> /// This is a rule that returns a warning message /// whenever there is a WAITFOR DELAY statement appears inside a subroutine body. /// This rule only applies to stored procedures, functions and triggers. /// </summary> public sealed class AvoidWaitForDelayRule
Derive a classe
AvoidWaitForDelayRule
da classe baseMicrosoft.SqlServer.Dac.CodeAnalysis.SqlCodeAnalysisRule
:public sealed class AvoidWaitForDelayRule : SqlCodeAnalysisRule
Adicione
LocalizedExportCodeAnalysisRuleAttribute
à sua classe.O atributo
LocalizedExportCodeAnalysisRuleAttribute
permite que o serviço de análise de código revele as regras de análise de código personalizadas. Somente as classes marcadas comExportCodeAnalysisRuleAttribute
(ou um atributo que seja herdeiro deste) podem ser usadas no Code Analysis.O atributo
LocalizedExportCodeAnalysisRuleAttribute
fornece alguns metadados necessários que são usados pelo serviço. Isso inclui uma ID exclusiva para essa regra, um nome de exibição que será mostrado na interface do usuário do Visual Studio e umaDescription
que pode ser usada pela regra ao identificar problemas.[LocalizedExportCodeAnalysisRule(AvoidWaitForDelayRule.RuleId, RuleConstants.ResourceBaseName, RuleConstants.AvoidWaitForDelay_RuleName, RuleConstants.AvoidWaitForDelay_ProblemDescription Category = RuleConstants.CategoryPerformance, RuleScope = SqlRuleScope.Element)] public sealed class AvoidWaitForDelayRule : SqlCodeAnalysisRule { /// <summary> /// The Rule ID should resemble a fully-qualified class name. In the Visual Studio UI /// rules are grouped by "Namespace + Category", and each rule is shown using "Short ID: DisplayName". /// For this rule, that means the grouping will be "Public.Dac.Samples.Performance", with the rule /// shown as "SR1004: Avoid using WaitFor Delay statements in stored procedures, functions and triggers." /// </summary> public const string RuleId = "RuleSamples.SR1004"; }
A propriedade RuleScope deve ser
Microsoft.SqlServer.Dac.CodeAnalysis.SqlRuleScope.Element
, pois essa regra analisa elementos específicos. A regra será chamada uma vez para cada elemento correspondente no modelo. Caso deseje analisar um modelo inteiro, você pode usarMicrosoft.SqlServer.Dac.CodeAnalysis.SqlRuleScope.Model
em vez disso.Adicione um construtor que configure
Microsoft.SqlServer.Dac.CodeAnalysis.SqlAnalysisRule.SupportedElementTypes
. Isso é necessário para regras de escopo do elemento. Ele define os tipos de elementos para os quais essa regra se aplica. Nesse caso, a regra é aplicada a procedimentos armazenados, gatilhos e funções. A classeMicrosoft.SqlServer.Dac.Model.ModelSchema
lista todos os tipos de elementos disponíveis que podem ser analisados.public AvoidWaitForDelayRule() { // This rule supports Procedures, Functions and Triggers. Only those objects will be passed to the Analyze method SupportedElementTypes = new[] { // Note: can use the ModelSchema definitions, or access the TypeClass for any of these types ModelSchema.ExtendedProcedure, ModelSchema.Procedure, ModelSchema.TableValuedFunction, ModelSchema.ScalarFunction, ModelSchema.DatabaseDdlTrigger, ModelSchema.DmlTrigger, ModelSchema.ServerDdlTrigger }; }
Adicione uma substituição para o método
Microsoft.SqlServer.Dac.CodeAnalysis.SqlAnalysisRule.Analyze
(Microsoft.SqlServer.Dac.CodeAnalysis.SqlRuleExecutionContext)
, que usaMicrosoft.SqlServer.Dac.CodeAnalysis.SqlRuleExecutionContext
como parâmetro de entrada. Esse método retorna uma lista de possíveis problemas.O método obtém
Microsoft.SqlServer.Dac.Model.TSqlModel
,Microsoft.SqlServer.Dac.Model.TSqlObject
e TSqlFragment usando o parâmetro de contexto. Em seguida, a classeWaitForDelayVisitor
é usada para obter uma lista de todas as instruçõesWAITFOR DELAY
presentes no modelo.Para cada WaitForStatement nessa lista, há a criação de um
Microsoft.SqlServer.Dac.CodeAnalysis.SqlRuleProblem
./// <summary> /// For element-scoped rules the Analyze method is executed once for every matching /// object in the model. /// </summary> /// <param name="ruleExecutionContext">The context object contains the TSqlObject being /// analyzed, a TSqlFragment /// that's the AST representation of the object, the current rule's descriptor, and a /// reference to the model being /// analyzed. /// </param> /// <returns>A list of problems should be returned. These will be displayed in the Visual /// Studio error list</returns> public override IList<SqlRuleProblem> Analyze( SqlRuleExecutionContext ruleExecutionContext) { IList<SqlRuleProblem> problems = new List<SqlRuleProblem>(); TSqlObject modelElement = ruleExecutionContext.ModelElement; // this rule does not apply to inline table-valued function // we simply do not return any problem in that case. if (IsInlineTableValuedFunction(modelElement)) { return problems; } string elementName = GetElementName(ruleExecutionContext, modelElement); // The rule execution context has all the objects we'll need, including the // fragment representing the object, // and a descriptor that lets us access rule metadata TSqlFragment fragment = ruleExecutionContext.ScriptFragment; RuleDescriptor ruleDescriptor = ruleExecutionContext.RuleDescriptor; // To process the fragment and identify WAITFOR DELAY statements we will use a // visitor WaitForDelayVisitor visitor = new WaitForDelayVisitor(); fragment.Accept(visitor); IList<WaitForStatement> waitforDelayStatements = visitor.WaitForDelayStatements; // Create problems for each WAITFOR DELAY statement found // When creating a rule problem, always include the TSqlObject being analyzed. This // is used to determine // the name of the source this problem was found in and a best guess as to the // line/column the problem was found at. // // In addition if you have a specific TSqlFragment that is related to the problem //also include this // since the most accurate source position information (start line and column) will // be read from the fragment foreach (WaitForStatement waitForStatement in waitforDelayStatements) { SqlRuleProblem problem = new SqlRuleProblem( String.Format(CultureInfo.CurrentCulture, ruleDescriptor.DisplayDescription, elementName), modelElement, waitForStatement); problems.Add(problem); } return problems; } private static string GetElementName( SqlRuleExecutionContext ruleExecutionContext, TSqlObject modelElement) { // Get the element name using the built in DisplayServices. This provides a number of // useful formatting options to // make a name user-readable var displayServices = ruleExecutionContext.SchemaModel.DisplayServices; string elementName = displayServices.GetElementName( modelElement, ElementNameStyle.EscapedFullyQualifiedName); return elementName; } private static bool IsInlineTableValuedFunction(TSqlObject modelElement) { return TableValuedFunction.TypeClass.Equals(modelElement.ObjectType) && FunctionType.InlineTableValuedFunction == modelElement.GetMetadata<FunctionType>(TableValuedFunction.FunctionType); }
No menu Arquivo, selecione Salvar.
Etapa 4: criar a biblioteca de classes
- No menu Projeto, selecione Propriedades de SampleRules.
- Selecione a guia Assinatura.
- Selecione Assinar Assembly.
- Em Escolher um Arquivo de Chave com Nome Forte, selecione <Novo>.
- Na caixa de diálogo Criar Chave com Nome Forte, em Nome de Arquivo de Chave, digite
MyRefKey
. - (opcional) Você pode especificar uma senha para o arquivo de chave de nome forte.
- Selecione OK.
- No menu Arquivo, selecione Salvar Tudo.
- No menu Build, selecione Compilar Solução.
- No menu Projeto, selecione Propriedades de SampleRules.
- Selecione a guia Assinatura.
- Selecione Assinar Assembly.
- Em Escolher um Arquivo de Chave com Nome Forte, selecione <Novo>.
- Na caixa de diálogo Criar Chave com Nome Forte, em Nome de Arquivo de Chave, digite
MyRefKey
. - (opcional) Você pode especificar uma senha para o arquivo de chave de nome forte.
- Selecione OK.
- No menu Arquivo, selecione Salvar Tudo.
- No menu Build, selecione Compilar Solução.
Abra a janela Terminal no Visual Studio Code selecionando o menu Exibir, depois Terminal.
No Terminal, insira o seguinte comando no terminal para criar o projeto:
dotnet build /p:Configuration=Release
Navegue até o diretório
SampleRules
.Execute o comando a seguir, para criar o projeto:
dotnet build /p:Configuration=Release
Etapa 5: instalar e testar a nova regra de análise de código
Em seguida, é necessário instalar o assembly de modo que ele seja carregado quando você desenvolver um projeto de banco de dados SQL.
Para instalar uma regra que será executada quando você criar um projeto SQL original com o Visual Studio, você deve copiar o assembly e o arquivo associado .pdb
para a pasta Extensões.
Etapa 5.1: instalar o assembly SampleRules
Em seguida, copie as informações do assembly para o diretório Extensões. Quando o Visual Studio é iniciado, ele identifica as extensões no diretório <Visual Studio Install Dir>\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\Extensions
e nos subdiretórios e as disponibiliza para uso.
Para o Visual Studio 2022, <Visual Studio Install Dir>
geralmente é C:\Program Files\Microsoft Visual Studio\2022\Enterprise
. Substitua Enterprise
por Professional
ou Community
, dependendo da edição do Visual Studio instalada.
Copie o arquivo de assembly SampleRules.dll do diretório de saída para o diretório <Visual Studio Install Dir>\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\Extensions
. Por padrão, o caminho do arquivo .dll
compilado é YourSolutionPath\YourProjectPath\bin\Debug
ou YourSolutionPath\YourProjectPath\bin\Release
.
Observação
Talvez seja necessário criar o diretório Extensions
.
Agora, a regra deve estar instalada e ser exibida quando você reiniciar o Visual Studio. A seguir, você iniciará uma nova sessão do Visual Studio e criará um projeto de banco de dados.
Etapa 5.2: iniciar uma nova sessão do Visual Studio e criar um projeto de banco de dados
- Inicie uma segunda sessão do Visual Studio.
- Selecione Arquivo>Novo>Projeto.
- Na caixa de diálogo Novo Projeto, localize e selecione Projeto de Banco de Dados do SQL Server.
- Na caixa de texto Nome, digite
SampleRulesDB
e selecione OK.
Etapa 5.3: habilitar a regra de análise de código AvoidWaitForRule
- No Gerenciador de Soluções, selecione o projeto
SampleRulesDB
. - No menu Projeto, selecione Propriedades. A página de propriedades
SampleRulesDB
será exibida. - Selecione Code Analysis. Você deverá ver uma nova categoria chamada
RuleSamples.CategorySamples
. - Expanda
RuleSamples.CategorySamples
. Você deverá verSR1004: Avoid WAITFOR DELAY statement in stored procedures, triggers, and functions
. - Habilite essa regra marcando a caixa de seleção ao lado do nome da regra e a caixa de seleção Habilitar análise de código no build. Para obter mais informações sobre como habilitar a análise de código, consulte a Visão geral da análise de código.
- Quando a ação de build do projeto for usada, a regra será executada e todas as instruções
WAITFOR DELAY
encontradas serão relatadas como avisos.
Para instalar uma regra que será executada quando você criar um projeto SQL original com o Visual Studio, você deve copiar o assembly e o arquivo associado .pdb
para a pasta Extensões.
Etapa 5.1: instalar o assembly SampleRules
Em seguida, copie as informações do assembly para o diretório Extensões. Quando o Visual Studio é iniciado, ele identifica as extensões no diretório <Visual Studio Install Dir>\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\Extensions
e nos subdiretórios e as disponibiliza para uso.
Para o Visual Studio 2022, <Visual Studio Install Dir>
geralmente é C:\Program Files\Microsoft Visual Studio\2022\Enterprise
. Substitua Enterprise
por Professional
ou Community
, dependendo da edição do Visual Studio instalada.
Copie o arquivo de assembly SampleRules.dll do diretório de saída para o diretório <Visual Studio Install Dir>\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\Extensions
. Por padrão, o caminho do arquivo .dll
compilado é YourSolutionPath\YourProjectPath\bin\Debug
ou YourSolutionPath\YourProjectPath\bin\Release
.
Observação
Talvez seja necessário criar o diretório Extensions
.
Agora, a regra deve estar instalada e ser exibida quando você reiniciar o Visual Studio. A seguir, você iniciará uma nova sessão do Visual Studio e criará um projeto de banco de dados.
Etapa 5.2: iniciar uma nova sessão do Visual Studio e criar um projeto de banco de dados
- Inicie uma segunda sessão do Visual Studio.
- Selecione Arquivo>Novo>Projeto.
- Na caixa de diálogo Novo Projeto, localize e selecione Projeto de Banco de Dados do SQL Server, estilo SDK (versão prévia).
- Na caixa de texto Nome, digite
SampleRulesDB
e selecione OK.
Etapa 5.3: habilitar a regra de análise de código AvoidWaitForRule
- No Gerenciador de Soluções, selecione o projeto
SampleRulesDB
. - Clique duas vezes no nó de projeto para abrir o arquivo de projeto. O arquivo de projeto
SampleRulesDB
é exibido em um editor de texto. - Habilite a análise de código no build no arquivo de projeto SQL definindo a propriedade
RunSqlCodeAnalysis
comotrue
. - Quando a ação de build do projeto for usada, a regra será executada e todas as instruções
WAITFOR DELAY
encontradas serão relatadas como avisos.
Uma solução alternativa está disponível para projetos no estilo SDK para instalar regras personalizadas até que haja suporte para referências de pacote.
- Execute
dotnet restore
para restaurar as dependências do projeto no projeto SQL, garantindo que o cache de pacotes NuGet local contenha Microsoft.Build.Sql. - Observe a versão do Microsoft.Build.Sql usada no arquivo de projeto SQL, como
0.1.19-preview
. - Copie o arquivo do assembly
SampleRules.dll
do diretório de saída para o diretório~/.nuget/packages/microsoft.build.sql/0.1.19-preview/tools/netstandard2.1
. O caminho exato do diretório pode variar dependendo da versão do Microsoft.Build.Sql usada no arquivo de projeto SQL. - Habilite a análise de código no build no arquivo de projeto SQL definindo a propriedade
RunSqlCodeAnalysis
comotrue
. - Execute
dotnet build
para criar o projeto SQL e executar a regra personalizada.
Uma solução alternativa está disponível para projetos no estilo SDK para instalar regras personalizadas até que haja suporte para referências de pacote.
- Execute
dotnet restore
para restaurar as dependências do projeto no projeto SQL, garantindo que o cache de pacotes NuGet local contenha Microsoft.Build.Sql. - Observe a versão do Microsoft.Build.Sql usada no arquivo de projeto SQL, como
0.1.19-preview
. - Copie o arquivo do assembly
SampleRules.dll
do diretório de saída para o diretório~/.nuget/packages/microsoft.build.sql/0.1.19-preview/tools/netstandard2.1
. O caminho exato do diretório pode variar dependendo da versão do Microsoft.Build.Sql usada no arquivo de projeto SQL. - Habilite a análise de código no build no arquivo de projeto SQL definindo a propriedade
RunSqlCodeAnalysis
comotrue
. - Execute
dotnet build
para criar o projeto SQL e executar a regra personalizada.