Freigeben über


Exemplarische Vorgehensweise: Erstellen einer benutzerdefinierten Regelassembly für die statische Codeanalyse in SQL

In diesem Thema wird schrittweise das Verfahren zum Erstellen einer SQL-Codeanalyseregel veranschaulicht. Die mit dieser exemplarischen Vorgehensweise erstellte Regel wird verwendet, um WAITFOR DELAY-Anweisungen in gespeicherten Prozeduren, Triggern und Funktionen zu vermeiden.

In dieser exemplarischen Vorgehensweise wird mithilfe der folgenden Prozesse eine benutzerdefinierte Regel für die Analyse von statischem Transact-SQL-Code erstellt:

  1. Erstellen Sie eine Klassenbibliothek, aktivieren Sie die Signierung für das Projekt, und fügen Sie die erforderlichen Verweise hinzu.

  2. Erstellen Sie zwei C#-Hilfsklassen.

  3. Erstellen Sie eine benutzerdefinierte C#-Regelklasse.

  4. Erstellen Sie eine XML-Datei, die zum Registrieren der Assembly verwendet wird.

  5. Kopieren Sie die von Ihnen erstellte DLL- und die XML-Datei in das Erweiterungsverzeichnis, um diese zu registrieren.

  6. Überprüfen Sie, ob die neue Codeanalyseregel richtig positioniert ist.

Vorbereitungsmaßnahmen

Sie können diese exemplarische Vorgehensweise nur ausführen, wenn Visual Studio Premium oder Visual Studio Ultimate installiert ist.

Erstellen einer benutzerdefinierten Codeanalyseregel für SQL

Zuerst erstellen Sie eine Klassenbibliothek.

So erstellen Sie eine Klassenbibliothek

  1. Klicken Sie im Menü Datei auf Neu und anschließend auf Projekt.

  2. Klicken Sie im Dialogfeld Neues Projekt in der Liste Installierte Vorlagen auf Visual C#.

  3. Wählen Sie im Detailbereich die Option Klassenbibliothek aus.

  4. Geben Sie im Textfeld Name die Zeichenfolge "SampleRules" ein, und klicken Sie auf OK.

Anschließend signieren Sie das Projekt.

So aktivieren Sie das Signieren für das Projekt

  1. Markieren Sie im Projektmappen-Explorer den Projektknoten SampleRules , klicken Sie im Menü Projekt auf Eigenschaften (oder klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektknoten, und klicken Sie dann auf Eigenschaften).

  2. Klicken Sie auf die Registerkarte Signierung.

  3. Aktivieren Sie das Kontrollkästchen Assembly signieren.

  4. Geben Sie eine neue Schlüsseldatei an. Wählen Sie in der Dropdownliste Schlüsseldatei mit starkem Namen auswählen die Option <Neu...> aus.

    Das Dialogfeld Schlüssel für einen starken Namen erstellen wird geöffnet. Weitere Informationen finden Sie unter Dialogfeld "Schlüssel für einen starken Namen erstellen".

  5. Geben Sie im Dialogfeld Schlüssel für einen starken Namen erstellen im Textfeld Name die Zeichenfolge "SampleRulesKey" für die neue Schlüsseldatei ein. In dieser exemplarischen Vorgehensweise müssen Sie kein Kennwort angeben. Weitere Informationen finden Sie unter Verwalten der Signierung von Assemblys und Manifesten.

Als Nächstes fügen Sie dem Projekt die erforderlichen Verweise hinzu.

So fügen Sie dem Projekt die zutreffenden Verweise hinzu

  1. Wählen Sie im Projektmappen-Explorer das Projekt SampleRules aus.

  2. Klicken Sie im Menü Projekt auf Verweis hinzufügen.

    Das Dialogfeld Verweis hinzufügen wird geöffnet. Weitere Informationen finden Sie unter Gewusst wie: Hinzufügen oder Entfernen von Verweisen in Visual Studio.

  3. Wählen Sie die Registerkarte .NET aus.

  4. Suchen Sie in der Spalte Komponentenname die folgenden Komponenten:

    Tipp

    Wenn Sie mehrere Komponenten auswählen möchten, halten Sie STRG gedrückt, während Sie auf die einzelnen Komponenten klicken.

  5. Klicken Sie auf OK, nachdem Sie alle erforderlichen Komponenten ausgewählt haben.

    Die ausgewählten Verweise werden im Projektmappen-Explorer unter dem Knoten Verweise des Projekts angezeigt.

