チュートリアル : SQL のカスタム スタティック コード分析規則アセンブリの作成
ここでは、SQL コード分析規則を作成する方法を手順を追って説明します。 このチュートリアルで作成する規則は、ストアド プロシージャ、トリガ、および関数で WAITFOR DELAY ステートメントを使用しないようにするために使用します。
このチュートリアルでは、次の手順で SQL スタティック コード分析のカスタム規則を作成します。
クラス ライブラリを作成し、プロジェクトに署名して、必要な参照を追加します。
ヘルパー C# クラスを作成します。
カスタム規則 C# クラスを作成します。
アセンブリの登録に使用する XML ファイルを作成します。
アセンブリを登録するために、生成された DLL と作成した XML ファイルを Extensions ディレクトリにコピーします。
新しいコード分析規則が設定されていることを確認します。
前提条件
このチュートリアルを完了するには、Visual Studio Team System Database Edition または Visual Studio Team System がインストールされている必要があります。
SQL のカスタム コード分析規則の作成
まず、クラス ライブラリを作成します。
クラス ライブラリを作成するには
[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。
[新しいプロジェクト] ダイアログ ボックスで、[プロジェクトの種類] の [Visual C#] をクリックします。
[テンプレート] の [クラス ライブラリ] を選択します。
[名前] ボックスに「SampleRules」と入力し、[OK] をクリックします。
次に、プロジェクトに署名します。
プロジェクトに署名するには
ソリューション エクスプローラで SampleRules プロジェクト ノードを選択した状態で、[プロジェクト] メニューの [プロパティ] をクリックします (または、ソリューション エクスプローラでこのプロジェクト ノードを右クリックし、[プロパティ] をクリックします)。
[署名] タブをクリックします。
[アセンブリの署名] チェック ボックスをオンにします。
新しいキー ファイルを指定します。[厳密な名前のキー ファイルを選択してください] ボックスの一覧の [<新規作成...>] を選択します。
[厳密な名前キーの作成] ダイアログ ボックスが表示されます。 詳細については、「[厳密な名前キーの作成] ダイアログ ボックス」を参照してください。
[厳密な名前キーの作成] ダイアログ ボックスで、新しいキー ファイルの [名前] ボックスに「SampleRulesKey」と入力します。 このチュートリアルでは、パスワードを指定する必要はありません。 詳細については、「アセンブリおよびマニフェストへの署名の管理」を参照してください。
次に、必要な参照をプロジェクトに追加します。
適用可能な参照をプロジェクトに追加するには
ソリューション エクスプローラで、SampleRules プロジェクトを選択します。
[プロジェクト] メニューの [参照の追加] をクリックします。
[参照の追加] ダイアログ ボックスが開きます。 詳細については、「[参照の追加] ダイアログ ボックス」を参照してください。
[.NET] タブをクリックします。
[コンポーネント名] 列で、次のコンポーネントを探します。
ヒント : 複数のコンポーネントを選択するには、Ctrl キーを押しながらコンポーネントをクリックします。
必要なすべてのコンポーネントを選択したら、[OK] をクリックします。
ソリューション エクスプローラで、選択した参照がプロジェクトの [参照設定] ノードの下に表示されます。
カスタム コード分析規則のヘルパー クラスの作成
規則自体のクラスを作成する前に、2 つのヘルパー クラスをプロジェクトに追加します。
ヒント : |
---|
これらのヘルパー クラスは、追加のカスタム規則を作成する場合に役立ちます。 |
1 つ目のヘルパー クラスは SqlRule.cs です。このクラスは、Rule から継承し、コンストラクタと一部のメソッドをオーバーライドします。
SqlRule クラスは、このチュートリアルの「カスタム コード分析規則クラスの作成」で作成するカスタム コード分析規則クラスから継承されます。
SqlRule.cs ファイルをプロジェクトに追加するには
ソリューション エクスプローラで、Class1.cs を右クリックし、[名前の変更] をクリックして、「SqlRule.cs」と入力します。
SqlRule.cs ファイルを開き、次の using ステートメントを追加します。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Data.Schema.SchemaModel; using Microsoft.Data.Schema.Sql.SchemaModel.SqlServer; using Microsoft.Data.Schema.StaticCodeAnalysis; namespace SampleRules {
SqlRule クラスは、他のクラスの基本クラスとなることだけを目的としているため、クラス宣言でアクセス修飾子を "internal abstract" に変更します。
internal abstract class SqlRule {
Rule から SqlRule クラスを派生させます。
internal abstract class SqlRule : Rule {
コンストラクタを追加します。
/// <summary> /// Default constructor. /// </summary> public SqlRule( string idNamespace, string id, string name, string description, string helpUrl, string helpKeyword) : base( idNamespace, id, name, description, helpUrl, helpKeyword) { }
IsSupported メソッドをオーバーライドします。このメソッドでは、入力パラメータとして IModelElement を使用します。
/// <summary> /// Specify whether a particular element is supported by the rule. /// </summary> /// <param name="element"></param> /// <returns></returns> public override bool IsSupported(IModelElement element) { // by default, we would like to handle every element. return true; }
Analyze メソッドをオーバーライドします。このメソッドでは、入力パラメータとして IModelElement と RuleSetting を使用します。 次に、このメソッドで IModelElement 入力パラメータを SQL 固有の SqlSchemaModel 型と ISqlModelElement 型にキャストします。
/// <summary> /// Method to analyze a model element and return problems if any. /// </summary> /// <param name="modelElement"></param> /// <param name="ruleSetting"></param> /// <returns></returns> public override IList<Problem> Analyze(IModelElement modelElement, RuleSetting ruleSetting) { // Casting to SQL-specific types. SqlSchemaModel sqlSchemaModel = modelElement.Model as SqlSchemaModel; ISqlModelElement sqlElement = modelElement as ISqlModelElement; return Analyze(sqlSchemaModel, sqlElement, ruleSetting); }
Analyze メソッドの保護抽象メソッドを追加します。 詳細については、「abstract (C# リファレンス)」を参照してください。
/// <summary> /// Abstract method to analyze sql model element. /// </summary> /// <returns>a list of problems</returns> protected abstract IList<Problem> Analyze(SqlSchemaModel sqlSchemaModel, ISqlModelElement sqlModelElement, RuleSetting ruleSetting); } }
[ファイル] メニューの [保存] をクリックします。
2 つ目のヘルパー クラスは SqlRuleUtils.cs です。このクラスには、このチュートリアルの「カスタム コード分析規則クラスの作成」で作成するカスタム コード分析規則クラスで使用されるユーティリティ メソッドが含まれます。これらのメソッドは次のとおりです。。
UpdateProblemPosition : 行および列情報を計算するために使用します。
ReadFileContent : ファイルの内容を読み取るために使用します。
GetElementSourceFile : ソース ファイルを取得するために使用します。
ComputeLineColumn : ScriptDom のオフセットをスクリプト ファイル内の行と列に変換するために使用します。
SqlRuleUtils.cs ファイルをプロジェクトに追加するには
ソリューション エクスプローラで、SampleRules プロジェクトを選択します。
[プロジェクト] メニューの [クラスの追加] を選択します。
[新しい項目の追加] ダイアログ ボックスが表示されます。
[名前] ボックスに「SqlRuleUtils.cs」と入力し、[追加] をクリックします。
ソリューション エクスプローラで、SqlRuleUtils.cs ファイルがプロジェクトに追加されます。
SqlRuleUtils.cs ファイルを開き、次の using ステートメントを追加します。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Data.Schema.SchemaModel; using Microsoft.Data.Schema.Sql.SchemaModel.SqlServer; using System.Diagnostics; using System.IO; using Microsoft.Data.Schema.StaticCodeAnalysis; namespace SampleRules {
SqlRuleUtils クラス宣言で、アクセス修飾子を "internal static" に変更します。
internal static class SqlRuleUtils {
次のコードを追加して、UpdateProblemPosition メソッドを作成します。このメソッドでは、入力パラメータとして Problem を使用します。
/// <summary> /// Compute the start Line/Col and the end Line/Col to update problem information. /// </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(Problem 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"); } } } } }
次のコードを追加して、ReadFileContent メソッドを作成します。
/// <summary> /// Read file content from a file. /// </summary> /// <param name="filePath"> file path </param> /// <returns> file content in a string </returns> public static string ReadFileContent(string filePath) { // Verify that the file exists first. if (!File.Exists(filePath)) { Debug.WriteLine(string.Format("Cannot find the file: '{0}'", filePath)); return string.Empty; } string content; using (StreamReader reader = new StreamReader(filePath)) { content = reader.ReadToEnd(); reader.Close(); } return content; }
次のコードを追加して、GetElementSourceFile メソッドを作成します。このメソッドでは、入力パラメータとして IModelElement を使用し、String を使用してファイル名を取得します。 このメソッドは、IModelElement を IScriptSourcedElement としてキャストし、モデル要素からのスクリプト ファイル パスを特定するときに ElementSource を使用します。
/// <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; IScriptSourcedElement scriptSourcedElement = element as IScriptSourcedElement; if (scriptSourcedElement != null) { ElementSource elementSource = scriptSourcedElement.ElementSource; if (elementSource != null) { fileName = elementSource.CacheIdentifier; } } return String.IsNullOrEmpty(fileName) == false; }
次のコードを追加して、ComputeLineColumn メソッドを作成します。
/// This method converts offset from ScriptDom to line\column in script files. /// A line is defined as a sequence of characters followed by a carriage return ("\r"), /// a line feed ("\n"), or a carriage return immediately followed by a line feed. public static bool ComputeLineColumn(string text, Int32 offset, Int32 length, out Int32 startLine, out Int32 startColumn, out Int32 endLine, out Int32 endColumn) { const char LF = '\n'; const char CR = '\r'; // Setting the initial value of line and column to 0 since VS auto-increments by 1. startLine = 0; startColumn = 0; endLine = 0; endColumn = 0; int textLength = text.Length; if (offset < 0 || length < 0 || offset + length > textLength) { return false; } for (int charIndex = 0; charIndex < length + offset; ++charIndex) { char currentChar = text[charIndex]; Boolean afterOffset = charIndex >= offset; if (currentChar == LF) { ++endLine; endColumn = 0; if (afterOffset == false) { ++startLine; startColumn = 0; } } else if (currentChar == CR) { // CR/LF combination, consuming LF. if ((charIndex + 1 < textLength) && (text[charIndex + 1] == LF)) { ++charIndex; } ++endLine; endColumn = 0; if (afterOffset == false) { ++startLine; startColumn = 0; } } else { ++endColumn; if (afterOffset == false) { ++startColumn; } } } return true; } } }
[ファイル] メニューの [保存] をクリックします。
カスタム コード分析規則クラスの作成
カスタム コード分析規則で使用するヘルパー クラスを追加できました。次に、カスタム規則クラスを作成し、AvoidWaitForDelayRule という名前を付けます。 AvoidWaitForDelayRule カスタム規則を使用する目的は、データベース開発者がストアド プロシージャ、トリガ、および関数で WAITFOR DELAY ステートメントを使用しないようにすることです。
AvoidWaitForDelayRule クラスを作成するには
ソリューション エクスプローラで、SampleRules プロジェクトを選択します。
[プロジェクト] メニューの [新しいフォルダ] をクリックします。
ソリューション エクスプローラに新しいフォルダが表示されます。 このフォルダに AvoidWaitForDelayRule という名前を付けます。
ソリューション エクスプローラで、AvoidWaitForDelayRule フォルダが選択されていることを確認します。
[プロジェクト] メニューの [クラスの追加] を選択します。
[新しい項目の追加] ダイアログ ボックスが表示されます。
[名前] ボックスに「AvoidWaitForDelayRule.cs」と入力し、[追加] をクリックします。
ソリューション エクスプローラで、AvoidWaitForDelayRule.cs ファイルがプロジェクトの AvoidWaitForDelayRule フォルダに追加されます。
AvoidWaitForDelayRule.cs ファイルを開き、次の using ステートメントを追加します。
using System; using System.Collections.Generic; using System.Linq; using System.Text; 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.SqlServer; using Microsoft.Data.Schema.Sql.SqlDsp; using Microsoft.Data.Schema.StaticCodeAnalysis; namespace SampleRules {
AvoidWaitForDelayRule クラス宣言で、アクセス修飾子を "internal" に変更します。
internal class AvoidWaitForDelayRule
前のセクションで作成した SqlRule ヘルパー クラスから AvoidWaitForDelayRule クラスを派生させます。
internal class AvoidWaitForDelayRule : SqlRule
DatabaseSchemaProviderCompatibilityAttribute 属性を追加します。 詳細については、「カスタム データ ジェネレータで独自のテスト データを生成する」を参照してください。
[DatabaseSchemaProviderCompatibility(typeof(SqlDatabaseSchemaProvider))] internal class AvoidWaitForDelayRule : SqlRule
メンバ変数を作成します。
{ #region constants public const string SampleNamespace = "MyRules.SampleRules"; public const string AvoidWaitForDelayRuleId = "SR1001"; public const string AvoidWaitForDelayRuleName = @"Avoid WAITFOR DELAY statement in stored procedures, triggers and functions."; public const string AvoidWaitForDelayProblemDescription = @"WAITFOR DELAY statement found in {0}."; #endregion
コンストラクタを作成します。
#region ctor /// <summary> /// The default constructor. /// </summary> public AvoidWaitForDelayRule() : base( SampleNamespace, AvoidWaitForDelayRuleId, AvoidWaitForDelayRuleName, AvoidWaitForDelayProblemDescription, String.Empty, String.Empty) { } #endregion
IsSupported のオーバーライドを追加します。このメソッドでは、入力パラメータとして IModelElement を使用します。 このメソッドは、ブール型の出力パラメータを決定するときに、ISqlProcedure、ISqlTrigger、ISqlFunction、および ISqlInlineTableValuedFunction を使用します。
/// <summary> /// Specifies this rule only checks Procedures/Functions/Triggers /// </summary> /// <param name="element"></param> /// <returns></returns> public override bool IsSupported(IModelElement element) { return element is ISqlProcedure || element is ISqlTrigger || (element is ISqlFunction && !(element is ISqlInlineTableValuedFunction)); }
Analyze のオーバーライドを追加します。 このメソッドでは、入力パラメータとして SqlSchemaModel、ISqlModelElement、および RuleSetting を使用します。
このメソッドは、ISqlModelElement を IScriptSourcedElement としてキャストして TSqlFragment のインスタンスを作成します。このインスタンスは、モデル要素の ScriptDom を作成するために使用されます。
TSqlFragment が null ではない場合、コードで StatementList を ProcedureStatementBodyBase および CreateTriggerStatement と共に使用して、この規則がトリガ、プロシージャ、および関数にのみ適用されることを指定します。
生成された StatementList が null でない場合、メソッドは WaitForStatement の List<T> を使用し、StatementList の各 TSqlStatement に対して FindWaitForDelay メソッド (この後の手順で追加します) を呼び出して、返された WaitForStatement ごとに Problem を作成します。
/// <summary> /// Analyze the model element. /// </summary> protected override IList<Problem> Analyze(SqlSchemaModel sqlSchemaModel, ISqlModelElement sqlModelElement, RuleSetting ruleSetting) { if (sqlSchemaModel == null) { throw new ArgumentException("SqlSchemaModel is expected", "schemaModel"); } if (sqlModelElement == null) { throw new ArgumentException("ISqlModelElement is expected", "modelElement"); } List<Problem> problems = new List<Problem>(); // Get ScriptDom for this model element TSqlFragment sqlFragment = null; IScriptSourcedElement scriptSourcedElement = sqlModelElement as IScriptSourcedElement; if (scriptSourcedElement != null && scriptSourcedElement.ElementSource != null) { sqlFragment = scriptSourcedElement.ElementSource.ScriptDom as TSqlFragment; } if (sqlFragment != null) { // extract statement list from the sql fragment StatementList statementList = null; if (sqlFragment is ProcedureStatementBodyBase) // procs & functions { statementList = (sqlFragment as ProcedureStatementBodyBase).StatementList; } else if (sqlFragment is CreateTriggerStatement) // triggers { statementList = (sqlFragment as CreateTriggerStatement).StatementList; } if (statementList != null) { // in statement list, search all WaitFor statement List<WaitForStatement> waitForDelayList = new List<WaitForStatement>(); foreach (TSqlStatement statement in statementList.Statements) { FindWaitForDelay(statement, waitForDelayList); } // Create problems for WAITFOR DELAY statements found foreach (WaitForStatement waitForStatement in waitForDelayList) { Problem p = new Problem(this, string.Format(CultureInfo.CurrentCulture, this.Description, sqlModelElement.ToString()), sqlModelElement); SqlRuleUtils.UpdateProblemPosition(p, waitForStatement.StartOffset, waitForStatement.FragmentLength); problems.Add(p); } } } return problems; }
FindWaitForDelay というサポート メソッドを追加します。このメソッドでは、入力パラメータとして TSqlStatement と WaitForStatement を使用します。 このメソッドは、TSqlStatement で Delay に設定された WaitForOption を使用して、WaitForStatement のすべての出現箇所を検索します。 また、再帰を使用して IfStatement、WhileStatement、BeginEndBlockStatement、および TryCatchStatement の各ブロック内の WaitForStatement を検索します。
#region Supporting methods /// <summary> /// Recursively find all WAITFOR DELAY statements in TSqlStatement /// </summary> /// <param name="st">statement input</param> /// <param name="waitForDelayList">WAITFOR DELAY statements found</param> private void FindWaitForDelay(TSqlStatement st, List<WaitForStatement> waitForDelayList) { if (st is WaitForStatement) { WaitForStatement waitForStatement = (WaitForStatement)st; if (waitForStatement.WaitForOption == WaitForOption.Delay) // Only looking for WAITFOR DELAY occurrences { waitForDelayList.Add(waitForStatement); } } else if (st is IfStatement) { IfStatement ifStatement = (IfStatement)st; FindWaitForDelay((ifStatement.ThenStatement) as TSqlStatement, waitForDelayList); FindWaitForDelay((ifStatement.ElseStatement) as TSqlStatement, waitForDelayList); } else if (st is WhileStatement) { WhileStatement whileStatement = (WhileStatement)st; FindWaitForDelay((whileStatement.Statement) as TSqlStatement, waitForDelayList); } else if (st is BeginEndBlockStatement) { BeginEndBlockStatement stBlock = (BeginEndBlockStatement)st; foreach (TSqlStatement s in stBlock.StatementList.Statements) { FindWaitForDelay(s, waitForDelayList); } } else if (st is TryCatchStatement) { TryCatchStatement tryCatchStatement = (TryCatchStatement)st; foreach (TSqlStatement s in tryCatchStatement.TryStatements.Statements) { FindWaitForDelay(s, waitForDelayList); } foreach (TSqlStatement s in tryCatchStatement.CatchStatements.Statements) { FindWaitForDelay(s, waitForDelayList); } } } #endregion } }
[ファイル] メニューの [保存] をクリックします。
次に、プロジェクトをビルドします。
プロジェクトをビルドするには
- [ビルド] メニューの [ソリューションのビルド] をクリックします。
次に、バージョン、カルチャ、PublicKeyToken などプロジェクトで生成されたアセンブリ情報を収集します。
アセンブリ情報を収集するには
[表示] メニューの [その他のウィンドウ] をクリックし、[コマンド ウィンドウ] をクリックして、[コマンド] ウィンドウを開きます。
[コマンド] ウィンドウに、次のコードを入力します。FilePath をコンパイル済みの .dll ファイルのパスとファイル名に置き換えます。パスとファイル名は引用符で囲みます。
メモ : 既定では、コンパイル済みの .dll ファイルのパスは YourSolutionPath\bin\Debug または YourSolutionPath\bin\Release です。
? System.Reflection.Assembly.LoadFrom(@"FilePath").FullName
Enter キーを押します。 具体的な PublicKeyToken の値を含む次のような行が表示されます。
"SampleRules, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nnnnnnnnnnnnnnnn"
このアセンブリ情報をメモするか、コピーします。この情報は次の手順で使用します。
次に、前の手順で収集したアセンブリ情報を使用して XML ファイルを作成します。
XML ファイルを作成するには
ソリューション エクスプローラで、SampleRules プロジェクトを選択します。
[プロジェクト] メニューの [新しい項目の追加] をクリックします。
[テンプレート] ペインで、[XML ファイル] という項目を探してクリックします。
[名前] ボックスに「SampleRules.Extensions.xml」と入力し、[追加] をクリックします。
ソリューション エクスプローラで、SampleRules.Extensions.xml ファイルがプロジェクトに追加されます。
SampleRules.Extensions.xml ファイルを開き、次の XML に合わせて内容を更新します。 前の手順で取得したバージョン、カルチャ、および PublicKeyToken を置き換えます。
<?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.AvoidWaitForDelayRule" assembly="SampleRules, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b4deb9b383d021b0" enabled="true"/> </extensions>
[ファイル] メニューの [保存] をクリックします。
次に、アセンブリ情報と XML ファイルを Extensions ディレクトリにコピーします。 Database Edition が起動すると、<Microsoft Visual Studio 9.0>\VSTSDB\Extensions ディレクトリとそのサブディレクトリ内の拡張機能が識別され、セッションで使用できるよう登録されます。
アセンブリ情報と XML ファイルを Extensions ディレクトリにコピーするには
<Microsoft Visual Studio 9.0>\VSTSDB\Extensions\ ディレクトリに CustomRules という名前の新しいフォルダを作成します。
<Projects>\SampleRules\SampleRules\bin\Debug\ ディレクトリの SampleRules.dll アセンブリ ファイルを、前の手順で作成した <Microsoft Visual Studio 9.0>\VSTSDB\Extensions\CustomRules ディレクトリにコピーします。
<Projects>\SampleRules\SampleRules\ ディレクトリの SampleRules.Extensions.xml ファイルを、前の手順で作成した <Microsoft Visual Studio 9.0>\VSTSDB\Extensions\CustomRules ディレクトリにコピーします。
ヒント : 拡張機能アセンブリは、<Microsoft Visual Studio 9.0>\VSTSDB\Extensions ディレクトリにフォルダを作成して格納することをお勧めします。 これにより、もともと製品に用意されていた拡張機能と、自分の作成した拡張機能を識別できます。 また、フォルダを使用すると、拡張機能を詳細なカテゴリに分類することもできます。
次に、Visual Studio の新しいセッションを開始して、SQL Server プロジェクトを作成します。
新しい Visual Studio のセッションを開始して SQL Server プロジェクトを作成するには
Database Edition の別のセッションを開始します。
[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。
[新しいプロジェクト] ダイアログ ボックスで、[プロジェクトの種類] の [データベース プロジェクト] をクリックし、[SQL Server 2008] をクリックします。
[テンプレート] の [SQL Server 2008 データベース プロジェクト] を選択します。
[名前] ボックスに「SampleRulesDB」と入力し、[OK] をクリックします。
最後に、SQL Server プロジェクトに新しい規則が表示されていることを確認します。
新しい AvoidWaitForRule コード分析規則を表示するには
ソリューション エクスプローラで、SampleRulesDB プロジェクトを選択します。
[プロジェクト] メニューの [プロパティ] をクリックします。
SampleRulesDB プロパティ ページが表示されます。
[コード分析]をクリックします。
Microsoft.Samples という新しいカテゴリが表示されます。
Microsoft.Samples を展開します。
[SR1001: Avoid WAITFOR DELAY statement in stored procedures, triggers, and functions] と表示されます。
参照
処理手順
概念
参照
DatabaseSchemaProviderCompatibilityAttribute