Delen via


Regels voor aangepaste codeanalyse maken

van toepassing op:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceSQL-database in Microsoft Fabric

In dit scenario ziet u de stappen die worden gebruikt voor het maken van een SQL Server-codeanalyseregel. De regel die in deze handleiding is gemaakt, wordt gebruikt om WAITFOR DELAY statements in opgeslagen procedures, triggers en functies te voorkomen.

In deze handleiding maakt u een aangepaste regel voor Transact-SQL-statische codeanalyse volgens de volgende stappen.

  1. Maak een klassebibliotheekproject, schakel ondertekening voor dat project in en voeg de benodigde verwijzingen toe.
  2. Maak twee helper C#-klassen.
  3. Maak een aangepaste C#-regelklasse.
  4. Bouw het klassebibliotheekproject.
  5. Installeer en test de nieuwe regel voor codeanalyse.

Met uitzondering van de instructies voor Visual Studio (SQL Server Data Tools) richt de handleiding zich op SQL-projecten in DE SDK-stijl.

Prerequisites

U hebt de volgende onderdelen nodig om dit scenario te voltooien:

  • Een versie van Visual Studio die SQL Server Data Tools bevat en ondersteuning biedt voor C# .NET Framework-ontwikkeling.
  • Een SQL Server-project dat SQL Server-objecten bevat.
  • Een exemplaar van SQL Server waarnaar u een databaseproject kunt implementeren.

Deze procedure is bedoeld voor gebruikers die al bekend zijn met de SQL Server-functies van SQL Server Data Tools. U moet bekend zijn met Visual Studio-concepten, zoals het maken van een klassebibliotheek, het toevoegen van NuGet-pakketten en het gebruik van de code-editor om code toe te voegen aan een klasse.

Note

Vanwege de preview-beperkingen van SQL Server Data Tools in SDK-stijl zijn meerdere Visual Studio-installaties vereist om dit scenario te voltooien. De eerste installatie is vereist voor het maken van het klassebibliotheekproject. De tweede installatie is vereist voor het maken van het SQL-databaseproject in DE SDK-stijl.

Deze procedure is bedoeld voor gebruikers die al bekend zijn met de SQL Server-functies van SQL Server Data Tools. U moet bekend zijn met Visual Studio-concepten, zoals het maken van een klassebibliotheek, het toevoegen van NuGet-pakketten en het gebruik van de code-editor om code toe te voegen aan een klasse.

  • Er is een versie van Visual Studio Code geïnstalleerd, die de extensie SQL Database Projects bevat.
  • Een SQL-databaseproject dat SQL-objecten bevat.
  • .NET 8 SDK
  • Aanbevolen: C# Dev Kit-extensie voor VS Code

Dit scenario is bedoeld voor gebruikers die al bekend zijn met de extensie SQL Database Projects in Visual Studio Code. U moet bekend zijn met ontwikkelingsconcepten, zoals het maken van een klassebibliotheek, het toevoegen van pakketten en het gebruik van de code-editor om code te bewerken.

  • Een teksteditor, zoals de bestandseditor in Visual Studio Code.
  • Een SQL-databaseproject dat SQL-objecten bevat.
  • .NET 8 SDK

Dit scenario is bedoeld voor gebruikers die al bekend zijn met SQL-projecten. U moet bekend zijn met ontwikkelingsconcepten, zoals het maken van een klassebibliotheek, het toevoegen van pakketten en het gebruik van de code-editor om code te bewerken.

Stap 1: Een klassebibliotheekproject maken

Maak eerst een klassebibliotheek. Een klassebibliotheekproject maken:

  1. Maak een C#-klassebibliotheekproject (.NET Framework) met de naam SampleRules.

  2. Wijzig de naam van het bestand Class1.cs in AvoidWaitForDelayRule.cs.

  3. Klik in Solution Explorer met de rechtermuisknop op het projectknooppunt en selecteer vervolgens Toevoegen en vervolgens Verwijzing.

  4. Selecteer System.ComponentModel.Composition op het tabblad Assembly's\Frameworks.

  5. Klik in Solution Explorer met de rechtermuisknop op het projectknooppunt en selecteer vervolgens NuGet-pakketten beheren. Zoek en installeer het Microsoft.SqlServer.DacFx NuGet-pakket. De geselecteerde versie moet worden 162.x.x (bijvoorbeeld 162.2.111) met Visual Studio 2022.