Erstellen der benutzerdefinierten unterstützenden Klassen für Codeanalyseregeln

Bevor Sie die Klasse für die Regel selbst erstellen, werden dem Projekt eine Besucherklasse und eine Hilfsklasse hinzugefügt.

Tipp

Diese Klassen können beim Erstellen zusätzlicher benutzerdefinierter Regeln nützlich sein.

Die erste zu definierende Klasse ist die WaitForDelayVisitor-Klasse, die von TSqlConcreteFragmentVisitor abgeleitet wird. Diese Klasse ermöglicht den Zugriff auf die WAITFOR DELAY-Anweisungen im Modell.

So definieren Sie die WaitForDelayVisitor-Klasse

  1. Wählen Sie im Projektmappen-Explorer das Projekt SampleRules aus.

  2. Klicken Sie im Menü Projekt auf Klasse hinzufügen.

    Das Dialogfeld Neues Element hinzufügen wird angezeigt.

  3. Geben Sie im Textfeld Name den Namen "WaitForDelayVisitor.cs" ein, und klicken Sie anschließend auf die Schaltfläche Hinzufügen.

    Die Datei "WaitForDelayVisitor.cs" wird dem Projekt im Projektmappen-Explorer hinzugefügt.

  4. Öffnen Sie die Datei "WaitForDelayVisitor.cs", und aktualisieren Sie den Inhalt mit folgendem Code:

    using System.Collections.Generic;
    using Microsoft.Data.Schema.ScriptDom.Sql;
    
    namespace SampleRules
    {
        class WaitForDelayVistor
        {
        }
    }
    
  5. Legen Sie in der Klassendeklaration den Zugriffsmodifizierer als intern fest, und leiten Sie die Klasse von TSqlConcreteFragmentVisitor ab:

        internal class WaitForDelayVisitor : TSqlConcreteFragmentVisitor
        {
        }
    
  6. Fügen Sie den folgenden Code hinzu, um die List-Membervariable zu definieren:

            private List<WaitForStatement> _waitForDelayStatments;
    
  7. Definieren Sie den Klassenkonstruktor, indem Sie den folgenden Code hinzufügen:

            #region ctor
            public WaitForDelayVisitor()
            {
                _waitForDelayStatments = new List<WaitForStatement>();
            }
            #endregion
    
  8. Definieren Sie die schreibgeschützte WaitForDelayStatements-Eigenschaft, indem Sie den folgenden Code hinzufügen:

            #region properties
            public List<WaitForStatement> WaitForDelayStatements
            {
                get
                {
                    return _waitForDelayStatments;
                }
            }
            #endregion
    
  9. Setzen Sie die ExplicitVisit-Methode außer Kraft, indem Sie den folgenden Code hinzufügen:

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

    Mit dieser Methode werden die WAITFOR-Anweisungen im Modell überprüft, und die Anweisungen, für die die DELAY-Option angegeben ist, werden der Liste mit den WAITFOR DELAY-Anweisungen hinzugefügt. Die hier referenzierte Hauptklasse ist WaitForStatement.

  10. Klicken Sie im Menü Datei auf Speichern.

Die zweite Klasse ist "SqlRuleUtils.cs". Diese Klasse enthält einige Hilfsprogrammmethoden, die von der benutzerdefinierten Klasse für Codeanalyseregeln verwendet werden, die Sie später in dieser exemplarischen Vorgehensweise im Abschnitt Erstellen der benutzerdefinierten Codeanalyseregelklasse erstellen. Tests können auf folgende Weisen ausgeführt werden:

  • GetElementName: Dient zum Abrufen des mit Escapezeichen versehenen, vollqualifizierten Namens eines Modellelements.

  • UpdateProblemPosition Wird verwendet, um Zeilen- und Spalteninformationen zu berechnen.

  • ReadFileContent Wird verwendet, um Inhalt in einer Datei zu lesen.

  • GetElementSourceFile Wird verwendet, um die Quelldatei abzurufen.

  • ComputeLineColumn Wird verwendet, um den Offset von ScriptDom in Zeile und Spalte von Skriptdateien zu konvertieren.

