3

LinqToSQL を使用してデータベースに対して実行される次の単純化された Linq クエリがあるとします。

public IEnumerable<MembershipDto> GetAllUserMemberships()
{
    return (from m in _workspace.GetDataSource<UserMembership>()
            join g in _workspace.GetDataSource<Group>()
                on m.GroupID equals g.GroupID
            join u in _workspace.GetDataSource<User>()
                on m.UserID equals u.UserID
            select 
                new MembershipDto
                {
                    GroupID = g.GroupID,
                    GroupName = g.Name,
                    UserID = u.UserID,
                    UserName = u.Name
                }
            ).Distinct()
             .OrderBy(x => x.GroupName)
             .ThenBy(x => x.UserName);
}

パフォーマンスのために、生成された SQL クエリ内でこのクエリをできるだけ多く実行したいと考えています。ただし、Linq でビジネス ロジックを維持して、簡単に単体テストできるようにしたいと考えています。

私が抱えている問題は、上記のクエリが SQL での実行を停止し、メモリ内で操作を開始する場所がわからないことです。

私の仮定では、データが選択されるとすぐにnew MembershipDto、SQL で実行されなくなります。したがって、後続の操作OrderBy() ThenBy()Distinct()操作はメモリ内で発生します。

ただし、ではなくOrderBy()型のコレクションが生成されます。これは、クエリが SQL で完全に実行される可能性があることを示しています。IOrderedQueryableIOrderedEnumerable

私の仮定は正しいですか、それともクエリ全体が SQL に変換されますか?もしそうなら、なぜそうなるのでしょうか?

4

2 に答える 2

1

あなたが投稿したコードすべてSQLに変換されると思います。MembershipDto() 構造は、select ステートメントにマップされます。

関数が IEnumerable にキャストされ、列挙子が実行されると、Linq to Sql を「終了」し、Linq to Objects を「開始」します。

Linq to Sql で開発している場合、これを自分でテストするためのツールを用意することが絶対に不可欠です。

LINQPadをお勧めします。C# でコーディングすると、生成された SQL が表示されます。

もう 1 つの解決策は、生成された SQL をデータ コンテキスト内でログに記録することです。

#if DEBUG
        /// <summary>
        /// Code which runs when the data context is created; called from the constructor
        /// </summary>
        /// <remarks>Adds console and/or ASP.NET trace logger in DEBUG builds only</remarks>
        partial void OnCreated()
        {
            this.DebugBuildLogging();
        }
#endif

また、LINQ に関する優れた本を読むことをお勧めします。何度でも報われます。

于 2013-06-13T16:56:31.923 に答える