Voeg vervolgens ondersteunende klassen toe die door de regel worden gebruikt.

Maak eerst een klassebibliotheek. Een klassebibliotheekproject maken:

  1. Maak een C#-klassebibliotheekproject (.NET Framework) met de naam SampleRules.

  2. Wijzig de naam van het bestand Class1.cs in AvoidWaitForDelayRule.cs.

  3. Klik in Solution Explorer met de rechtermuisknop op het projectknooppunt en selecteer vervolgens Toevoegen en vervolgens Verwijzing.

  4. Selecteer System.ComponentModel.Composition op het tabblad Assembly's\Frameworks.

  5. Klik in Solution Explorer met de rechtermuisknop op het projectknooppunt en selecteer vervolgens NuGet-pakketten beheren. Zoek en installeer het Microsoft.SqlServer.DacFx NuGet-pakket. De geselecteerde versie moet worden 162.x.x (bijvoorbeeld 162.2.111) met Visual Studio 2022.

Voeg vervolgens ondersteunende klassen toe die door de regel worden gebruikt.

  1. Start Visual Studio Code en open de map waarin u het project wilt maken.

  2. Open een Terminal-venster in Visual Studio Code door het menu Weergave te selecteren en vervolgens op Terminalte klikken.

  3. Voer in de Terminalde volgende opdrachten in om een nieuwe oplossing en project te maken:

    dotnet new sln
    dotnet new classlib -n SampleRules -o SampleRules
    dotnet sln add SampleRules/SampleRules.csproj
    
  4. Ga naar de directory SampleRules:

    cd SampleRules
    
  5. Voeg het vereiste NuGet-pakket toe:

    dotnet add package Microsoft.SqlServer.DacFx
    

Voeg vervolgens ondersteunende klassen toe die door de regel worden gebruikt.

  1. Open een opdrachtprompt of terminalvenster en navigeer naar de map waarin u het project wilt maken.

  2. Voer in de Terminalde volgende opdrachten in om een nieuwe oplossing en project te maken:

    dotnet new sln
    dotnet new classlib -n SampleRules -o SampleRules
    dotnet sln add SampleRules/SampleRules.csproj
    
  3. Ga naar de directory SampleRules:

    cd SampleRules
    
  4. Voeg het vereiste NuGet-pakket toe:

    dotnet add package Microsoft.SqlServer.DacFx
    

Stap 2: Aangepaste helperklassen voor regels maken

Voordat u de klasse voor de regel zelf maakt, voegt u een bezoekersklasse en een kenmerkklasse toe aan het project. Deze klassen kunnen handig zijn voor het maken van meer aangepaste regels.

Stap 2.1: De klasse WaitForDelayVisitor definiëren