So fügen Sie dem Projekt die Datei SqlRuleUtils.cs hinzu

  1. Wählen Sie im Projektmappen-Explorer das Projekt SampleRules aus.

  2. Klicken Sie im Menü Projekt auf Klasse hinzufügen.

    Das Dialogfeld Neues Element hinzufügen wird angezeigt.

  3. Geben Sie im Textfeld Name den Namen "SqlRuleUtils.cs" ein, und klicken Sie anschließend auf die Schaltfläche Hinzufügen.

    Die Datei SqlRuleUtils.cs wird dem Projekt im Projektmappen-Explorer hinzugefügt.

  4. Öffnen Sie die Datei SqlRuleUtils.cs, und fügen Sie der Datei die folgenden using-Anweisungen hinzu:

    using System;
    using System.Diagnostics;
    using System.IO;
    using Microsoft.Data.Schema.SchemaModel;
    using Microsoft.Data.Schema.Sql.SchemaModel;
    using Microsoft.Data.Schema.StaticCodeAnalysis;
    using Microsoft.Data.Schema;
    
    
    namespace SampleRules
    {
    }
    
  5. Ändern Sie in der SqlRuleUtils-Klassendeklaration den Zugriffsmodifizierer zu "public static":

        public static class SqlRuleUtils
        {
        }
    
  6. Fügen Sie den folgenden Code hinzu, um die GetElementName-Methode zu erstellen, von der SqlSchemaModel und ISqlModelElement als Eingabeparameter verwendet werden:

            /// <summary>
            /// Get escaped fully qualified name of a model element 
            /// </summary>
            /// <param name="sm">schema model</param>
            /// <param name="element">model element</param>
            /// <returns>name of the element</returns>
            public static string GetElementName(SqlSchemaModel sm, ISqlModelElement element)
            {
                return sm.DatabaseSchemaProvider.UserInteractionServices.GetElementName(element, ElementNameStyle.EscapedFullyQualifiedName);
            }
    
  7. Fügen Sie den folgenden Code hinzu, um die ReadFileContent-Methode zu erstellen:

            /// <summary>
            /// Read file content from a file.
            /// </summary>
            /// <param name="filePath"> file path </param>
            /// <returns> file content in a string </returns>
            public static string ReadFileContent(string filePath)
            {
                //  Verify that the file exists first.
                if (!File.Exists(filePath))
                {
                    Debug.WriteLine(string.Format("Cannot find the file: '{0}'", filePath));
                    return string.Empty;
                }
    
                string content;
                using (StreamReader reader = new StreamReader(filePath))
                {
                    content = reader.ReadToEnd();
                    reader.Close();
                }
                return content;
            }
    
  8. Fügen Sie den folgenden Code hinzu, um die GetElementSourceFile-Methode zu erstellen, die IModelElement als Eingabeparameter und String zum Abrufen des Dateinamens verwendet. Die Methode wandelt das IModelElement in IScriptSourcedModelElement um und bestimmt dann anhand von ISourceInformation den Skriptdateipfad im Modellelement.

            /// <summary>
            /// Get the corresponding script file path from a model element.
            /// </summary>
            /// <param name="element">model element</param>
            /// <param name="fileName">file path of the scripts corresponding to the model element</param>
            /// <returns></returns>
            private static Boolean GetElementSourceFile(IModelElement element, out String fileName)
            {
                fileName = null;
    
                IScriptSourcedModelElement scriptSourcedElement = element as IScriptSourcedModelElement;
                if (scriptSourcedElement != null)
                {
                    ISourceInformation elementSource = scriptSourcedElement.PrimarySource;
                    if (elementSource != null)
                    {
                        fileName = elementSource.SourceName;
                    }
                }
    
                return String.IsNullOrEmpty(fileName) == false;
            }
    
  9. Fügen Sie den folgenden Code hinzu, um die ComputeLineColumn-Methode zu erstellen:

            /// This method converts offset from ScriptDom to line\column in script files.
            /// A line is defined as a sequence of characters followed by a carriage return ("\r"), 
            /// a line feed ("\n"), or a carriage return immediately followed by a line feed. 
            public static bool ComputeLineColumn(string text, Int32 offset, Int32 length,
                                                out Int32 startLine, out Int32 startColumn, out Int32 endLine, out Int32 endColumn)
            {
                const char LF = '\n';
                const char CR = '\r';
    
                // Setting the initial value of line and column to 0 since VS auto-increments by 1.
                startLine = 0;
                startColumn = 0;
                endLine = 0;
                endColumn = 0;
    
                int textLength = text.Length;
    
                if (offset < 0 || length < 0 || offset + length > textLength)
                {
                    return false;
                }
    
                for (int charIndex = 0; charIndex < length + offset; ++charIndex)
                {
                    char currentChar = text[charIndex];
                    Boolean afterOffset = charIndex >= offset;
                    if (currentChar == LF)
                    {
                        ++endLine;
                        endColumn = 0;
                        if (afterOffset == false)
                        {
                            ++startLine;
                            startColumn = 0;
                        }
                    }
                    else if (currentChar == CR)
                    {
                        // CR/LF combination, consuming LF.
                        if ((charIndex + 1 < textLength) && (text[charIndex + 1] == LF))
                        {
                            ++charIndex;
                        }
    
                        ++endLine;
                        endColumn = 0;
                        if (afterOffset == false)
                        {
                            ++startLine;
                            startColumn = 0;
                        }
                    }
                    else
                    {
                        ++endColumn;
                        if (afterOffset == false)
                        {
                            ++startColumn;
                        }
                    }
                }
    
                return true;
            }
    
  10. Fügen Sie den folgenden Code hinzu, um die UpdateProblemPosition-Methode zu erstellen, die DataRuleProblem als Eingabeparameter verwendet:

            /// <summary>
            /// Compute the start Line/Col and the end Line/Col to update problem info
            /// </summary>
            /// <param name="problem">problem found</param>
            /// <param name="offset">offset of the fragment having problem</param>
            /// <param name="length">length of the fragment having problem</param>
            public static void UpdateProblemPosition(DataRuleProblem problem, int offset, int length)
            {
                if (problem.ModelElement != null)
                {
                    String fileName = null;
                    int startLine = 0;
                    int startColumn = 0;
                    int endLine = 0;
                    int endColumn = 0;
    
                    bool ret = GetElementSourceFile(problem.ModelElement, out fileName);
                    if (ret)
                    {
                        string fullScript = ReadFileContent(fileName);
    
                        if (fullScript != null)
                        {
                            if (ComputeLineColumn(fullScript, offset, length, out startLine, out startColumn, out endLine, out endColumn))
                            {
                                problem.FileName = fileName;
                                problem.StartLine = startLine + 1;
                                problem.StartColumn = startColumn + 1;
                                problem.EndLine = endLine + 1;
                                problem.EndColumn = endColumn + 1;
                            }
                            else
                            {
                                Debug.WriteLine("Could not compute line and column");
                            }
                        }
                    }
                }
            }
    
  11. Klicken Sie im Menü Datei auf Speichern.

