テスト用のSQL Serverデータベースに対して実行するASP.NETアプリケーションの単体テストを作成しています。つまり、ClassInitializeメソッドはテストデータを含む新しいデータベースを作成し、ClassCleanupはデータベースを削除します。これを行うには、コードから.batスクリプトを実行します。
テスト対象のクラスには、運用データベースではなく単体テストデータベースに接続する接続文字列が与えられます。
問題は、データベースにフルテキストインデックスが含まれていることです。フルテキストインデックスには、テストを期待どおりに実行するために、テストデータを完全に入力する必要があります。
私が知る限り、フルテキストインデックスは常にバックグラウンドで読み込まれます。私は次のいずれかをできるようにしたいと思います。
私の現在の解決策は、クラスの初期化メソッドの最後に遅延を強制することです-5秒は動作しているようです-ドキュメントに何も見つからないためです。
FULLTEXTCATALOGPROPERTYを使用してステータスを照会できます(こちらを参照してください: http://technet.Microsoft.com/en-us/library/ms190370.aspx )。
例えば:
SELECT
FULLTEXTCATALOGPROPERTY(cat.name,'ItemCount') AS [ItemCount],
FULLTEXTCATALOGPROPERTY(cat.name,'MergeStatus') AS [MergeStatus],
FULLTEXTCATALOGPROPERTY(cat.name,'PopulateCompletionAge') AS [PopulateCompletionAge],
FULLTEXTCATALOGPROPERTY(cat.name,'PopulateStatus') AS [PopulateStatus],
FULLTEXTCATALOGPROPERTY(cat.name,'ImportStatus') AS [ImportStatus]
FROM sys.fulltext_catalogs AS cat
また、SQLプロファイラーを使用して、カタログのプロパティダイアログを表示するときにSQL Server Management Studioが発行するコマンドを監視することもできます。ダイアログには、人口状況の指標が含まれ、表示されるすべての情報はT-SQLを使用してクエリされます。
@Daniel Renshawの答えの読みやすいバージョンを提供したいと思います。
DECLARE @CatalogName VARCHAR(MAX)
SET @CatalogName = 'FTS_Demo_Catalog'
SELECT
DATEADD(ss, FULLTEXTCATALOGPROPERTY(@CatalogName,'PopulateCompletionAge'), '1/1/1990') AS LastPopulated
,(SELECT CASE FULLTEXTCATALOGPROPERTY(@CatalogName,'PopulateStatus')
WHEN 0 THEN 'Idle'
WHEN 1 THEN 'Full Population In Progress'
WHEN 2 THEN 'Paused'
WHEN 3 THEN 'Throttled'
WHEN 4 THEN 'Recovering'
WHEN 5 THEN 'Shutdown'
WHEN 6 THEN 'Incremental Population In Progress'
WHEN 7 THEN 'Building Index'
WHEN 8 THEN 'Disk Full. Paused'
WHEN 9 THEN 'Change Tracking' END) AS PopulateStatus
FROM sys.fulltext_catalogs AS cat
結果:
LastPopulated PopulateStatus
----------------------- ----------------------------------
2012-05-08 14:51:37.000 Idle
(1 row(s) affected)
これは、GarethOwenの回答に基づいて作成したストアドプロシージャです。パラメーターとしてテーブルのコンマ区切りリストを受け入れ、すべてのテーブルのフルテキストインデックスが更新されるまで待機します。ディスクのスラッシングを防止するために10秒ごとにこのチェックを行い、物事がゆっくり/壊れている場合に備えて10秒後にタイムアウトします。 FT検索が複数のインデックスにまたがる場合に役立ちます。
次の方法で呼び出されます。
EXECUTE [dbo].[WaitForFullTextIndexing] 'MY_TABLE,ALTERNATE_NAMES,TAG_GROUP_VALUES,TAG_GROUPS,FIELD_OPTION';
起源:
CREATE PROCEDURE WaitForFullTextIndexing
@TablesStr varchar(max)
AS
BEGIN
DECLARE @Tables AS TABLE( [Word] [varchar](8000) NULL)
INSERT INTO @Tables (Word) SELECT items from dbo.Split(@TablesStr, ',');
DECLARE @NumberOfTables int;
SELECT @NumberOfTables = COUNT(*) from @Tables;
DECLARE @readyCount int;
SET @readyCount = 0;
DECLARE @waitLoops int;
SET @waitLoops = 0;
DECLARE @result bit;
WHILE @readyCount <> @NumberOfTables AND @waitLoops < 100
BEGIN
select @readyCount = COUNT(*)
from @Tables tabs
where OBJECTPROPERTY(object_id(tabs.Word), 'TableFulltextPopulateStatus') = 0;
IF @readyCount <> @NumberOfTables
BEGIN
-- prevent thrashing
WAITFOR DELAY '00:00:00.1';
END
set @waitLoops = @waitLoops + 1;
END
END
GO
dbo.splitは、誰もが持つ必要のあるテーブル値関数で、区切り文字列を一時テーブルに分割します。
CREATE FUNCTION [dbo].[Split](@String varchar(8000), @Delimiter char(1))
returns @temptable TABLE (items varchar(8000))
as
begin
declare @idx int
declare @slice varchar(8000)
select @idx = 1
if len(@String)<1 or @String is null return
while @idx!= 0
begin
set @idx = charindex(@Delimiter,@String)
if @idx!=0
set @slice = left(@String,@idx - 1)
else
set @slice = @String
if(len(@slice)>0)
insert into @temptable(Items) values(@slice)
set @String = right(@String,len(@String) - @idx)
if len(@String) = 0 break
end
return
end
GO
ダニエルのおかげで、あなたの答えは私を正しい方向に導きました。
実際に次のT-SQLステートメントを使用して、フルテキストインデックスの作成ステータスがアイドルかどうかを確認します。
SELECT OBJECTPROPERTY(object_id('v_doc_desc_de'), 'TableFulltextPopulateStatus')
「v_doc_desc_de」は、インデックス付けするデータベースビューの名前です。
ポピュレーションステータスがアイドルでない場合は、アイドルになるまで数秒待ってから再度尋ねます。ポピュレーションステータスを継続的にチェックすることにより、全テキストのポピュレーションが遅くならないように、チェックの間に少しの時間を空けることが重要です。
MSDNドキュメント は、プロパティ「PopulateStatus」を持つOBJECTPROPERTYEX
ステートメントよりもFULLTEXTCATALOGPROPERTY
関数(テーブルレベル)が推奨されることを示しています。次のように述べています。
次のプロパティは、SQL Serverの将来のリリースで削除されます:LogSizeおよびPopulateStatus。新しい開発作業でこれらのプロパティを使用することは避け、現在これらのプロパティを使用しているアプリケーションを変更することを計画してください。
フルテキストカタログが名前を指定せずにすべてのテーブルとビューの作成を完了するのを待つには、次のストアドプロシージャを使用できます。これは、この質問に対するJohnBの回答と 関連する質問 へのcezarmによる回答の組み合わせです。
CREATE PROCEDURE WaitForFullTextIndexing
@CatalogName VARCHAR(MAX)
AS
BEGIN
DECLARE @status int;
SET @status = 1;
DECLARE @waitLoops int;
SET @waitLoops = 0;
WHILE @status > 0 AND @waitLoops < 100
BEGIN
SELECT @status = FULLTEXTCATALOGPROPERTY(@CatalogName,'PopulateStatus')
FROM sys.fulltext_catalogs AS cat;
IF @status > 0
BEGIN
-- prevent thrashing
WAITFOR DELAY '00:00:00.1';
END
SET @waitLoops = @waitLoops + 1;
END
END