De eerste klasse die u moet definiëren, is de WaitForDelayVisitor klasse, afgeleid van TSqlConcreteFragmentVisitor. Deze klasse biedt toegang tot de WAITFOR DELAY instructies in het model. Bezoekersklassen maken gebruik van de ScriptDom API's van SQL Server. In deze API wordt Transact-SQL code weergegeven als een abstracte syntaxisstructuur (AST) en bezoekersklassen kunnen handig zijn wanneer u specifieke syntaxisobjecten zoals WAITFOR DELAY instructies wilt zoeken. Deze instructies zijn mogelijk moeilijk te vinden met behulp van het objectmodel omdat ze niet zijn gekoppeld aan een specifieke objecteigenschap of -relatie, maar u kunt deze vinden met behulp van het bezoekerspatroon en de ScriptDom-API.

  1. Selecteer in Solution Explorerhet SampleRules project.

  2. Selecteer Klasse toevoegenin het menu Project. Het dialoogvenster Nieuw item toevoegen wordt weergegeven. Typ in het tekstvak WaitForDelayVisitor.cs en selecteer vervolgens de knop toevoegen. Het bestand WaitForDelayVisitor.cs wordt toegevoegd aan het project in Solution Explorer-.

  1. Selecteer in Solution Explorerhet SampleRules project.

  2. Selecteer Klasse toevoegenin het menu Project. Het dialoogvenster Nieuw item toevoegen wordt weergegeven. Typ in het tekstvak WaitForDelayVisitor.cs en selecteer vervolgens de knop toevoegen. Het bestand WaitForDelayVisitor.cs wordt toegevoegd aan het project in Solution Explorer-.

  1. Open de -verkenner-weergave in Visual Studio Code.

  2. Maak een nieuw bestand met de naam WaitForDelayVisitor.cs in de map SampleRules.

  1. Navigeer naar de map SampleRules.
  2. Maak een nieuw bestand met de naam WaitForDelayVisitor.cs.
  1. Open het bestand WaitForDelayVisitor.cs en werk de inhoud bij zodat deze overeenkomt met de volgende code:

    using System.Collections.Generic;
    using Microsoft.SqlServer.TransactSql.ScriptDom;
    namespace SampleRules {
        class WaitForDelayVisitor {}
    }
    
  2. Wijzig in de klassedeclaratie de toegangswijziging in intern en leid de klasse af van TSqlConcreteFragmentVisitor:

    internal class WaitForDelayVisitor : TSqlConcreteFragmentVisitor {}
    
  3. Voeg de volgende code toe om de variabele Lijstlid te definiëren:

    public IList<WaitForStatement> WaitForDelayStatements { get; private set; }
    
  4. Definieer de klasseconstructor door de volgende code toe te voegen:

    public WaitForDelayVisitor() {
       WaitForDelayStatements = new List<WaitForStatement>();
    }
    
  5. Overschrijf de methode ExplicitVisit door de volgende code toe te voegen:

    public override void ExplicitVisit(WaitForStatement node) {
       // We are only interested in WAITFOR DELAY occurrences
       if (node.WaitForOption == WaitForOption.Delay)
          WaitForDelayStatements.Add(node);
    }
    

    Deze methode bezoekt de WAITFOR-instructies in het model en voegt instructies toe waarvoor de DELAY optie is opgegeven in de lijst met WAITFOR DELAY instructies. De sleutelklasse waarnaar wordt verwezen, is WaitForStatement-.

  6. In het menu Bestand, selecteer Opslaan.

Stap 2.2: Een resourcebestand en drie resourcereeksen toevoegen

Voeg vervolgens een resourcebestand toe dat de regelnaam, regelbeschrijving en de categorie definieert waarin de regel wordt weergegeven in de regelconfiguratie-interface.

  1. Selecteer in Solution Explorerhet SampleRules project. Selecteer in het menu ProjectToevoegen, en vervolgens Nieuw Item. Het dialoogvenster Nieuw item toevoegen wordt weergegeven.

  2. Selecteer in de lijst met Geïnstalleerde sjablonenAlgemeen. Selecteer in het detailvenster Resources-bestand.

  3. In naam , typ RuleResources.resx. De resource-editor wordt weergegeven, zonder dat er resources zijn gedefinieerd.

  4. Definieer vier resourcereeksen als volgt:

    Name Value
    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}.
  5. Selecteer in het menu Bestand de optie Opslaan voor RuleResources.resx.

  1. Selecteer in Solution Explorerhet SampleRules project. Selecteer in het menu ProjectToevoegen, en vervolgens Nieuw Item. Het dialoogvenster Nieuw item toevoegen wordt weergegeven.

  2. Selecteer in de lijst met Geïnstalleerde sjablonenAlgemeen. Selecteer in het detailvenster Resources-bestand.

  3. In naam , typ RuleResources.resx. De resource-editor wordt weergegeven, zonder dat er resources zijn gedefinieerd.

  4. Definieer vier resourcereeksen als volgt:

    Name Value
    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}.
  5. Selecteer in het menu Bestand de optie Opslaan voor RuleResources.resx.

  1. Maak in de map SampleRules een nieuw bestand met de naam RuleResources.resx.

  2. Open het bestand RuleResources.resx en voeg de volgende code toe:

    <?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>
    
  3. Sla het RuleResources.resx bestand op.

  4. Open het SampleRules.csproj bestand en voeg de volgende code toe om de resource-inhoud in het project bij te werken en op te nemen:

    <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>
    
  5. Sla het SampleRules.csproj bestand op.

  1. Maak in de map SampleRules een nieuw bestand met de naam RuleResources.resx.

  2. Open het bestand RuleResources.resx en voeg de volgende code toe:

    <?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>
    
  3. Sla het RuleResources.resx bestand op.

  4. Open het SampleRules.csproj bestand en voeg de volgende code toe om de resource-inhoud in het project bij te werken en op te nemen:

    <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>
    
  5. Sla het SampleRules.csproj bestand op.