Im nächsten Schritt wird eine Ressourcendatei hinzugefügt, mit der der Regelname, die Regelbeschreibung und die Kategorie definiert werden, in der die Regel in der Regelkonfiguration angezeigt wird.

So fügen Sie eine Ressourcendatei und drei Ressourcenzeichenfolgen hinzu

  1. Wählen Sie im Projektmappen-Explorer das Projekt SampleRules aus.

  2. Klicken Sie im Menü Projekt auf Neues Element hinzufügen.

    Das Dialogfeld Neues Element hinzufügen wird angezeigt.

  3. Klicken Sie in der Liste Installierte Vorlagen auf Allgemein.

  4. Klicken Sie im Detailbereich auf Ressourcendatei.

  5. Geben Sie im Feld Name den Namen SampleRuleResource.resx ein.

    Der Ressourcen-Editor wird angezeigt, enthält allerdings noch keine definierten Ressourcen.

  6. Gehen Sie folgendermaßen vor, um drei Ressourcenzeichenfolgen zu definieren:

    Name

    Wert

    AvoidWaitForDelay_ProblemDescription

    WAITFOR DELAY-Anweisung gefunden in "{0}".

    AvoidWaitForDelay_RuleName

    Vermeiden Sie WAITFOR DELAY-Anweisung in gespeicherten Prozeduren, Triggern und Funktionen.

    CategorySamples

    SamplesCategory

  7. Klicken Sie im Menü Datei auf SampleRuleResource.resx speichern.

