0

だから私はこの機能を持っています:

public static BaseList GetVersesByChapterVerseRanges(string translation, BaseList criteriaList) { BaseList returnValue = new BaseList();;

    if(criteriaList.Count() > 0)
    {

        List<VerseMaster.BusinessLayer.Vers> queryList = new List<Vers>();

        int bookId = criteriaList[0].Book.BookId;
        int StartChapter = criteriaList[0].StartChapter;
        int EndChapter = criteriaList[0].EndChapter;
        int StartVerse = criteriaList[0].StartChapterStartVerse;
        int EndVerse = criteriaList[0].EndChapterEndVerse;
        var searchQuery = (from v in VerseMaster.BusinessLayer.Controller.Controller.VerseMasterEntities.Verses where v.Translation.ToLower().StartsWith(translation.ToLower()) && v.BookId == bookId && v.ChapterNumber >= StartChapter && v.ChapterNumber <= EndChapter && (v.ChapterNumber == StartChapter ? (v.VerseNumber >= StartVerse) : true) && (v.ChapterNumber == EndChapter ? (v.VerseNumber <= EndVerse) : true) orderby v.ChapterNumber, v.VerseNumber ascending select v);


        for(int i = 1; i < criteriaList.Count(); i++)
        {
            bookId = criteriaList[i].Book.BookId;
            StartChapter = criteriaList[i].StartChapter;
            EndChapter = criteriaList[i].EndChapter;
            StartVerse = criteriaList[i].StartChapterStartVerse;
            EndVerse = criteriaList[i].EndChapterEndVerse;
            VerseMaster.BusinessLayer.DataObjects.Helper.VerseSearchCriteria criteria = criteriaList[i];
            searchQuery = (System.Linq.IOrderedQueryable<VerseMaster.BusinessLayer.Vers>)searchQuery.Concat(from v in VerseMaster.BusinessLayer.Controller.Controller.VerseMasterEntities.Verses where v.Translation.ToLower().StartsWith(translation.ToLower()) && v.BookId == bookId && v.ChapterNumber >= StartChapter && v.ChapterNumber <= EndChapter && (v.ChapterNumber == StartChapter ? (v.VerseNumber >= StartVerse) : true) && (v.ChapterNumber == EndChapter ? (v.VerseNumber <= EndVerse) : true) orderby v.ChapterNumber, v.VerseNumber ascending select v);

        }

        string traceString = ((System.Data.Objects.ObjectQuery)searchQuery).ToTraceString();

        foreach (var entVerse in searchQuery)
        {
            VerseMaster.BusinessLayer.DataObjects.IVerse verse = new VerseMaster.BusinessLayer.DataObjects.Verse();
            LoadVerseFromEntityVerse(ref verse, entVerse);

            Console.Write(String.Format("Chapter={0} Verse={1} Text={2}\n", entVerse.ChapterNumber, entVerse.VerseNumber, entVerse.Verse));
            //returnValue.Add((VerseMaster.BusinessLayer.DataObjects.Verse)verse);
        }
    }

    return returnValue;
}

そのため、何らかの理由で、関連するかどうかわからないエラーのために、linqクエリに入る各パラメーターを標準のintに変換する必要がありました。したがって、生成されたSQLは次のとおりです。

 SELECT 