Stap 2.3: De klasse LocalizedExportCodeAnalysisRuleAttribute definiëren

De tweede klasse is LocalizedExportCodeAnalysisRuleAttribute.cs. Dit is een uitbreiding van de ingebouwde Microsoft.SqlServer.Dac.CodeAnalysis.ExportCodeAnalysisRuleAttribute die door het framework wordt geleverd en ondersteunt het lezen van de DisplayName en Description die door uw regel worden gebruikt uit een bronnenbestand. Dit is een handige klasse als u ooit uw regels in meerdere talen wilt laten gebruiken.

  1. Selecteer in Solution Explorerhet SampleRules project.

  2. Selecteer Klasse toevoegenin het menu Project. Het dialoogvenster Nieuw item toevoegen wordt weergegeven. Typ in het tekstvak LocalizedExportCodeAnalysisRuleAttribute.cs en selecteer vervolgens de knop toevoegen. Het bestand wordt toegevoegd aan het project in Solution Explorer-.

  1. Selecteer in Solution Explorerhet SampleRules project.

  2. Selecteer Klasse toevoegenin het menu Project. Het dialoogvenster Nieuw item toevoegen wordt weergegeven. Typ in het tekstvak LocalizedExportCodeAnalysisRuleAttribute.cs en selecteer vervolgens de knop toevoegen. Het bestand wordt toegevoegd aan het project in Solution Explorer-.

  1. Navigeer naar de map SampleRules in de Explorer--weergave in Visual Studio Code.
  2. Maak een nieuw bestand met de naam LocalizedExportCodeAnalysisRuleAttribute.cs.
  1. Navigeer naar de map SampleRules.
  2. Maak een nieuw bestand met de naam LocalizedExportCodeAnalysisRuleAttribute.cs.
  1. Open het bestand en werk de inhoud bij zodat deze overeenkomt met de volgende code:

    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;
                }
            }
        }
    }
    

Stap 2.4: De klasse SampleConstants definiëren

Definieer vervolgens een klasse die verwijst naar de resources in het resourcebestand dat door Visual Studio wordt gebruikt om informatie over uw regel in de gebruikersinterface weer te geven.

  1. Selecteer in Solution Explorerhet SampleRules project.

  2. Selecteer in het menu ProjectToevoegen en Klasse. Het dialoogvenster Nieuw item toevoegen wordt weergegeven. Typ in het Naam tekstvak SampleRuleConstants.cs en selecteer de knop toevoegen. Het bestand SampleRuleConstants.cs wordt toegevoegd aan het project in Solution Explorer-.

  1. Selecteer in Solution Explorerhet SampleRules project.

  2. Selecteer in het menu ProjectToevoegen en Klasse. Het dialoogvenster Nieuw item toevoegen wordt weergegeven. Typ in het Naam tekstvak SampleRuleConstants.cs en selecteer de knop toevoegen. Het bestand SampleRuleConstants.cs wordt toegevoegd aan het project in Solution Explorer-.

  1. Navigeer naar de map SampleRules in de Explorer--weergave in Visual Studio Code.
  2. Maak een nieuw bestand met de naam SampleRuleConstants.cs.
  1. Navigeer naar de map SampleRules.
  2. Maak een nieuw bestand met de naam SampleRuleConstants.cs.
  1. Open het bestand SampleRuleConstants.cs en voeg het volgende toe met behulp van instructies aan het bestand:

    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";
        }
    }
    
  2. In het menu Bestand, selecteer Opslaan.