Im nächsten Schritt wird eine Klasse definiert, von der auf die Ressourcen in der Ressourcendatei verwiesen wird, die von Visual Studio verwendet werden, um auf der Benutzeroberfläche Informationen zur Regel anzuzeigen.

So definieren Sie die SampleConstants-Klasse

  1. Wählen Sie im Projektmappen-Explorer das Projekt SampleRules aus.

  2. Klicken Sie im Menü Projekt auf Klasse hinzufügen.

    Das Dialogfeld Neues Element hinzufügen wird angezeigt.

  3. Geben Sie im Textfeld Name den Namen "SampleRuleConstants.cs" ein, und klicken Sie anschließend auf die Schaltfläche Hinzufügen.

    Die Datei "SampleRuleConstants.cs" wird dem Projekt im Projektmappen-Explorer hinzugefügt.

  4. Öffnen Sie die Datei "SampleRuleConstants.cs", und fügen Sie der Datei die folgenden using-Anweisungen hinzu:

    namespace SampleRules
    {
        internal class SampleConstants
        {
            public const string NameSpace = "SamplesRules";
            public const string ResourceBaseName = "SampleRules.SampleRuleResource";
            public const string CategorySamples = "CategorySamples";
    
            public const string AvoidWaitForDelayRuleId = "SR1004";
            public const string AvoidWaitForDelay_RuleName = "AvoidWaitForDelay_RuleName";
            public const string AvoidWaitForDelay_ProblemDescription = "AvoidWaitForDelay_ProblemDescription";
        }
    }
    
  5. Klicken Sie im Menü Datei auf Speichern.

Erstellen der benutzerdefinierten Klasse für Codeanalyseregeln

Da Sie nun die Hilfsklassen hinzugefügt haben, die von der benutzerdefinierten Codeanalyseregel verwendet werden, erstellen Sie eine benutzerdefinierte Regelklasse und benennen diese mit AvoidWaitForDelayRule. Mit der benutzerdefinierten AvoidWaitForDelayRule-Regel können Datenbankentwicklern WAITFOR DELAY-Anweisungen in gespeicherten Prozeduren, Triggern und Funktionen leichter vermeiden.