[UnionAll2].[C1] AS [C1], 
[UnionAll2].[C2] AS [C2], 
[UnionAll2].[C3] AS [C3], 
[UnionAll2].[C4] AS [C4], 
[UnionAll2].[C5] AS [C5], 
[UnionAll2].[C6] AS [C6]
FROM  (SELECT 
    [UnionAll1].[VerseId] AS [C1], 
    [UnionAll1].[ChapterNumber] AS [C2], 
    [UnionAll1].[VerseNumber] AS [C3], 
    [UnionAll1].[Verse] AS [C4], 
    [UnionAll1].[Translation] AS [C5], 
    [UnionAll1].[BookId] AS [C6]
    FROM  (SELECT 
        [Extent1].[VerseId] AS [VerseId], 
        [Extent1].[ChapterNumber] AS [ChapterNumber], 
        [Extent1].[VerseNumber] AS [VerseNumber], 
        [Extent1].[Verse] AS [Verse], 
        [Extent1].[Translation] AS [Translation], 
        [Extent1].[BookId] AS [BookId]
        FROM [dbo].[Verses] AS [Extent1]
        WHERE (( CAST(CHARINDEX(LOWER(@p__linq__0), LOWER([Extent1].[Translation])) AS int)) = 1) AND ([Extent1].[BookId] = @p__linq__1) AND ([Extent1].[ChapterNumber] >= @p__linq__2) AND ([Extent1].[ChapterNumber] <= @p__linq__3) AND ((CASE WHEN ([Extent1].[ChapterNumber] = @p__linq__4) THEN CASE WHEN ([Extent1].[VerseNumber] >= @p__linq__5) THEN cast(1 as bit) WHEN ( NOT ([Extent1].[VerseNumber] >= @p__linq__5)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1) AND ((CASE WHEN ([Extent1].[ChapterNumber] = @p__linq__6) THEN CASE WHEN ([Extent1].[VerseNumber] <= @p__linq__7) THEN cast(1 as bit) WHEN ( NOT ([Extent1].[VerseNumber] <= @p__linq__7)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1)
    UNION ALL
        SELECT 
        [Extent2].[VerseId] AS [VerseId], 
        [Extent2].[ChapterNumber] AS [ChapterNumber], 
        [Extent2].[VerseNumber] AS [VerseNumber], 
        [Extent2].[Verse] AS [Verse], 
        [Extent2].[Translation] AS [Translation], 
        [Extent2].[BookId] AS [BookId]
        FROM [dbo].[Verses] AS [Extent2]
        WHERE (( CAST(CHARINDEX(LOWER(@p__linq__8), LOWER([Extent2].[Translation])) AS int)) = 1) AND ([Extent2].[BookId] = @p__linq__9) AND ([Extent2].[ChapterNumber] >= @p__linq__10) AND ([Extent2].[ChapterNumber] <= @p__linq__11) AND ((CASE WHEN ([Extent2].[ChapterNumber] = @p__linq__12) THEN CASE WHEN ([Extent2].[VerseNumber] >= @p__linq__13) THEN cast(1 as bit) WHEN ( NOT ([Extent2].[VerseNumber] >= @p__linq__13)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1) AND ((CASE WHEN ([Extent2].[ChapterNumber] = @p__linq__14) THEN CASE WHEN ([Extent2].[VerseNumber] <= @p__linq__15) THEN cast(1 as bit) WHEN ( NOT ([Extent2].[VerseNumber] <= @p__linq__15)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1)) AS [UnionAll1]
UNION ALL
    SELECT 
    [Extent3].[VerseId] AS [VerseId], 
    [Extent3].[ChapterNumber] AS [ChapterNumber], 
    [Extent3].[VerseNumber] AS [VerseNumber], 
    [Extent3].[Verse] AS [Verse], 
    [Extent3].[Translation] AS [Translation], 
    [Extent3].[BookId] AS [BookId]
    FROM [dbo].[Verses] AS [Extent3]
    WHERE (( CAST(CHARINDEX(LOWER(@p__linq__16), LOWER([Extent3].[Translation])) AS int)) = 1) AND ([Extent3].[BookId] = @p__linq__17) AND ([Extent3].[ChapterNumber] >= @p__linq__18) AND ([Extent3].[ChapterNumber] <= @p__linq__19) AND ((CASE WHEN ([Extent3].[ChapterNumber] = @p__linq__20) THEN CASE WHEN ([Extent3].[VerseNumber] >= @p__linq__21) THEN cast(1 as bit) WHEN ( NOT ([Extent3].[VerseNumber] >= @p__linq__21)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1) AND ((CASE WHEN ([Extent3].[ChapterNumber] = @p__linq__22) THEN CASE WHEN ([Extent3].[VerseNumber] <= @p__linq__23) THEN cast(1 as bit) WHEN ( NOT ([Extent3].[VerseNumber] <= @p__linq__23)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1)) AS [UnionAll2]

したがって、問題は、何らかの理由で、同じパラメーターの 3 つのセットを送信して連結したかのように、指定した各パラメーターを処理するため、同じ詩のセットを 3 回返すことです。私はlinqまたはエンティティフレームワークの専門家ではないので、なぜこれを行うのかわかりません。何か提案はありますか?

4

1 に答える 1

2

これは、変更されたクロージャの問題の非常にトリッキーな例です。forループでは、変数などを使用するクエリパーツを生成します。bookIdクエリが実行されるときに、ループの最後の反復後の値である、これらの変数がその時点で持っている値を使用します。(トリッキーな部分は、通常、ループ変数がキャプチャされることですが、ここでは、ループスコープ外で宣言された変数についてです)。

各クエリ部分が変数の独自のインスタンス(クロージャと呼ばれる)をキャプチャするため、forループ内で変数を宣言した場合は異なります。

良いニュース:これを行うと同時に、コードをクリーンアップすることができます!

if(criteriaList.Count() > 0)
{
    IQueryable<Verse> baseQuery = null;
    for(int i = 0; i < criteriaList.Count(); i++) // starting i = 0 now !
    {
        int bookId = criteriaList[0].Book.BookId;
        int StartChapter = criteriaList[0].StartChapter;
        int EndChapter = criteriaList[0].EndChapter;
        int StartVerse = criteriaList[0].StartChapterStartVerse;
        int EndVerse = criteriaList[0].EndChapterEndVerse;
        searchQuery = (IOrderedQueryable<Vers>)searchQuery.Concat(
            from v in Controller.Controller.VerseMasterEntities.Verses 
            where v.Translation.ToLower().StartsWith(translation.ToLower()) 
                && v.BookId == bookId 
                && v.ChapterNumber >= StartChapter 
                && v.ChapterNumber <= EndChapter 
                && (v.ChapterNumber == StartChapter ? (v.VerseNumber >= StartVerse) : true) 
                && (v.ChapterNumber == EndChapter ? (v.VerseNumber <= EndVerse) : true) 
            select v);

        if (i == 0)
            baseQuery = searchQuery;
        else
            baseQuery = baseQuery.Concat(searchQuery);
    }
    ...

(後で注文してください)

于 2012-05-23T13:13:45.913 に答える