Stap 3: Een aangepaste regelklasse maken

Nadat u de helperklassen hebt toegevoegd die door de aangepaste codeanalyseregel worden gebruikt, maakt u een aangepaste regelklasse en geeft u deze de naam AvoidWaitForDelayRule. De AvoidWaitForDelayRule aangepaste regel wordt gebruikt om databaseontwikkelaars te helpen WAITFOR DELAY instructies in opgeslagen procedures, triggers en functies te voorkomen.

Stap 3.1: De klasse AvoidWaitForDelayRule maken

  1. Selecteer in Solution Explorerhet SampleRules project.

  2. Selecteer in het menu ProjectToevoegen en Klasse. Het dialoogvenster Nieuw item toevoegen wordt weergegeven. Typ in het tekstvak AvoidWaitForDelayRule.cs en selecteer Toevoegen. Het bestand AvoidWaitForDelayRule.cs wordt toegevoegd aan het project in Solution Explorer-.

  1. Selecteer in Solution Explorerhet SampleRules project.

  2. Selecteer in het menu ProjectToevoegen en Klasse. Het dialoogvenster Nieuw item toevoegen wordt weergegeven. Typ in het tekstvak AvoidWaitForDelayRule.cs en selecteer Toevoegen. Het bestand AvoidWaitForDelayRule.cs wordt toegevoegd aan het project in Solution Explorer-.

  1. Navigeer naar de map SampleRules in de Explorer--weergave in Visual Studio Code.
  2. Maak een nieuw bestand met de naam AvoidWaitForDelayRule.cs.
  1. Navigeer naar de map SampleRules.
  2. Maak een nieuw bestand met de naam AvoidWaitForDelayRule.cs.
  1. Open het bestand AvoidWaitForDelayRule.cs en voeg het volgende toe met behulp van instructies aan het bestand:

    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 {}
    }
    
  2. Wijzig in de AvoidWaitForDelayRule klassedeclaratie de toegangsmodificator naar 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
    
  3. De AvoidWaitForDelayRule-klasse afleiden uit de Microsoft.SqlServer.Dac.CodeAnalysis.SqlCodeAnalysisRule basisklasse:

    public sealed class AvoidWaitForDelayRule : SqlCodeAnalysisRule
    
  4. Voeg de LocalizedExportCodeAnalysisRuleAttribute toe aan uw klas.

    LocalizedExportCodeAnalysisRuleAttribute kan de codeanalyseservice aangepaste codeanalyseregels detecteren. Alleen klassen die zijn gemarkeerd met een ExportCodeAnalysisRuleAttribute (of een kenmerk dat hiervan overgaat) kunnen worden gebruikt in codeanalyse.

    LocalizedExportCodeAnalysisRuleAttribute bevat enkele vereiste metagegevens die door de service worden gebruikt. Dit omvat een unieke id voor deze regel, een weergavenaam die wordt weergegeven in de Gebruikersinterface van Visual Studio en een Description die door uw regel kan worden gebruikt bij het identificeren van problemen.

    [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";
    }
    

    De eigenschap RuleScope moet worden Microsoft.SqlServer.Dac.CodeAnalysis.SqlRuleScope.Element omdat deze regel specifieke elementen analyseert. De regel wordt eenmaal aangeroepen voor elk overeenkomend element in het model. Als u een volledig model wilt analyseren, kunt u in plaats daarvan Microsoft.SqlServer.Dac.CodeAnalysis.SqlRuleScope.Model gebruiken.

  5. Voeg een constructor toe waarmee de Microsoft.SqlServer.Dac.CodeAnalysis.SqlAnalysisRule.SupportedElementTypes wordt ingesteld. Dit is vereist voor regels op elementniveau. Hiermee worden de typen elementen gedefinieerd waarop deze regel van toepassing is. In dit geval wordt de regel toegepast op opgeslagen procedures, triggers en functies. De Microsoft.SqlServer.Dac.Model.ModelSchema klasse bevat alle beschikbare elementtypen die kunnen worden geanalyseerd.

    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
       };
    }
    
  6. Voeg een overschrijving toe voor de methode Microsoft.SqlServer.Dac.CodeAnalysis.SqlAnalysisRule.Analyze(Microsoft.SqlServer.Dac.CodeAnalysis.SqlRuleExecutionContext), die Microsoft.SqlServer.Dac.CodeAnalysis.SqlRuleExecutionContext als invoerparameters gebruikt. Deze methode retourneert een lijst met mogelijke problemen.

    De methode verkrijgt de Microsoft.SqlServer.Dac.Model.TSqlModel-, Microsoft.SqlServer.Dac.Model.TSqlObject- en -TSqlFragment van de contextparameter. De WaitForDelayVisitor-klasse wordt vervolgens gebruikt om een lijst met alle WAITFOR DELAY instructies in het model te verkrijgen.

    Voor elke WaitForStatement- in die lijst wordt een Microsoft.SqlServer.Dac.CodeAnalysis.SqlRuleProblem gemaakt.

    /// <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);
    }
    
  7. Selecteer Opslaanin het menu Bestand.

