Linq to SQL全文搜索程序 - 奇怪的错误

时间:2011-07-25 09:03:17

标签: asp.net sql-server-2008 linq-to-sql full-text-search

我正在将使用表适配器和存储过程创建的ASP.NET网站转换为使用Linq to SQL(.NET 4),因为它使整个事情更易于维护。

该应用程序是一个图书馆目录,我在SQL Server 2008 R2 express中使用全文搜索,以允许用户搜索各种字段,如标题,作者,出版商等。 我现有的全文搜索是一个存储过程,它根据用户指定的搜索参数生成动态查询。在LinQ to SQL中,我计划重用这个相同的查询,因为没有直接访问全文搜索。

查询本身始终执行正常。现在我在运行时从编译器继续获得“全文谓词null或空”,特别是在执行存储过程的行中:

IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), section_ID, division_ID, start_Catalogue_Number, end_Catalogue_Number, start_Revision_Date, end_Revision_Date, start_Added_Date, end_Added_Date, book_Type, searchTitle, searchAuthor, searchPublisher, searchDealer, searchPrinter, searchSummary, searchComments, searchString, searchStringsCombinator, searchConditionsCombinator, pageNumber, pageSize, resultCount);

所以,我尝试从头开始重建查询子句将子句添加到存储过程,并且全文搜索工作正常,直到“fulltext predicate null或empty”错误再次出现。

我只是看不出我在做什么有什么问题,而且它反复撞击砖墙。任何帮助将不胜感激。

刚才工作的存储过程是:

ALTER PROCEDURE dbo.AAATest
(
    /*Non-fulltext search parameters*/
    @Section_ID int = null,
    @Division_ID int = null,
    @Start_Catalogue_Number int = null,
    @End_Catalogue_Number int = null,
    @Start_Revision_Date smalldatetime = null,
    @End_Revision_Date smalldatetime = null,
    @Start_Added_Date smalldatetime = null,
    @End_Added_Date smalldatetime = null,
    @Book_Type int = null,

    /*Fulltext search parameters*/
    @SearchTitle bit = 0,
    @SearchAuthor bit = 0,
    @SearchPublisher bit = 0,
    @SearchDealer bit = 0,
    @SearchPrinter bit = 0,
    @SearchSummary bit = 0,
    @SearchComments bit = 0,
    @SearchString nvarchar(4000) = NULL,
    @SearchStringsCombinator nvarchar(3) = 'OR',
    @SearchConditionsCombinator nvarchar(3) = 'OR',

    /*Paging variables*/
    @PageNumber int = 0,
    @PageSize int = 10,

    /*Output parameters*/
    @ResultCount int OUTPUT
)

AS

DECLARE @DynamicSearchQuery nvarchar(MAX),
        @DynamicSearchClause nvarchar(MAX),
        @DynamicSearchParameters nvarchar(MAX),
        @FullTextClauseSubjects nvarchar(MAX),
        @FullTextClauseKeywords nvarchar(MAX)

SELECT @DynamicSearchQuery = 'SELECT Teikoku_Lib_Current_Books.Book_ID, Teikoku_Lib_Current_Books.Book_Catalogue_Number, Teikoku_Lib_Current_Books.Book_ISBN_Number, Teikoku_Lib_Current_Books.Book_Title, Teikoku_Lib_Current_Books.Book_Author, Teikoku_Lib_Current_Books.Book_Publication_Date, Teikoku_Lib_Current_Books.Book_Revision_Date, Teikoku_Lib_Current_Books.Book_Publisher, Teikoku_Lib_Current_Books.Book_Edition_Date, Teikoku_Lib_Current_Books.Book_Edition_Number, Teikoku_Lib_Current_Books.Book_Printer, Teikoku_Lib_Current_Books.Book_Dealer, Teikoku_Lib_Current_Books.Book_Number_Of_Copies, Teikoku_Lib_Current_Books.Book_Part, Teikoku_Lib_Current_Books.Book_Summary, Teikoku_Lib_Current_Books.Book_Comments, Teikoku_Lib_Current_Books.Book_Section_ID, Teikoku_Lib_Current_Books.Book_Division_ID, Teikoku_Lib_Current_Books.Book_Added_Date, Teikoku_Lib_Current_Books.Book_Type';
    SELECT @DynamicSearchQuery = @DynamicSearchQuery + ' ' + 'FROM Teikoku_Lib_Current_Books';
    SELECT @DynamicSearchQuery = @DynamicSearchQuery + ' ' + 'WHERE ';