So erstellen Sie die AvoidWaitForDelayRule-Klasse

  1. Wählen Sie im Projektmappen-Explorer das Projekt SampleRules aus.

  2. Wählen Sie im Menü Projekt die Option Neuer Ordner.

  3. Im Projektmappen-Explorer wird ein neuer Ordner angezeigt. Benennen Sie den Ordner mit AvoidWaitForDelayRule.

  4. Überprüfen Sie im Projektmappen-Explorer, ob der Ordner AvoidWaitForDelayRule ausgewählt ist.

  5. Klicken Sie im Menü Projekt auf Klasse hinzufügen.

    Das Dialogfeld Neues Element hinzufügen wird angezeigt.

  6. Geben Sie im Textfeld Name den Namen "AvoidWaitForDelayRule.cs" ein, und klicken Sie anschließend auf die Schaltfläche Hinzufügen.

    Die Datei AvoidWaitForDelayRule.cs wird im Projektmappen-Explorer dem Ordner AvoidWaitForDelayRule des Projekts hinzugefügt.

  7. Öffnen Sie die Datei AvoidWaitForDelayRule.cs, und fügen Sie der Datei die folgenden using-Anweisungen hinzu:

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Globalization;
    using Microsoft.Data.Schema.Extensibility;
    using Microsoft.Data.Schema.SchemaModel;
    using Microsoft.Data.Schema.ScriptDom.Sql;
    using Microsoft.Data.Schema.Sql.SchemaModel;
    using Microsoft.Data.Schema.Sql;
    using Microsoft.Data.Schema.StaticCodeAnalysis;
    namespace SampleRules
    {
        public class AvoidWaitForDelayRule
        {
        }
    }
    

    Tipp

    Sie müssen den Namespacenamen aus SampleRules.AvoidWaitForDelayRule in SampleRules ändern.

  8. Ändern Sie in der AvoidWaitForDelayRule-Klassendeklaration den Zugriffsmodifizierer zu "public":

        /// <summary>
        /// This is a SQL rule which returns a warning message 
        /// whenever there is a WAITFOR DELAY statement appears inside a subroutine body. 
        /// This rule only applies to SQL stored procedures, functions and triggers.
        /// </summary>
        public class AvoidWaitForDelayRule
    
  9. Leiten Sie die AvoidWaitForDelayRule-Klasse von der StaticCodeAnalysisRule-Basisklasse ab:

        public class AvoidWaitForDelayRule : StaticCodeAnalysisRule
    
  10. Fügen Sie der Klasse Folgendes hinzu: DatabaseSchemaProviderCompatibilityAttribute, DataRuleAttribute und SupportedElementTypeAttribute. Weitere Informationen zur Kompatibilität von Funktionserweiterungen finden Sie unter Erweitern der Datenbankfunktionen von Visual Studio.

        [DatabaseSchemaProviderCompatibility(typeof(SqlDatabaseSchemaProvider))]
        [DataRuleAttribute(
            SampleConstants.NameSpace,
            SampleConstants.AvoidWaitForDelayRuleId,
            SampleConstants.ResourceBaseName,
            SampleConstants.AvoidWaitForDelay_RuleName,
            SampleConstants.CategorySamples,
            DescriptionResourceId = SampleConstants.AvoidWaitForDelay_ProblemDescription)]
        [SupportedElementType(typeof(ISqlProcedure))]
        [SupportedElementType(typeof(ISqlTrigger))]
        [SupportedElementType(typeof(ISqlFunction))]
        public class AvoidWaitForDelayRule : StaticCodeAnalysisRule
    

    Mit "DataRuleAttribute" werden Informationen angegeben, die beim Konfigurieren von Analyseregeln für Datenbankcode in Visual Studio angezeigt werden. Mit "SupportedElementTypeAttribute" werden die Arten von Elementen definiert, auf die diese Regel angewendet wird. In diesem Fall wird die Regel auf gespeicherte Prozeduren, Trigger und Funktionen angewendet.

  11. Fügen Sie eine Außerkraftsetzung für die Analyze-Methode hinzu, von der DataRuleSetting und DataRuleExecutionContext als Eingabeparameter verwendet werden. Von dieser Methode wird eine Liste mit potenziellen Problemen zurückgegeben.

    IModelElement und TSqlFragment erhält die Methode durch den Kontextparameter. SqlSchemaModel und ISqlModelElement werden aus dem Modellelement abgerufen. Anschließend wird mithilfe der WaitForDelayVisitor-Klasse eine Liste mit allen WAITFOR DELAY-Anweisungen im Modell abgerufen.

    Für jede WaitForStatement in dieser Liste wird ein DataRuleProblem erstellt.

            #region Overrides
            /// <summary>
            /// Analyze the model element
            /// </summary>
            public override IList<DataRuleProblem> Analyze(DataRuleSetting ruleSetting, DataRuleExecutionContext context)
            {
                List<DataRuleProblem> problems = new List<DataRuleProblem>();
    
                IModelElement modelElement = context.ModelElement;
    
                // this rule does not apply to inline table-valued function
                // we simply do not return any problem
                if (modelElement is ISqlInlineTableValuedFunction)
                {
                    return problems;
                }
    
                // casting to SQL specific 
                SqlSchemaModel sqlSchemaModel = modelElement.Model as SqlSchemaModel;
                Debug.Assert(sqlSchemaModel!=null, "SqlSchemaModel is expected");
    
                ISqlModelElement sqlElement = modelElement as ISqlModelElement;
                Debug.Assert(sqlElement != null, "ISqlModelElement is expected");
    
                // Get ScriptDom for this model element
                TSqlFragment sqlFragment = context.ScriptFragment as TSqlFragment;
                Debug.Assert(sqlFragment != null, "TSqlFragment is expected");
    
                // visitor to get the ocurrences of WAITFOR DELAY statements
                WaitForDelayVisitor visitor = new WaitForDelayVisitor();
                sqlFragment.Accept(visitor);
                List<WaitForStatement> waitforDelayStatements = visitor.WaitForDelayStatements;
    
                // Create problems for each WAITFOR DELAY statement found 
                foreach (WaitForStatement waitForStatement in waitforDelayStatements)
                {
                    DataRuleProblem problem = new DataRuleProblem(this,
                                                String.Format(CultureInfo.CurrentCulture, this.RuleProperties.Description, SqlRuleUtils.GetElementName(sqlSchemaModel, sqlElement)),
                                                sqlElement);
    
                    SqlRuleUtils.UpdateProblemPosition(problem, waitForStatement.StartOffset, waitForStatement.FragmentLength);
                    problems.Add(problem);
                }
    
                return problems;
            }
    
            #endregion    
    
    
  12. Klicken Sie im Menü Datei auf Speichern.