Stap 4: De klassebibliotheek bouwen

  1. Selecteer in het menu Project het SampleRules Properties.
  2. Selecteer het tabblad ondertekenen.
  3. Selecteer Onderteken de assembly.
  4. Selecteer in Kies een sterke sleutelbestandsnaam<Nieuw>.
  5. In het dialoogvenster Sterke Naam Sleutel Maken, typ bij MyRefKey.
  6. (optioneel) U kunt een wachtwoord opgeven voor uw sterke naamsleutelbestand.
  7. Kies OK.
  8. Selecteer in het menu Bestand de optie Alles opslaan.
  9. Selecteer in het menu BuildBuild Solution.
  1. Selecteer in het menu Project het SampleRules Properties.
  2. Selecteer het tabblad ondertekenen.
  3. Selecteer Onderteken de assembly.
  4. Selecteer in Kies een sterke sleutelbestandsnaam<Nieuw>.
  5. In het dialoogvenster Sterke Naam Sleutel Maken, typ bij MyRefKey.
  6. (optioneel) U kunt een wachtwoord opgeven voor uw sterke naamsleutelbestand.
  7. Kies OK.
  8. Selecteer in het menu Bestand de optie Alles opslaan.
  9. Selecteer in het menu BuildBuild Solution.
  1. Open het Terminal-venster in Visual Studio Code door het menu Weergave te selecteren en Terminal.

  2. Voer in de Terminal-de volgende opdracht in om het project te bouwen:

    dotnet build /p:Configuration=Release
    
  1. Navigeer naar de map SampleRules.

  2. Voer de volgende opdracht uit om het project te bouwen:

    dotnet build /p:Configuration=Release
    

Stap 5: De nieuwe regel voor codeanalyse installeren en testen

Vervolgens moet u de assembly installeren zodat deze wordt geladen wanneer u een SQL-databaseproject bouwt.

Als u een regel wilt installeren die wordt uitgevoerd wanneer u een oorspronkelijk SQL-project bouwt met Visual Studio, moet u de assembly en het bijbehorende .pdb-bestand kopiëren naar de map Extensies.

Stap 5.1: De SampleRules-assembly installeren

  1. Kopieer vervolgens de assembly-gegevens naar de map Extensies. Wanneer Visual Studio wordt gestart, worden eventuele extensies in <Visual Studio Install Dir>\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\Extensions directory en submappen geïdentificeerd en kunnen ze worden gebruikt. Voor Visual Studio 2022 is de <Visual Studio Install Dir> meestal C:\Program Files\Microsoft Visual Studio\2022\Enterprise. Vervang Enterprise door Professional of Community, afhankelijk van de Visual Studio-editie die u hebt geïnstalleerd.
  2. Kopieer het SampleRules.dll assemblybestand uit de uitvoermap naar de <Visual Studio Install Dir>\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\Extensions map. Standaard is het pad van het gecompileerde .dll-bestand YourSolutionPath\YourProjectPath\bin\Debug of YourSolutionPath\YourProjectPath\bin\Release.