/*Add static search conditions*/
/*Section and division data*/
SELECT @DynamicSearchQuery = @DynamicSearchQuery + '(Teikoku_Lib_Current_Books.Book_Section_ID = @dynSection_ID OR @dynSection_ID IS NULL)';
SELECT @DynamicSearchQuery = @DynamicSearchQuery + ' AND ';
SELECT @DynamicSearchQuery = @DynamicSearchQuery + '(Teikoku_Lib_Current_Books.Book_Division_ID = @dynDivision_ID OR @dynDivision_ID IS NULL)';
SELECT @DynamicSearchQuery = @DynamicSearchQuery + ' AND ';
/*Book type*/
SELECT @DynamicSearchQuery = @DynamicSearchQuery + '(Teikoku_Lib_Current_Books.Book_Type = @dynBook_Type OR @dynBook_Type IS NULL)';
SELECT @DynamicSearchQuery = @DynamicSearchQuery + ' AND ';
/*Catalogue number*/
SELECT @DynamicSearchQuery = @DynamicSearchQuery + '(Teikoku_Lib_Current_Books.Book_Catalogue_Number >= @dynStart_Catalogue_Number OR @dynStart_Catalogue_Number IS NULL)';
SELECT @DynamicSearchQuery = @DynamicSearchQuery + ' AND ';
SELECT @DynamicSearchQuery = @DynamicSearchQuery + '(Teikoku_Lib_Current_Books.Book_Catalogue_Number <= @dynEnd_Catalogue_Number OR @dynEnd_Catalogue_Number IS NULL)';
SELECT @DynamicSearchQuery = @DynamicSearchQuery + ' AND ';
/*Revision date*/
SELECT @DynamicSearchQuery = @DynamicSearchQuery + '(Teikoku_Lib_Current_Books.Book_Revision_Date >= @dynStart_Revision_Date OR @dynStart_Revision_Date IS NULL)';
SELECT @DynamicSearchQuery = @DynamicSearchQuery + ' AND ';
SELECT @DynamicSearchQuery = @DynamicSearchQuery + '(Teikoku_Lib_Current_Books.Book_Revision_Date <= @dynEnd_Revision_Date OR @dynEnd_Revision_Date IS NULL)';
SELECT @DynamicSearchQuery = @DynamicSearchQuery + ' AND ';
SELECT @DynamicSearchQuery = @DynamicSearchQuery + '(Teikoku_Lib_Current_Books.Book_Added_Date >= @dynStart_Added_Date OR @dynStart_Added_Date IS NULL)';
SELECT @DynamicSearchQuery = @DynamicSearchQuery + ' AND ';
SELECT @DynamicSearchQuery = @DynamicSearchQuery + '(Teikoku_Lib_Current_Books.Book_Added_Date <= @dynEnd_Added_Date OR @dynEnd_Added_Date IS NULL)';