Anschließend erstellen Sie das Projekt.

So erstellen Sie das Projekt

  • Klicken Sie im Menü Erstellen auf Projektmappe erstellen.

Anschließend erfassen Sie im Projekt generierte Assemblyinformationen, u. a. Version, Kultur und PublicKeyToken.

So erfassen Sie Assemblyinformationen

  1. Klicken Sie im Menü Ansicht auf Weitere Fenster, und klicken Sie dann auf Befehlsfenster, um das Befehlsfenster zu öffnen.

  2. Geben Sie im Befehlsfenster folgenden Code ein. Ersetzen Sie FilePath durch den Pfad und Dateinamen der kompilierten DLL-Datei. Schließen Sie Pfad und Dateiname in Anführungszeichen ein.

    Tipp

    Standardmäßig ist FilePath auf Projects\SampleRules\SampleRules\bin\Debug\YourDLL oder Projects\SampleRules\SampleRules\bin\Release \YourDLL festgelegt.

    ? System.Reflection.Assembly.LoadFrom(@"FilePath")
    
  3. Drücken Sie die EINGABETASTE. Die Zeile sollte mit Ihrem entsprechenden PublicKeyToken etwa folgendermaßen aussehen:

    "SampleRules, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nnnnnnnnnnnnnnnn"
    

    Notieren oder kopieren Sie diese Assemblyinformationen, da Sie sie für das nächste Verfahren benötigen.

Danach erstellen Sie eine XML-Datei mit den Assemblyinformationen, die Sie im vorhergehenden Verfahren erfasst haben.

So erstellen Sie die XML-Datei

  1. Wählen Sie im Projektmappen-Explorer das Projekt SampleRules aus.

  2. Klicken Sie im Menü Projekt auf Neues Element hinzufügen.

  3. Suchen Sie im Bereich Vorlagen das Element XML-Datei, und wählen Sie es aus.

  4. Geben Sie im Textfeld Name den Namen "SampleRules.Extensions.xml" ein, und klicken Sie anschließend auf die Schaltfläche Hinzufügen.

    Dem Projekt wird im Projektmappen-Explorer die Datei SampleRules.Extensions.xml hinzugefügt.

  5. Öffnen Sie die Datei SampleRules.Extensions.xml, und aktualisieren Sie diese so, dass sie mit dem folgenden XML übereinstimmt. Ersetzen Sie die Werte für Version, Kultur und PublicKeyToken durch die in der vorherigen Prozedur abgerufenen Werte.

    <?xml version="1.0" encoding="utf-8"?>
    <extensions assembly=""
                version="1" xmlns="urn:Microsoft.Data.Schema.Extensions"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="urn:Microsoft.Data.Schema.Extensions Microsoft.Data.Schema.Extensions.xsd">
    
      <extension type="SampleRules.AvoidWaitForDelayRule" assembly="SampleRules, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b4deb9b383d021b0" enabled="true"/>
    </extensions> 
    
  6. Klicken Sie im Menü Datei auf Speichern.