Note

Mogelijk moet u de Extensions directory maken.

Uw regel moet nu worden geïnstalleerd en wordt weergegeven wanneer u Visual Studio opnieuw start. Start vervolgens een nieuwe sessie van Visual Studio en maak een databaseproject.

Stap 5.2: Een nieuwe Visual Studio-sessie starten en een databaseproject maken

  1. Start een tweede sessie van Visual Studio.
  2. Selecteer Bestand>Nieuw>Project.
  3. Zoek en selecteer in het dialoogvenster New Project de optie SQL Server Database Project.
  4. Typ in het tekstvak SampleRulesDB en selecteer OK.

Stap 5.3: De AvoidWaitForRule-codeanalysetregel inschakelen

  1. Selecteer in Solution Explorerhet SampleRulesDB project.
  2. Selecteer Eigenschappenin het Project menu. De eigenschappenpagina SampleRulesDB wordt weergegeven.
  3. Selecteer Codeanalyse. U zou een nieuwe categorie met de naam RuleSamples.CategorySamplesmoeten zien.
  4. Vouw RuleSamples.CategorySamplesuit. U zou SR1004: Avoid WAITFOR DELAY statement in stored procedures, triggers, and functionsmoeten zien.
  5. Schakel deze regel in door het selectievakje naast de naam van de regel en het selectievakje voor Codeanalyse inschakelen op buildin te schakelen. Zie het overzicht van codeanalysevoor meer informatie over het inschakelen van codeanalyse.
  6. Wanneer de project build-actie wordt gebruikt, zal de regel worden uitgevoerd en zullen alle gevonden WAITFOR DELAY-instructies als waarschuwingen worden gerapporteerd.

Als u een regel wilt installeren die wordt uitgevoerd wanneer u een oorspronkelijk SQL-project bouwt met Visual Studio, moet u de assembly en het bijbehorende .pdb-bestand kopiëren naar de map Extensies.

Stap 5.1: De SampleRules-assembly installeren

  1. Kopieer vervolgens de assembly-gegevens naar de map Extensies. Wanneer Visual Studio wordt gestart, worden eventuele extensies in <Visual Studio Install Dir>\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\Extensions directory en submappen geïdentificeerd en kunnen ze worden gebruikt. Voor Visual Studio 2022 is de <Visual Studio Install Dir> meestal C:\Program Files\Microsoft Visual Studio\2022\Enterprise. Vervang Enterprise door Professional of Community, afhankelijk van uw geïnstalleerde Visual Studio-editie.
  2. Kopieer het SampleRules.dll assemblybestand uit de uitvoermap naar de <Visual Studio Install Dir>\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\Extensions map. Standaard is het pad van het gecompileerde .dll-bestand YourSolutionPath\YourProjectPath\bin\Debug of YourSolutionPath\YourProjectPath\bin\Release.

Note

Mogelijk moet u de Extensions directory maken.

Uw regel moet nu worden geïnstalleerd en wordt weergegeven wanneer u Visual Studio opnieuw start. Start vervolgens een nieuwe sessie van Visual Studio en maak een databaseproject.

Stap 5.2: Een nieuwe Visual Studio-sessie starten en een databaseproject maken

  1. Start een tweede sessie van Visual Studio.
  2. Selecteer Bestand>Nieuw>Project.
  3. Zoek en selecteer in het dialoogvenster Nieuw project de SQL Server Database Project, SDK-stijl (preview).
  4. Typ in het tekstvak SampleRulesDB en selecteer OK.

Stap 5.3: De AvoidWaitForRule-codeanalysetregel inschakelen

  1. Selecteer in Solution Explorerhet SampleRulesDB project.
  2. Dubbelklik op het projectknooppunt om het projectbestand te openen. Het SampleRulesDB projectbestand wordt weergegeven in een teksteditor.
  3. Schakel codeanalyse in op build- in het SQL-projectbestand door de eigenschap RunSqlCodeAnalysis in te stellen op true.
  4. Wanneer de project build-actie wordt gebruikt, zal de regel worden uitgevoerd en zullen alle gevonden WAITFOR DELAY-instructies als waarschuwingen worden gerapporteerd.