/*Dynamic search conditions*/
IF @SearchString IS NOT NULL
BEGIN

    /*Set combinator for the search strings*/ 
    IF @SearchStringsCombinator <> 'OR' AND @SearchStringsCombinator <> 'AND'
        SELECT @SearchStringsCombinator = 'OR'

    /*Replace underscore separators used in the querystring with the search string combinator keyword*/
    SELECT @SearchString = REPLACE(RTRIM(LTRIM(REPLACE(REPLACE(LTRIM(RTRIM(@SearchString)), '_', ' '), ' ', ' '))), ' ', ' ' + @SearchStringsCombinator + ' ');

    /*Fulltext search on the title*/
    IF @SearchTitle > 0
        SELECT @DynamicSearchClause = 'CONTAINS(Teikoku_Lib_Current_Books.Book_Title, @dynSearchString)';

    /*Fulltext search on the author*/
    IF @SearchAuthor > 0
        BEGIN
        IF @DynamicSearchClause IS NULL
            SELECT @DynamicSearchClause = 'CONTAINS(Teikoku_Lib_Current_Books.Book_Author, @dynSearchString)';
        ELSE
            SELECT @DynamicSearchClause = @DynamicSearchClause + ' ' + @SearchConditionsCombinator + ' ' + 'AND CONTAINS(Teikoku_Lib_Current_Books.Book_Author, @dynSearchString)';
        END

    /*Fulltext search on the publisher*/
    IF @SearchPublisher > 0
        BEGIN
        IF @DynamicSearchClause IS NULL
            SELECT @DynamicSearchClause = 'CONTAINS(Teikoku_Lib_Current_Books.Book_Publisher, @dynSearchString)';
        ELSE
            SELECT @DynamicSearchClause = @DynamicSearchClause + ' ' + @SearchConditionsCombinator + ' ' + 'AND CONTAINS(Teikoku_Lib_Current_Books.Book_Publisher, @dynSearchString)';
        END

    /*Fulltext search on the dealer*/
    IF @SearchDealer > 0
        BEGIN
        IF @DynamicSearchClause IS NULL
            SELECT @DynamicSearchClause = 'CONTAINS(Teikoku_Lib_Current_Books.Book_Dealer, @dynSearchString)';
        ELSE
            SELECT @DynamicSearchClause = @DynamicSearchClause + ' ' + @SearchConditionsCombinator + ' ' +'CONTAINS(Teikoku_Lib_Current_Books.Book_Dealer, @dynSearchString)';
        END

    /*Fulltext search on the printer*/
    IF @SearchPrinter > 0
        BEGIN
        IF @DynamicSearchClause IS NULL
            SELECT @DynamicSearchClause = 'CONTAINS(Teikoku_Lib_Current_Books.Book_Printer, @dynSearchString)';
        ELSE
            SELECT @DynamicSearchClause = @DynamicSearchClause + ' ' + @SearchConditionsCombinator + ' ' + 'CONTAINS(Teikoku_Lib_Current_Books.Book_Printer, @dynSearchString)';
        END

    /*Fulltext search on the summary*/
    IF @SearchSummary > 0
        BEGIN
        IF @DynamicSearchClause IS NULL
            SELECT @DynamicSearchClause = 'CONTAINS(Teikoku_Lib_Current_Books.Book_Summary, @dynSearchString)';
        ELSE
            SELECT @DynamicSearchClause = @DynamicSearchClause + ' ' + @SearchConditionsCombinator + ' ' + 'CONTAINS(Teikoku_Lib_Current_Books.Book_Summary, @dynSearchString)';
        END

    /*Fulltext search on the comments*/
    IF @SearchComments > 0
        BEGIN
        IF @DynamicSearchClause IS NULL
            SELECT @DynamicSearchClause = 'CONTAINS(Teikoku_Lib_Current_Books.Book_Comments, @dynSearchString)';
        ELSE
            SELECT @DynamicSearchClause = @DynamicSearchClause + ' ' + @SearchConditionsCombinator + ' ' + 'CONTAINS(Teikoku_Lib_Current_Books.Book_Comments, @dynSearchString)';
        END

    /*Add the dynamic conditions to the query*/
    IF @DynamicSearchClause IS NOT NULL
        SELECT @DynamicSearchQuery = @DynamicSearchQuery + 'AND (' + @DynamicSearchClause + ')';

END

/*Dynamic query variables declaration*/
SELECT @DynamicSearchParameters = '@dynSection_ID int = null, @dynDivision_ID int = null, @dynStart_Catalogue_Number int = null,
    @dynEnd_Catalogue_Number int = null, @dynStart_Revision_Date smalldatetime = null, @dynEnd_Revision_Date smalldatetime = null,
    @dynStart_Added_Date smalldatetime = null, @dynEnd_Added_Date smalldatetime = null, @dynBook_Type int = null, @dynSearchString nvarchar(4000)';