Danach kopieren Sie die Assemblyinformationen und die XML-Datei in das Erweiterungsverzeichnis. Beim Start von Visual Studio werden sämtliche Erweiterungen im Verzeichnis "Microsoft Visual Studio 10.0\VSTSDB\Extensions" und in den Unterverzeichnissen identifiziert und für die Verwendung in der Sitzung registriert.

So kopieren Sie die Assemblyinformationen und die XML-Datei in das Erweiterungsverzeichnis

  1. Erstellen Sie im Verzeichnis Microsoft Visual Studio 10.0\VSTSDB\Extensions\ den neuen Ordner CustomRules.

  2. Kopieren Sie die Assemblydatei SampleRules.dll aus dem Verzeichnis Projects\SampleRules\SampleRules\bin\Debug\ in das von Ihnen erstellte Verzeichnis Microsoft Visual Studio 10.0\VSTSDB\Extensions\CustomRules.

  3. Kopieren Sie die Datei SampleRules.Extensions.xml aus dem Verzeichnis Projects\SampleRules\SampleRules\ in das von Ihnen erstellte Verzeichnis Microsoft Visual Studio 10.0\VSTSDB\Extensions\CustomRules.

    Tipp

    Als Vorgehensweise wird empfohlen, die Erweiterungsassemblys in einem Ordner im Verzeichnis Microsoft Visual Studio 10.0\VSTSDB\Extensions einzufügen. So können Sie leichter ermitteln, welche Erweiterungen im Produkt enthalten waren und welche Sie benutzerdefiniert erstellt haben. Ordner werden auch zum Einordnen der Erweiterungen in bestimmte Kategorien empfohlen.

Im nächsten Schritt wird eine neue Visual Studio-Sitzung gestartet und ein Datenbankprojekt erstellt.

So starten Sie eine neue Visual Studio-Sitzung und erstellen ein Datenbankprojekt

  1. Starten Sie eine zweite Sitzung von Visual Studio.

  2. Klicken Sie im Menü Datei auf Neu und anschließend auf Projekt.

  3. Erweitern Sie im Dialogfeld Neues Projekt in der Liste Installierte Vorlagen den Knoten mit den Datenbankprojekten, und klicken Sie anschließend auf SQL Server.

  4. Wählen Sie im Detailbereich die Option SQL Server 2008-Datenbankprojekt aus.

  5. Geben Sie im Textfeld Name den Namen "SampleRulesDB" ein, und klicken Sie auf OK.

Die neue Regel wird im SQL Server-Projekt angezeigt.

So zeigen Sie die neue Codeanalyseregel AvoidWaitForRule an

  1. Wählen Sie im Projektmappen-Explorer das Projekt SampleRulesDB aus.

  2. Klicken Sie im Menü Projekt auf Eigenschaften.

    Die Eigenschaftenseite für SampleRulesDB wird angezeigt.

  3. Klicken Sie auf Codeanalyse.

    Die neue Kategorie "CategorySamples" wird angezeigt.

  4. Erweitern Sie "CategorySamples".

    Der Text SR1004: Vermeiden Sie WAITFOR DELAY-Anweisung in gespeicherten Prozeduren, Triggern und Funktionen sollte angezeigt werden.

Siehe auch

Aufgaben

Gewusst wie: Registrieren und Verwalten von Funktionserweiterungen

Gewusst wie: Verteilen benutzerdefinierter Funktionserweiterungen an Teammitglieder

Referenz

ISqlProcedure

ISqlTrigger

ISqlFunction

ISqlInlineTableValuedFunction

Konzepte

Erweitern der Datenbankfunktionen von Visual Studio

Analysieren von Datenbankcode zum Verbessern der Codequalität

Analysieren der Qualität von verwaltetem Code mit der Codeanalyse