Creare regole di analisi del codice personalizzate
Si applica a: SQL Server database SQL di Azure Istanza gestita di SQL di Azure database SQL in Microsoft Fabric
Questa procedura dettagliata illustra i passaggi necessari per creare una regola di analisi del codice di SQL Server. La regola creata in questa procedura dettagliata viene usata per evitare le istruzioni WAITFOR DELAY
in stored procedure, trigger e funzioni.
In questa procedura dettagliata verrà creata una regola personalizzata per l'analisi del codice statico di Transact-SQL eseguendo i passaggi seguenti:
- Creare un progetto di libreria di classi, abilitare la firma per il progetto e aggiungere i riferimenti necessari.
- Creare due classi di helper di C#.
- Creare una classe di regola personalizzata C#.
- Compila il progetto di libreria di classi.
- Installare e testare la nuova regola di analisi del codice.
Ad eccezione delle istruzioni di Visual Studio (SQL Server Data Tools), la guida è incentrata sui progetti SQL in stile SDK.
Prerequisiti
Per completare questa procedura dettagliata, è necessario disporre dei componenti seguenti:
- Una versione di Visual Studio installata, che include SQL Server Data Tools e supporta lo sviluppo in C# .NET Framework.
- Un progetto di SQL Server contenente oggetti di SQL Server.
- Un'istanza di SQL Server a cui sia possibile distribuire un progetto di database.
Questa procedura dettagliata è destinata a utenti che hanno già familiarità con le funzionalità di SQL Server Data Tools. È anche necessario che l'utente conosca i concetti di base di Visual Studio, ad esempio come creare una libreria di classi, aggiungere pacchetti NuGet e come usare l'editor di codice per aggiungere codice a una classe.
Nota
A causa delle limitazioni di anteprima di SQL Server Data Tools in stile SDK, per completare questa procedura dettagliata sono necessarie più installazioni di Visual Studio. La prima installazione è necessaria per creare il progetto di libreria di classi, la seconda installazione è necessaria per creare il progetto di database SQL in stile SDK.
- .NET 8 SDK
- Visual Studio 2022 Community, Professional, o Enterprise
- SQL Server Data Tools, in stile SDK (anteprima) installato in Visual Studio 2022
- Una versione di Visual Studio installata, che supporta lo sviluppo in C# .NET.
- Un progetto di SQL Server contenente oggetti di SQL Server.
Questa procedura dettagliata è destinata a utenti che hanno già familiarità con le funzionalità di SQL Server Data Tools. È anche necessario che l'utente conosca i concetti di base di Visual Studio, ad esempio come creare una libreria di classi, aggiungere pacchetti NuGet e come usare l'editor di codice per aggiungere codice a una classe.
- Versione di Visual Studio Code installata, che include l'estensione database SQL Projects.
- Un progetto di database SQL contenente oggetti di SQL.
- .NET 8 SDK
- Consigliato: estensione C# Dev Kit per VS Code
Questa procedura dettagliata è destinata agli utenti che hanno già familiarità con l'estensione progetti database SQL in Visual Studio Code. È anche necessario che l'utente conosca i concetti di sviluppo, ad esempio come creare una libreria di classi, aggiungere pacchetti e come usare l'editor di codice per editare il codice.
- Un editor di testo, ad esempio l’editor di file in Visual Studio Code.
- Un progetto di database SQL contenente oggetti di SQL.
- .NET 8 SDK
Questa procedura dettagliata è destinata a utenti che abbiano già familiarità con SQL projects. È anche necessario che l'utente conosca i concetti di sviluppo, ad esempio come creare una libreria di classi, aggiungere pacchetti e come usare l'editor di codice per editare il codice.
Passaggio 1: creare un progetto libreria di classi
Per prima cosa creare una libreria di classi. Per creare un progetto libreria di classi:
Create un progetto libreria di classi in C# (.NET Framework) denominato
SampleRules
.Rinominare il file
Class1.cs
inAvoidWaitForDelayRule.cs
.In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo del progetto e scegliere Aggiungi, quindi Riferimento.
Selezionare
System.ComponentModel.Composition
nella scheda Assembly\Frameworks.In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo del progetto e scegliere Gestisci pacchetti NuGet. Ricercare e installare il pacchetto NuGet
Microsoft.SqlServer.DacFx
. La versione selezionata deve essere162.x.x
(ad esempio162.2.111
) con Visual Studio 2022.
A questo punto aggiungere le classi di supporto che verranno usate dalla regola.
Per prima cosa creare una libreria di classi. Per creare un progetto libreria di classi:
Create un progetto libreria di classi in C# (.NET Framework) denominato
SampleRules
.Rinominare il file
Class1.cs
inAvoidWaitForDelayRule.cs
.In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo del progetto e scegliere Aggiungi, quindi Riferimento.
Selezionare
System.ComponentModel.Composition
nella scheda Assembly\Frameworks.In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo del progetto e scegliere Gestisci pacchetti NuGet. Ricercare e installare il pacchetto NuGet
Microsoft.SqlServer.DacFx
. La versione selezionata deve essere162.x.x
(ad esempio162.2.111
) con Visual Studio 2022.
A questo punto aggiungere le classi di supporto che verranno usate dalla regola.
Avviare Visual Studio Code e aprire la cartella in cui si vuole creare il progetto.
In Visual Studio Code aprire la finestra del terminale selezionando il menu Visualizza, quindi Terminale.
Nel Terminale immettere i comandi seguenti per creare una nuova soluzione e progetto:
dotnet new sln dotnet new classlib -n SampleRules -o SampleRules dotnet sln add SampleRules/SampleRules.csproj
Passare alla directory
SampleRules
:cd SampleRules
Aggiungere i pacchetti NuGet necessari:
dotnet add package Microsoft.SqlServer.DacFx
A questo punto aggiungere le classi di supporto che verranno usate dalla regola.
Aprire un prompt dei comandi o una finestra di terminale e passare alla cartella in cui si vuole creare il progetto.
Nel Terminale immettere i comandi seguenti per creare una nuova soluzione e progetto:
dotnet new sln dotnet new classlib -n SampleRules -o SampleRules dotnet sln add SampleRules/SampleRules.csproj
Passare alla directory
SampleRules
:cd SampleRules
Aggiungere i pacchetti NuGet necessari:
dotnet add package Microsoft.SqlServer.DacFx
Passaggio 2: creare classi helper di regole personalizzate
Prima di creare la classe per la regola stessa, aggiungere al progetto una classe visitor e una classe attribute. Queste classi possono rivelarsi utili per la creazione di altre regole personalizzate.
Passaggio 2.1: definizione della classe WaitForDelayVisitor
La prima classe da definire è la classe WaitForDelayVisitor
, derivata da TSqlConcreteFragmentVisitor. Questa classe fornisce l'accesso alle istruzioni WAITFOR DELAY
nel modello. Le classi visitor usano le API ScriptDom fornite da SQL Server. In questa API il codice Transact-SQL viene rappresentato come un albero sintattico astratto e le classi visitor possono essere utili per trovare oggetti di sintassi specifici quali le istruzioni WAITFOR DELAY
. Può essere difficile trovare queste istruzioni usando il modello a oggetti, poiché non sono associate a una proprietà o a una relazione di un oggetto specifico, mentre è facile trovarle con il modello visitor e l'API ScriptDom.
In Esplora soluzioni selezionare il progetto
SampleRules
.Nel menu Progetto selezionare Aggiungi classe. Verrà visualizzata la finestra di dialogo Aggiungi nuovo elemento. Nella casella di testo Nome, digitare
WaitForDelayVisitor.cs
e quindi selezionare Aggiungi. Il fileWaitForDelayVisitor.cs
viene aggiunto al progetto in Esplora soluzioni.
In Esplora soluzioni selezionare il progetto
SampleRules
.Nel menu Progetto selezionare Aggiungi classe. Verrà visualizzata la finestra di dialogo Aggiungi nuovo elemento. Nella casella di testo Nome, digitare
WaitForDelayVisitor.cs
e quindi selezionare Aggiungi. Il fileWaitForDelayVisitor.cs
viene aggiunto al progetto in Esplora soluzioni.
In Visual Studio Code aprire la vista Esplora.
Nella cartella
WaitForDelayVisitor.cs
, creare un nuovo file denominatoSampleRules
.
- Passare alla directory
SampleRules
. - Creare un file denominato
WaitForDelayVisitor.cs
.
Aprire il file
WaitForDelayVisitor.cs
e aggiornare il contenuto in modo che corrisponda al codice seguente:using System.Collections.Generic; using Microsoft.SqlServer.TransactSql.ScriptDom; namespace SampleRules { class WaitForDelayVisitor {} }
Nella dichiarazione di classe impostare il modificatore di accesso su internal e derivare la classe da
TSqlConcreteFragmentVisitor
:internal class WaitForDelayVisitor : TSqlConcreteFragmentVisitor {}
Aggiungere il codice seguente per definire la variabile membro dell'elenco:
public IList<WaitForStatement> WaitForDelayStatements { get; private set; }
Definire il costruttore della classe aggiungendo il codice seguente:
public WaitForDelayVisitor() { WaitForDelayStatements = new List<WaitForStatement>(); }
Eseguire l'override del metodo
ExplicitVisit
aggiungendo il codice seguente:public override void ExplicitVisit(WaitForStatement node) { // We are only interested in WAITFOR DELAY occurrences if (node.WaitForOption == WaitForOption.Delay) WaitForDelayStatements.Add(node); }
Questo metodo visita le istruzioni
WAITFOR
nel modello e aggiunge quelle per cui è specificata l'opzioneDELAY
all'elenco di istruzioniWAITFOR DELAY
. La classe principale a cui si fa riferimento qui è WaitForStatement.Scegliere Save (Salva) dal menu File.
Passaggio 2.2: Aggiungere un file di risorse e tre stringhe di risorse
A questo punto aggiungere un file di risorse che definirà il nome della regola, la descrizione della regola e la categoria in cui la regola verrà visualizzata nell'interfaccia di configurazione delle regole.
In Esplora soluzioni selezionare il progetto
SampleRules
. Nel menu Progetto, selezionare Aggiungi e poi Nuovo elemento. Verrà visualizzata la finestra di dialogo Aggiungi nuovo elemento.Nell'elenco dei Modelli installati, fare clic su Generale. Nel riquadro dei dettagli, fare clic su File di risorse.
In Nomedigitare
RuleResources.resx
. Viene visualizzato l'editor delle risorse, senza alcuna risorsa definita.Definire quattro stringhe di risorse come segue:
Nome Valore 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}.
Nel menu Salva RuleResources.resx, selezionare Salva RuleResources.resx.
In Esplora soluzioni selezionare il progetto
SampleRules
. Nel menu Progetto, selezionare Aggiungi e poi Nuovo elemento. Verrà visualizzata la finestra di dialogo Aggiungi nuovo elemento.Nell'elenco dei Modelli installati, fare clic su Generale. Nel riquadro dei dettagli, fare clic su File di risorse.
In Nomedigitare
RuleResources.resx
. Viene visualizzato l'editor delle risorse, senza alcuna risorsa definita.Definire quattro stringhe di risorse come segue:
Nome Valore 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}.
Nel menu Salva RuleResources.resx, selezionare Salva RuleResources.resx.
Creare un nuovo file denominato
RuleResources.resx
nella directorySampleRules
.Aprire il file
RuleResources.resx
e aggiungere il codice seguente:<?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>
Salvare il file
RuleResources.resx
.Aprire il file
SampleRules.csproj
e aggiungere il codice seguente per aggiornare e includere il contenuto della risorsa nel progetto:<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>
Salvare il file
SampleRules.csproj
.
Creare un nuovo file denominato
RuleResources.resx
nella directorySampleRules
.Aprire il file
RuleResources.resx
e aggiungere il codice seguente:<?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>
Salvare il file
RuleResources.resx
.Aprire il file
SampleRules.csproj
e aggiungere il codice seguente per aggiornare e includere il contenuto della risorsa nel progetto:<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>
Salvare il file
SampleRules.csproj
.
Passaggio 2.3: Definire la classe LocalizedExportCodeAnalysisRuleAttribute
La seconda classe è LocalizedExportCodeAnalysisRuleAttribute.cs
. Si tratta di un'estensione del Microsoft.SqlServer.Dac.CodeAnalysis.ExportCodeAnalysisRuleAttribute
predefinito fornito dal framework e supporta la lettura di DisplayName
e Description
usati dalla regola da un file di risorse. È una classe utile se si prevede di usare le regole in più lingue.
In Esplora soluzioni selezionare il progetto
SampleRules
.Nel menu Progetto selezionare Aggiungi classe. Verrà visualizzata la finestra di dialogo Aggiungi nuovo elemento. Nella casella di testo Nome, digitare
LocalizedExportCodeAnalysisRuleAttribute.cs
e quindi selezionare Aggiungi. Il file viene aggiunto al progetto in Esplora soluzioni.
In Esplora soluzioni selezionare il progetto
SampleRules
.Nel menu Progetto selezionare Aggiungi classe. Verrà visualizzata la finestra di dialogo Aggiungi nuovo elemento. Nella casella di testo Nome, digitare
LocalizedExportCodeAnalysisRuleAttribute.cs
e quindi selezionare Aggiungi. Il file viene aggiunto al progetto in Esplora soluzioni.
- Passare alla directory
SampleRules
nella vista Esplora in Visual Studio Code. - Creare un file denominato
LocalizedExportCodeAnalysisRuleAttribute.cs
.
- Passare alla directory
SampleRules
. - Creare un file denominato
LocalizedExportCodeAnalysisRuleAttribute.cs
.
Aprire il file e aggiornare il contenuto in modo che corrisponda al codice seguente:
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; } } } }
Passaggio 2.4: definizione della classe SampleConstants
A questo punto definire una classe che faccia riferimento alle risorse nel file di risorse usate da Visual Studio per visualizzare le informazioni sulla regola nell'interfaccia utente.
In Esplora soluzioni selezionare il progetto
SampleRules
.Nel menu Progetto selezionare Aggiungi, quindi Classe. Verrà visualizzata la finestra di dialogo Aggiungi nuovo elemento. Nella casella di testo Nome, digitare
SampleRuleConstants.cs
, quindi selezionare il pulsante Agiungi. Il fileSampleRuleConstants.cs
viene aggiunto al progetto in Esplora soluzioni.
In Esplora soluzioni selezionare il progetto
SampleRules
.Nel menu Progetto selezionare Aggiungi, quindi Classe. Verrà visualizzata la finestra di dialogo Aggiungi nuovo elemento. Nella casella di testo Nome, digitare
SampleRuleConstants.cs
, quindi selezionare il pulsante Agiungi. Il fileSampleRuleConstants.cs
viene aggiunto al progetto in Esplora soluzioni.
- Passare alla directory
SampleRules
nella vista Esplora in Visual Studio Code. - Creare un file denominato
SampleRuleConstants.cs
.
- Passare alla directory
SampleRules
. - Creare un file denominato
SampleRuleConstants.cs
.
Aprire il file
SampleRuleConstants.cs
e aggiungere le istruzioni using seguente al file: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"; } }
Scegliere Save (Salva) dal menu File.
Passaggio 3: creare una classe di regole personalizzate
Dopo avere aggiunto le classi helper che verranno usate dalla regola di analisi del codice personalizzata, creare una classe di regole personalizzate e denominarla AvoidWaitForDelayRule
. La regola personalizzata AvoidWaitForDelayRule
sarà usata per consentire agli sviluppatori di database di evitare le istruzioni WAITFOR DELAY
in stored procedure, trigger e funzioni.
Passaggio 3.1: creazione della classe AvoidWaitForDelayRule
In Esplora soluzioni selezionare il progetto
SampleRules
.Nel menu Progetto selezionare Aggiungi, quindi Classe. Verrà visualizzata la finestra di dialogo Aggiungi nuovo elemento. Nella casella di testo Nome, digitare
AvoidWaitForDelayRule.cs
e quindi selezionare Aggiungi. Il fileAvoidWaitForDelayRule.cs
viene aggiunto al progetto in Esplora soluzioni.
In Esplora soluzioni selezionare il progetto
SampleRules
.Nel menu Progetto selezionare Aggiungi, quindi Classe. Verrà visualizzata la finestra di dialogo Aggiungi nuovo elemento. Nella casella di testo Nome, digitare
AvoidWaitForDelayRule.cs
e quindi selezionare Aggiungi. Il fileAvoidWaitForDelayRule.cs
viene aggiunto al progetto in Esplora soluzioni.
- Passare alla directory
SampleRules
nella vista Esplora in Visual Studio Code. - Creare un file denominato
AvoidWaitForDelayRule.cs
.
- Passare alla directory
SampleRules
. - Creare un file denominato
AvoidWaitForDelayRule.cs
.
Aprire il file
AvoidWaitForDelayRule.cs
e aggiungere le istruzioni using seguente al file: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 {} }
Nella dichiarazione della classe
AvoidWaitForDelayRule
impostare il modificatore di accesso su public:/// <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
Derivare la classe
AvoidWaitForDelayRule
dalla classe baseMicrosoft.SqlServer.Dac.CodeAnalysis.SqlCodeAnalysisRule
:public sealed class AvoidWaitForDelayRule : SqlCodeAnalysisRule
Aggiungere
LocalizedExportCodeAnalysisRuleAttribute
alla classe.LocalizedExportCodeAnalysisRuleAttribute
consente al servizio di analisi del codice di individuare le regole di analisi del codice personalizzate. Solo le classi contrassegnate conExportCodeAnalysisRuleAttribute
(o con un attributo che eredita da questa classe) possono essere usate nell'analisi del codice.LocalizedExportCodeAnalysisRuleAttribute
fornisce alcuni metadati necessari usati dal servizio. Tra cui un ID univoco per questa regola, un nome visualizzato che verrà visualizzato nell'interfaccia utente di Visual Studio e unDescription
che può essere usato dalla regola durante l'identificazione dei problemi.[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"; }
La proprietà RuleScope deve essere
Microsoft.SqlServer.Dac.CodeAnalysis.SqlRuleScope.Element
così come questa regola analizza elementi specifici. La regola viene chiamata una volta per ogni elemento corrispondente nel modello. Se si vuole analizzare un intero modello, allora è invece possibile usareMicrosoft.SqlServer.Dac.CodeAnalysis.SqlRuleScope.Model
.Aggiungere un costruttore che imposta
Microsoft.SqlServer.Dac.CodeAnalysis.SqlAnalysisRule.SupportedElementTypes
. Questa operazione è necessaria per le regole il cui ambito è costituito da elementi. Definisce i tipi di elementi a cui viene applicata questa regola. In questo caso, la regola viene applicata a stored procedure, trigger e funzioni. La classeMicrosoft.SqlServer.Dac.Model.ModelSchema
elenca tutti i tipi di elemento disponibili che possono essere analizzati.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 }; }
Aggiungere un override per il metodo
Microsoft.SqlServer.Dac.CodeAnalysis.SqlAnalysisRule.Analyze
(Microsoft.SqlServer.Dac.CodeAnalysis.SqlRuleExecutionContext)
, che usaMicrosoft.SqlServer.Dac.CodeAnalysis.SqlRuleExecutionContext
come parametri di input. Questo metodo restituisce un elenco di potenziali problemi.Il metodo ottiene
Microsoft.SqlServer.Dac.Model.TSqlModel
,Microsoft.SqlServer.Dac.Model.TSqlObject
e TSqlFragment dal parametro di contesto. La classeWaitForDelayVisitor
viene quindi usata per ottenere un elenco di tutte le istruzioniWAITFOR DELAY
nel modello.Per ogni WaitForStatement in tale elenco, viene creato un oggetto
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); }
Nel menu File selezionare Salva.
Passaggio 4: compilare la libreria di classi
- Scegliere Proprietà SampleRules dal menu Progetto.
- Seleziona la scheda Firma.
- Selezionare Firma l’assembly.
- In Scegli un file chiave con nome sicuro, fare clic su <Nuovo>.
- Nella finestra di dialogo Crea chiave con nome sicuro, in Nome file di chiave, digitare
MyRefKey
. - (facoltativo) È possibile specificare una password per il file di chiave con nome sicuro.
- Seleziona OK.
- Scegliere Save All (Salva tutto) dal menu File.
- Scegliere Compila soluzione dal menu Compila.
- Scegliere Proprietà SampleRules dal menu Progetto.
- Seleziona la scheda Firma.
- Selezionare Firma l’assembly.
- In Scegli un file chiave con nome sicuro, fare clic su <Nuovo>.
- Nella finestra di dialogo Crea chiave con nome sicuro, in Nome file di chiave, digitare
MyRefKey
. - (facoltativo) È possibile specificare una password per il file di chiave con nome sicuro.
- Seleziona OK.
- Scegliere Save All (Salva tutto) dal menu File.
- Scegliere Compila soluzione dal menu Compila.
In Visual Studio Code aprire la finestra del terminale selezionando il menu Visualizza, quindi Terminale.
Immettere il comando seguente nel terminale per compilare il progetto:
dotnet build /p:Configuration=Release
Passare alla directory
SampleRules
.Eseguire il comando seguente per compilare il progetto:
dotnet build /p:Configuration=Release
Passaggio 5: installare e testare la nuova regola di analisi del codice
È quindi necessario installare l'assembly in modo che venga caricato quando si compilano progetti di database di SQL.
Per installare una regola che verrà eseguita quando si compila un progetto SQL originale con Visual Studio, è necessario copiare l'assembly e il file associato .pdb
nella cartella Estensioni.
Passaggio 5.1: installare l'assembly SampleRules
Successivamente, copiare le informazioni sull'assembly nella directory Estensioni. All'avvio di Visual Studio, le eventuali estensioni vengono identificate nella directory <Visual Studio Install Dir>\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\Extensions
e relative sottodirectory, quindi vengono rese disponibili per l'uso.
Per Visual Studio 2022, è <Visual Studio Install Dir>
in genere C:\Program Files\Microsoft Visual Studio\2022\Enterprise
. Sostituire Enterprise
con Professional
o Community
a seconda dell'edizione di Visual Studio installata.
Copiare il file di assembly SampleRules.dll dalla directory di output alla directory <Visual Studio Install Dir>\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\Extensions
. Per impostazione predefinita, il percorso del file .dll
compilato è YourSolutionPath\YourProjectPath\bin\Debug
o YourSolutionPath\YourProjectPath\bin\Release
.
Nota
Potrebbe essere necessario creare la directory Extensions
.
La regola verrà quindi installata e verrà visualizzata al riavvio di Visual Studio. Quindi, avviare una nuova sessione di Visual Studio e creare un progetto di database.
Passaggio 5.2: avviare una nuova sessione di Visual Studio e creare un progetto di database
- Avviare una seconda sessione di Visual Studio.
- Selezionare File>New (Nuovo) >Project (Progetto).
- Nella finestra di dialogo Nuovo progetto individuare e selezionare Progetto di database di SQL Server.
- Nella casella di testo Nome digitare
SampleRulesDB
e quindi selezionare OK.
Passaggio 5.3: abilitare la regola di analisi del codice AvoidWaitForRule
- In Esplora soluzioni selezionare il progetto
SampleRulesDB
. - Scegliere Proprietà dal menu Progetto. Verrà visualizzata la pagina proprietà
SampleRulesDB
. - Selezionare Analisi del codice. Verrà visualizzata una nuova categoria denominata
RuleSamples.CategorySamples
. - Espandere
RuleSamples.CategorySamples
. Dovrebbe essere visualizzatoSR1004: Avoid WAITFOR DELAY statement in stored procedures, triggers, and functions
. - Abilitare questa regola selezionando la casella di controllo accanto al nome della regola e alla casella di controllo Abilita l'analisi del codice nella compilazione. Per altre informazioni sull'abilitazione dell'analisi del codice, vedere Panoramica dell'analisi del codice.
- Quando viene usata l'azione di compilazione del progetto, la regola verrà eseguita e tutte le istruzioni
WAITFOR DELAY
trovate verranno segnalate come avvisi.
Per installare una regola che verrà eseguita quando si compila un progetto SQL originale con Visual Studio, è necessario copiare l'assembly e il file associato .pdb
nella cartella Estensioni.
Passaggio 5.1: installare l'assembly SampleRules
Successivamente, copiare le informazioni sull'assembly nella directory Estensioni. All'avvio di Visual Studio, le eventuali estensioni vengono identificate nella directory <Visual Studio Install Dir>\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\Extensions
e relative sottodirectory, quindi vengono rese disponibili per l'uso.
Per Visual Studio 2022, è <Visual Studio Install Dir>
in genere C:\Program Files\Microsoft Visual Studio\2022\Enterprise
. Sostituire Enterprise
con Professional
o Community
a seconda dell'edizione di Visual Studio installata.
Copiare il file di assembly SampleRules.dll dalla directory di output alla directory <Visual Studio Install Dir>\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\Extensions
. Per impostazione predefinita, il percorso del file .dll
compilato è YourSolutionPath\YourProjectPath\bin\Debug
o YourSolutionPath\YourProjectPath\bin\Release
.
Nota
Potrebbe essere necessario creare la directory Extensions
.
La regola verrà quindi installata e verrà visualizzata al riavvio di Visual Studio. Quindi, avviare una nuova sessione di Visual Studio e creare un progetto di database.
Passaggio 5.2: avviare una nuova sessione di Visual Studio e creare un progetto di database
- Avviare una seconda sessione di Visual Studio.
- Selezionare File>New (Nuovo) >Project (Progetto).
- Nella finestra di dialogo Nuovo progetto individuare e selezionare Progetto di database di SQL Server in stile SDK (anteprima).
- Nella casella di testo Nome digitare
SampleRulesDB
e quindi selezionare OK.
Passaggio 5.3: abilitare la regola di analisi del codice AvoidWaitForRule
- In Esplora soluzioni selezionare il progetto
SampleRulesDB
. - Doppio clic su un nodo del progetto per aprire il file di progetto. Il file di progetto
SampleRulesDB
viene visualizzato in un editor di testo. - Abilitare l'analisi del codice in fase di compilazione nel file di progetto SQL impostando la proprietà
RunSqlCodeAnalysis
sutrue
. - Quando viene usata l'azione di compilazione del progetto, la regola verrà eseguita e tutte le istruzioni
WAITFOR DELAY
trovate verranno segnalate come avvisi.
Una soluzione alternativa è disponibile per i progetti in stile SDK per installare regole personalizzate fino a quando non sono supportati i riferimenti ai pacchetti.
- Eseguire
dotnet restore
per ripristinare le dipendenze del progetto nel progetto SQL, assicurandosi che la cache dei pacchetti NuGet locale contenga Microsoft.Build.Sql. - Si noti la versione di Microsoft.Build.Sql usata nel file di progetto SQL, ad esempio
0.1.19-preview
. - Copiare il file di assembly
SampleRules.dll
dalla directory di output alla directory~/.nuget/packages/microsoft.build.sql/0.1.19-preview/tools/netstandard2.1
. Il percorso esatto della directory può variare a seconda della versione di Microsoft.Build.Sql usata nel file di progetto SQL. - Abilitare l'analisi del codice in fase di compilazione nel file di progetto SQL impostando la proprietà
RunSqlCodeAnalysis
sutrue
. - Eseguire
dotnet build
per compilare il progetto SQL ed eseguire la regola personalizzata.
Una soluzione alternativa è disponibile per i progetti in stile SDK per installare regole personalizzate fino a quando non sono supportati i riferimenti ai pacchetti.
- Eseguire
dotnet restore
per ripristinare le dipendenze del progetto nel progetto SQL, assicurandosi che la cache dei pacchetti NuGet locale contenga Microsoft.Build.Sql. - Si noti la versione di Microsoft.Build.Sql usata nel file di progetto SQL, ad esempio
0.1.19-preview
. - Copiare il file di assembly
SampleRules.dll
dalla directory di output alla directory~/.nuget/packages/microsoft.build.sql/0.1.19-preview/tools/netstandard2.1
. Il percorso esatto della directory può variare a seconda della versione di Microsoft.Build.Sql usata nel file di progetto SQL. - Abilitare l'analisi del codice in fase di compilazione nel file di progetto SQL impostando la proprietà
RunSqlCodeAnalysis
sutrue
. - Eseguire
dotnet build
per compilare il progetto SQL ed eseguire la regola personalizzata.