/*Create table to hold results temporarily*/
CREATE table #searchResults
(
    temp_Book_ID int IDENTITY(1,1),
    Book_ID int,
    Book_Catalogue_Number int,
    Book_ISBN_Number nvarchar(13),
    Book_Title nvarchar(200),
    Book_Author nvarchar(200),
    Book_Publication_Date datetime,
    Book_Revision_Date datetime,
    Book_Publisher nvarchar(100),
    Book_Edition_Date datetime,
    Book_Edition_Number smallint,
    Book_Printer nvarchar(100),
    Book_Dealer nvarchar(100),
    Book_Number_Of_Copies int,
    Book_Part int,
    Book_Summary nvarchar(MAX),
    Book_Comments nvarchar(MAX),
    Book_Section_ID int,
    Book_Division_ID int,
    Book_Added_Date datetime,
    Book_Type int
)

INSERT INTO #searchResults  EXEC sp_executesql @DynamicSearchQuery, @DynamicSearchParameters, @Section_ID, @Division_ID, @Start_Catalogue_Number, 
    @End_Catalogue_Number, @Start_Revision_Date, @End_Revision_Date, @Start_Added_Date, @End_Added_Date, @Book_Type, @SearchString;

SELECT #searchResults.Book_ID, #searchResults.Book_Catalogue_Number, #searchResults.Book_ISBN_Number, 
    #searchResults.Book_Title, #searchResults.Book_Author, #searchResults.Book_Publication_Date, #searchResults.Book_Revision_Date, 
    #searchResults.Book_Publisher, #searchResults.Book_Edition_Date, #searchResults.Book_Edition_Number, #searchResults.Book_Printer, 
    #searchResults.Book_Dealer, #searchResults.Book_Number_Of_Copies, #searchResults.Book_Part, #searchResults.Book_Summary,
    #searchResults.Book_Comments, #searchResults.Book_Section_ID, #searchResults.Book_Division_ID, #searchResults.Book_Added_Date, 
    #searchResults.Book_Type 
    FROM #searchResults WHERE (#searchResults.temp_Book_ID >= (@PageNumber * @PageSize) AND #searchResults.temp_Book_ID <=  ((@PageNumber + 1) * @PageSize));

SELECT @ResultCount = COUNT(*) FROM #searchResults;

DROP TABLE #searchResults;

RETURN

我知道这很长,抱歉。但是,它基本上是一遍又一遍的代码。 存储过程的最后一位我需要获取查询返回的结果总数,这样我才能正确显示我的分页界面。

然后我从我的BLL中调用

return db.AAATest(SectionID, DivisionID, StartCatalogueNumber, EndCatalogueNumber, StartRevisionDate, EndRevisionDate,
        StartAddedDate, EndAddedDate, BookType, SearchTitle, SearchAuthor, SearchPublisher, SearchDealer, SearchPrinter,
        SearchSummary, SearchComments, SearchStrings, SearchStringCombinator, 
        SearchConditionsCombinator, PageNumber, PageSize, ref TotalRecords);

作为测试,我正在传递论据

lvCatalogueContent.DataSource = currentBook_Repository.GetCurrentBooksFiltered(null, null, null, null, null, null, null,
        null, null, true, false, false, false, false, false, false, true, true, "橋", null, null, null, null, null, 0, 20,
        ref totalRecords);

当我在SQL Server中测试存储过程时,这些参数工作得非常好......而且他们在ASP.NET中工作到很久以前。

更新:

我在编译器中遇到的确切错误是:

SqlException:“Null或Empty全文谓词” 等级:15 ErrorCode:-2146232060

1 个答案:

答案 0 :(得分:1)

好的,在整个早上一点一点地看着存储过程之后,我发现错误是由以下行引起的:

/*Replace underscore separators used in the querystring with the search string combinator keyword*/
SELECT @SearchString = REPLACE(RTRIM(LTRIM(REPLACE(REPLACE(LTRIM(RTRIM(@SearchString)), '_', ' '), ' ', ' '))), ' ', ' ' + @SearchStringsCombinator + ' ');

这包含在

IF @SearchString IS NOT NULL 
BEGIN
END

阻止以避免少量不必要的额外计算,但这似乎导致编译器认为全文谓词为null或为空。我已经移动了那个以及上一行检查组合器是否在包装器之外是OR还是AND,如果它看起来好像正在工作(现在无论如何)......

我发现的另一个选择是在调用存储过程之前在代码中处理搜索字符串。

希望有一天能帮到某人。