Stap 5.1: Plaats de SampleRules-assembly in een lokale NuGet-bron

  1. Als u geen lokale bron voor NuGet-pakketten hebt, voegt u een map toe op uw lokale computer om de NuGet-pakketten op te slaan voor lokaal testen. U kunt uw huidige NuGet-bronnen controleren door de volgende opdracht uit te voeren:
dotnet nuget list source
  1. Als een lokale bron niet wordt vermeld, kunt u er een toevoegen met behulp van de volgende opdracht, waarbij u <local folder path> vervangt door het pad naar uw lokale map, zoals C:\NuGetPackages of ~/NuGetPackages:
dotnet nuget add source <local folder path>
  1. Kopieer het SampleRules.dll assemblybestand uit de uitvoermap naar de lokale NuGet-bronmap. Standaard is het pad van het gecompileerde .dll-bestand YourSolutionPath\YourProjectPath\bin\Debug of YourSolutionPath\YourProjectPath\bin\Release.

Stap 5.2: SampleRules gebruiken in een databaseproject

  1. Maak een nieuw Microsoft.Build.Sql-project of open een bestaand project.
  2. Voeg een pakketreferentie toe aan het SampleRules NuGet-pakket in het projectbestand. In het volgende voorbeeld ziet u hoe u een verwijzing toevoegt naar het NuGet-pakket SampleRules in het .sqlproj-bestand:
<ItemGroup>
  <PackageReference Include="SampleRules" Version="1.0.0" />
</ItemGroup>

Stap 5.3: Codeanalyse inschakelen op build

  1. Schakel codeanalyse in op build- in het SQL-projectbestand door de eigenschap RunSqlCodeAnalysis in te stellen op true. Het NuGet-pakket SampleRules wordt hersteld wanneer het project standaard is gebouwd en opgenomen.
  2. Wanneer de project build-actie wordt gebruikt, zal de regel worden uitgevoerd en zullen alle gevonden WAITFOR DELAY-instructies als waarschuwingen worden gerapporteerd.

Stap 5.1: Plaats de SampleRules-assembly in een lokale NuGet-bron

  1. Als u geen lokale bron voor NuGet-pakketten hebt, voegt u een map toe op uw lokale computer om de NuGet-pakketten op te slaan voor lokaal testen. U kunt uw huidige NuGet-bronnen controleren door de volgende opdracht uit te voeren:
dotnet nuget list source
  1. Als een lokale bron niet wordt vermeld, kunt u er een toevoegen met behulp van de volgende opdracht, waarbij u <local folder path> vervangt door het pad naar uw lokale map, zoals C:\NuGetPackages of ~/NuGetPackages:
dotnet nuget add source <local folder path>
  1. Kopieer het SampleRules.dll assemblybestand uit de uitvoermap naar de lokale NuGet-bronmap. Standaard is het pad van het gecompileerde .dll-bestand YourSolutionPath\YourProjectPath\bin\Debug of YourSolutionPath\YourProjectPath\bin\Release.

Stap 5.2: SampleRules gebruiken in een databaseproject

  1. Maak een nieuw Microsoft.Build.Sql-project of open een bestaand project.
  2. Voeg een pakketreferentie toe aan het SampleRules NuGet-pakket in het projectbestand. In het volgende voorbeeld ziet u hoe u een verwijzing toevoegt naar het NuGet-pakket SampleRules in het .sqlproj-bestand:
<ItemGroup>
  <PackageReference Include="SampleRules" Version="1.0.0" />
</ItemGroup>

Stap 5.3: Codeanalyse inschakelen op build

  1. Schakel codeanalyse in op build- in het SQL-projectbestand door de eigenschap RunSqlCodeAnalysis in te stellen op true. Het NuGet-pakket SampleRules wordt hersteld wanneer het project standaard is gebouwd en opgenomen.
  2. Wanneer de project build-actie wordt gebruikt, zal de regel worden uitgevoerd en zullen alle gevonden WAITFOR DELAY-instructies als waarschuwingen worden gerapporteerd.