Nous écrivons des tests unitaires pour notre application ASP.NET qui s'exécutent sur une base de données de test SQL Server. En d'autres termes, la méthode ClassInitialize crée une nouvelle base de données avec des données de test et ClassCleanup supprime la base de données. Nous le faisons en exécutant des scripts .bat à partir du code.
Les classes testées reçoivent une chaîne de connexion qui se connecte à la base de données de test unitaire plutôt qu'à une base de données de production.
Notre problème est que la base de données contient un index de texte intégral, qui doit être entièrement rempli avec les données de test pour que nos tests s'exécutent comme prévu.
Pour autant que je sache, l'index de texte intégral est toujours rempli en arrière-plan. J'aimerais pouvoir soit:
Ma solution actuelle est de forcer un délai à la fin de la méthode d'initialisation de la classe - 5 secondes semble fonctionner - car je ne trouve rien dans la documentation.
Vous pouvez interroger l'état à l'aide de FULLTEXTCATALOGPROPERTY (voir ici: http://technet.Microsoft.com/en-us/library/ms190370.aspx ).
Par exemple:
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
Vous pouvez également utiliser SQL Profiler pour surveiller les commandes que SQL Server Management Studio émet lorsque vous ouvrez la boîte de dialogue des propriétés du catalogue. La boîte de dialogue comprend une indication de l'état de la population et toutes les informations affichées sont interrogées à l'aide de T-SQL.
J'aimerais offrir une version plus facile à lire de la réponse de @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
Résultats:
LastPopulated PopulateStatus
----------------------- ----------------------------------
2012-05-08 14:51:37.000 Idle
(1 row(s) affected)
Il s'agit d'une procédure stockée que nous avons créée sur la base de la réponse de GarethOwen. Il accepte une liste de tables séparées par des virgules en tant que paramètres et attend que les index de texte intégral sur chacun d'eux soient mis à jour. Il effectue cette vérification tous les dixièmes de seconde pour éviter de casser le disque et expire après 10 secondes au cas où les choses tournent lentement/cassent. Utile si vos recherches FT se font sur plusieurs index.
Appelé de la manière suivante:
EXECUTE [dbo].[WaitForFullTextIndexing] 'MY_TABLE,ALTERNATE_NAMES,TAG_GROUP_VALUES,TAG_GROUPS,FIELD_OPTION';
La source:
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 est une fonction de valeur de table que tout le monde doit avoir maintenant qui fractionne une chaîne sur un séparateur en une table temporaire:
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
Merci Daniel, votre réponse m'a mis sur la bonne voie.
J'utilise en fait l'instruction T-SQL suivante pour demander si l'état de la population de l'index de texte intégral est inactif:
SELECT OBJECTPROPERTY(object_id('v_doc_desc_de'), 'TableFulltextPopulateStatus')
'v_doc_desc_de' est le nom de la vue de base de données que nous indexons.
Si l'état de la population n'est pas inactif, j'attends quelques secondes et demande à nouveau, jusqu'à ce qu'il soit inactif. Il est important d'attendre un peu de temps entre les vérifications pour vous assurer que la population de texte intégral n'est pas ralentie en vérifiant en continu l'état de la population.
documentation MSDN indique que la fonction OBJECTPROPERTYEX
(au niveau de la table) est recommandée par rapport à l'instruction FULLTEXTCATALOGPROPERTY
avec la propriété 'PopulateStatus'. Il déclare ce qui suit:
Les propriétés suivantes seront supprimées dans une future version de SQL Server: LogSize et PopulateStatus. Évitez d'utiliser ces propriétés dans de nouveaux travaux de développement et prévoyez de modifier les applications qui utilisent actuellement l'une d'entre elles.
Pour attendre qu'un catalogue de texte intégral termine le remplissage de toutes ses tables et vues sans avoir à spécifier leurs noms, vous pouvez utiliser la procédure stockée suivante. Ceci est une combinaison de la réponse de JohnB à cette question et de la réponse par cezarm à une question connexe :
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