チュートリアル: SQL 用のカスタムの静的コード分析規則アセンブリを作成する
このトピックでは、SQL コード分析規則を作成する方法を手順に沿って説明します。 このチュートリアルで作成する規則は、ストアド プロシージャ、トリガー、および関数で WAITFOR DELAY ステートメントが使われないようにするために使用されます。
このチュートリアルでは、次の手順で Transact-SQL 静的コード分析用のカスタム規則を作成します。
クラス ライブラリを作成し、そのプロジェクトの署名を有効にして、必要な参照を追加する。
2 つの C# ヘルパー クラスを作成する。
C# カスタム規則クラスを作成する。
アセンブリの登録に使用する XML ファイルを作成する。
作成された DLL と XML ファイルを Extensions ディレクトリにコピーして登録する。
新しいコード分析規則が適用されることを確認する。
必須コンポーネント
このチュートリアルを完了するには、Visual Studio Premium または Visual Studio Ultimate をインストールする必要があります。
SQL 用のカスタム コード分析規則の作成
最初に、クラス ライブラリを作成します。
クラス ライブラリを作成するには
[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。
[新しいプロジェクト] ダイアログ ボックスの [インストールされたテンプレート] の一覧で、[Visual C#] をクリックします。
詳細ウィンドウで、[クラス ライブラリ] を選択します。
[名前] ボックスに「SampleRules」と入力し、[OK] をクリックします。
次に、プロジェクトに署名します。
プロジェクトの署名を有効にするには
ソリューション エクスプローラーで SampleRules プロジェクト ノードを選択した状態で、[プロジェクト] メニューの [プロパティ] をクリックします (または、ソリューション エクスプローラーでプロジェクト ノードを右クリックし、[プロパティ] をクリックします)。
[署名] タブをクリックします。
[アセンブリの署名] チェック ボックスをオンにします。
新しいキー ファイルを指定します。 [厳密な名前のキー ファイルを選択してください] ボックスの一覧の [<新規作成...>] を選択します。
[厳密な名前キーの作成] ダイアログ ボックスが表示されます。 詳細については、「[厳密な名前キーの作成] ダイアログ ボックス」を参照してください。
[厳密な名前キーの作成] ダイアログ ボックスの、新しいキー ファイルの [名前] ボックスに「SampleRulesKey」と入力します。 このチュートリアルでは、パスワードを指定する必要はありません。 詳細については、「アセンブリおよびマニフェストへの署名の管理」を参照してください。
次に、必要な参照をプロジェクトに追加します。
適切な参照をプロジェクトに追加するには
ソリューション エクスプローラーで、SampleRules プロジェクトを選択します。
[プロジェクト] メニューの [参照の追加] をクリックします。
[参照の追加] ダイアログ ボックスが表示されます。 詳細については、「方法: Visual Studio で参照を追加または削除する」を参照してください。
[.NET] タブを選択します。
[コンポーネント名] 列で、次のコンポーネントを探します。
注意
複数のコンポーネントを選択するには、Ctrl キーを押しながらコンポーネントを 1 つずつクリックします。
必要なすべてのコンポーネントを選択したら、[OK] をクリックします。
ソリューション エクスプローラーで、選択された参照がプロジェクトの [参照設定] ノードに表示されます。
カスタム コード分析規則のサポート クラスの作成
規則自体のクラスを作成する前に、ビジタ クラスとヘルパー クラスをプロジェクトに追加します。
ヒント
これらのクラスは、追加のカスタム規則を作成するときに便利な場合があります。
最初に定義する必要があるクラスは、TSqlConcreteFragmentVisitor から派生した WaitForDelayVisitor クラスです。 このクラスは、モデル内の WAITFOR DELAY ステートメントへのアクセスを提供します。
WaitForDelayVisitor クラスを定義するには
ソリューション エクスプローラーで、SampleRules プロジェクトを選択します。
[プロジェクト] メニューの [クラスの追加] を選択します。
[新しい項目の追加] ダイアログ ボックスが表示されます。
[名前] ボックスに「WaitForDelayVisitor.cs」と入力し、[追加] をクリックします。
ソリューション エクスプローラーで、プロジェクトに WaitForDelayVisitor.cs ファイルが追加されます。
WaitForDelayVisitor.cs ファイルを開き、次のコードと一致する内容を更新します。
using System.Collections.Generic; using Microsoft.Data.Schema.ScriptDom.Sql; namespace SampleRules { class WaitForDelayVistor { } }
クラス宣言で、アクセス修飾子を internal に変更し、クラスを TSqlConcreteFragmentVisitor から派生させます。
internal class WaitForDelayVisitor : TSqlConcreteFragmentVisitor { }
次のコードを追加して、List メンバー変数を定義します。
private List<WaitForStatement> _waitForDelayStatments;
次のコードを追加してクラス コンストラクターを定義します。
#region ctor public WaitForDelayVisitor() { _waitForDelayStatments = new List<WaitForStatement>(); } #endregion
次のコードを追加して、読み取り専用の WaitForDelayStatements プロパティを定義します。
#region properties public List<WaitForStatement> WaitForDelayStatements { get { return _waitForDelayStatments; } } #endregion
次のコードを追加して ExplicitVisit メソッドをオーバーライドします。
#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
このメソッドはモデルの WAITFOR ステートメントにアクセスし、DELAY オプションを指定したステートメントを WAITFOR DELAY ステートメントの一覧に追加します。 ここで参照されているキー クラスは WaitForStatement です。
[ファイル] メニューの [保存] をクリックします。
2 番目のクラスである SqlRuleUtils.cs には、カスタムのコード分析規則クラスで使用されるいくつかのユーティリティ メソッドが含まれます。カスタムのコード分析規則クラスは、このチュートリアルの後半にある「カスタムのコード分析規則クラスの作成」セクションで作成します。 次のメソッドが含まれます。
GetElementName。モデル要素のエスケープされた完全修飾名を取得するために使用されます。
UpdateProblemPosition。行と列の情報を計算するために使用されます。
ReadFileContent。ファイルからコンテンツを読み取るために使用されます。
GetElementSourceFile。ソース ファイルを取得するために使用されます。
ComputeLineColumn。ScriptDom のオフセットを、スクリプト ファイル内の行と列に変換するために使用されます。
プロジェクトに SqlRuleUtils.cs ファイルを追加するには
ソリューション エクスプローラーで、SampleRules プロジェクトを選択します。
[プロジェクト] メニューの [クラスの追加] を選択します。
[新しい項目の追加] ダイアログ ボックスが表示されます。
[名前] ボックスに「SqlRuleUtils.cs」と入力し、[追加] をクリックします。
ソリューション エクスプローラーで、プロジェクトに SqlRuleUtils ファイルが追加されます。
SqlRuleUtils.cs ファイルを開き、ファイルに次の using ステートメントを追加します。
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 { }
SqlRuleUtils クラス宣言で、アクセス修飾子を public static に変更します。
public static class SqlRuleUtils { }
次のコードを追加して、SqlSchemaModel および ISqlModelElement を入力パラメーターとして使用する GetElementName メソッドを作成します。
/// <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); }
次のコードを追加して 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 を IScriptSourcedModelElement としてキャストした後、ISourceInformation を使用して、モデル要素からスクリプト ファイル パスを決定します。
/// <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; }
次のコードを追加して 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; }
次のコードを追加して UpdateProblemPosition メソッドを作成します。このメソッドは、DataRuleProblem を入力パラメーターとして使用します。
/// <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"); } } } } }
[ファイル] メニューの [保存] をクリックします。
次に、規則名、規則の説明、および規則構成インターフェイスで規則が表示されるカテゴリを定義するリソース ファイルを追加します。
リソース ファイルと 3 つのリソース文字列を追加するには
ソリューション エクスプローラーで、SampleRules プロジェクトを選択します。
[プロジェクト] メニューの [新しい項目の追加] をクリックします。
[新しい項目の追加] ダイアログ ボックスが表示されます。
[インストールされているテンプレート] の一覧で [全般] をクリックします。
詳細ペイン内で、[リソース ファイル] をクリックします。
[名前] に、「SampleRuleResource.resx」と入力します。
リソース エディターが、リソースが定義されていない状態で表示されます。
3 つのリソース文字列を次のように定義します。
名前
値
AvoidWaitForDelay_ProblemDescription
WAITFOR DELAY statement was found in {0}.
AvoidWaitForDelay_RuleName
Avoid using WaitFor Delay statements in stored procedures, functions and triggers.
CategorySamples
SamplesCategory
[ファイル] メニューの [SampleRuleResource.resx の保存] をクリックします。
次に、Visual Studio でユーザー インターフェイスに規則に関する情報を表示するために使用するリソース ファイル内のリソースを参照するクラスを定義します。
SampleConstants クラスを定義するには
ソリューション エクスプローラーで、SampleRules プロジェクトを選択します。
[プロジェクト] メニューの [クラスの追加] を選択します。
[新しい項目の追加] ダイアログ ボックスが表示されます。
[名前] ボックスに「SampleRuleConstants.cs」と入力し、[追加] をクリックします。
ソリューション エクスプローラーで、プロジェクトに SampleRuleConstants.cs ファイルが追加されます。
SampleRuleConstants.cs ファイルを開き、次の using ステートメントをファイルに追加します。
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"; } }
[ファイル] メニューの [保存] をクリックします。
カスタム コード分析規則クラスの作成
これで、カスタム コード分析規則で使用されるヘルパー クラスを追加できました。ここでは、カスタム規則クラスを作成し、それに AvoidWaitForDelayRule という名前を付けます。 AvoidWaitForDelayRule カスタム規則を使用する目的は、データベース開発者が、ストアド プロシージャ、トリガー、および関数で WAITFOR DELAY ステートメントを使用しないようにすることです。
AvoidWaitForDelayRule クラスを作成するには
ソリューション エクスプローラーで、SampleRules プロジェクトを選択します。
[プロジェクト] メニューの [新しいフォルダー] を選択します。
ソリューション エクスプローラーに新しいフォルダーが表示されます。 このフォルダーに「AvoidWaitForDelayRule」という名前を付けます。
ソリューション エクスプローラーで、AvoidWaitForDelayRule フォルダーが選択されていることを確認します。
[プロジェクト] メニューの [クラスの追加] を選択します。
[新しい項目の追加] ダイアログ ボックスが表示されます。
[名前] ボックスに「AvoidWaitForDelayRule.cs」と入力し、[追加] をクリックします。
ソリューション エクスプローラーで、プロジェクトの AvoidWaitForDelayRule フォルダーに AvoidWaitForDelayRule.cs ファイルが追加されます。
AvoidWaitForDelayRule.cs ファイルを開き、ファイルに次の using ステートメントを追加します。
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 { } }
注意
名前空間名を SampleRules.AvoidWaitForDelayRule から SampleRules に変更する必要があります。
AvoidWaitForDelayRule クラス宣言で、アクセス修飾子を 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
AvoidWaitForDelayRule クラスを StaticCodeAnalysisRule 基本クラスから派生させます。
public class AvoidWaitForDelayRule : StaticCodeAnalysisRule
DatabaseSchemaProviderCompatibilityAttribute、DataRuleAttribute、および SupportedElementTypeAttribute をクラスに追加します。 機能拡張の互換性の詳細については、「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
DataRuleAttribute は、データベース コード分析規則を構成するときに、Visual Studio に表示される情報を指定します。 SupportedElementTypeAttribute は、この規則が適用される要素の種類を定義します。 この例では、規則はストアド プロシージャ、トリガー、および関数に適用されます。
DataRuleSetting および DataRuleExecutionContext を入力パラメーターとして使用する Analyze メソッドのオーバーライドを追加します。 このメソッドは、潜在的な問題の一覧を返します。
このメソッドは、コンテキスト パラメーターから IModelElement および TSqlFragment を取得します。 SqlSchemaModel および ISqlModelElement は、モデル要素から取得されます。 その後、WaitForDelayVisitor クラスを使用して、モデル内のすべての WAITFOR DELAY ステートメントの一覧を取得します。
その一覧の WaitForStatement ごとに、DataRuleProblem が作成されます。
#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
[ファイル] メニューの [保存] をクリックします。
次に、プロジェクトをビルドします。
プロジェクトをビルドするには
- [ビルド] メニューの [ソリューションのビルド] をクリックします。
次に、プロジェクトで生成されたアセンブリ情報を収集します。この情報には、バージョン、カルチャ、および PublicKeyToken が含まれます。
アセンブリ情報を収集するには
[表示] メニューの [その他のウィンドウ] をポイントし、[コマンド ウィンドウ] をクリックして、[コマンド] ウィンドウを開きます。
[コマンド] ウィンドウに、次のコードを入力します。 FilePath をコンパイル済みの .dll ファイルのパスとファイル名に置き換えます。 パスとファイル名は引用符で囲みます。
注意
既定では、FilePath は Projects\SampleRules\SampleRules\bin\Debug\YourDLL または Projects\SampleRules\SampleRules\bin\Release\YourDLL になります。
? System.Reflection.Assembly.LoadFrom(@"FilePath")
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" assembly="SampleRules, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b4deb9b383d021b0" enabled="true"/> </extensions>
[ファイル] メニューの [保存] をクリックします。
次に、アセンブリ情報と XML ファイルを Extensions ディレクトリにコピーします。 Visual Studio の起動時に、Microsoft Visual Studio 10.0\VSTSDB\Extensions ディレクトリとサブディレクトリ内の拡張機能が識別され、セッションで使用できるように登録されます。
アセンブリ情報と XML ファイルを Extensions ディレクトリにコピーするには
Microsoft Visual Studio 10.0\VSTSDB\Extensions\ ディレクトリに、CustomRules という名前の新しいフォルダーを作成します。
Projects\SampleRules\SampleRules\bin\Debug\ ディレクトリの SampleRules.dll アセンブリ ファイルを、作成した Microsoft Visual Studio 10.0\VSTSDB\Extensions\CustomRules ディレクトリにコピーします。
Projects\SampleRules\SampleRules\ ディレクトリの SampleRules.Extensions.xml ファイルを、作成した Microsoft Visual Studio 10.0\VSTSDB\Extensions\CustomRules ディレクトリにコピーします。
注意
拡張機能のアセンブリは、Microsoft Visual Studio 10.0\VSTSDB\Extensions ディレクトリ内のフォルダーに配置することをお勧めします。 これにより、製品に付属していた拡張機能と、カスタマイズして作成した拡張機能を識別しやすくなります。 フォルダーの使用は、拡張機能をカテゴリ別に整理するためにも推奨されます。
次に、Visual Studio の新しいセッションを開始し、データベース プロジェクトを作成します。
Visual Studio の新しいセッションを開始し、データベース プロジェクトを作成するには
Visual Studio の別のセッションを開始します。
[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。
[新しいプロジェクト] ダイアログ ボックスの [インストールされたテンプレート] の一覧で、[データベース プロジェクト] ノードを展開し、[SQL Server] をクリックします。
詳細ペインで、[SQL Server 2008 データベース プロジェクト] を選択します。
[名前] ボックスに「SampleRulesDB」と入力し、[OK] をクリックします。
最後に、SQL Server プロジェクトで新しい規則が表示されることを確認します。
新しい AvoidWaitForRule コード分析規則を表示するには
ソリューション エクスプローラーで、SampleRulesDB プロジェクトを選択します。
[プロジェクト] メニューの [プロパティ] をクリックします。
SampleRulesDB のプロパティ ページが表示されます。
[コード分析] をクリックします。
CategorySamples という名前の新しいカテゴリが表示されます。
CategorySamples を展開します。
"SR1004: Avoid WAITFOR DELAY statement in stored procedures, triggers, and functions" が表示されます。