IEnumerable とIQueryable 、違いは何ですか?

Khabrovchiansの皆さん、私は少し前に出会ったLinqToSqlを使用した明らかでない瞬間を共有することにしました。 つまり、カスケードLinqクエリを使用する機能について:



次のASP.NET MVCプロジェクトに取り組み、データベースへのアクセスレベルを設計するために、L2Cフレームワークによって生成されたスクリプトの品質を確認する必要がありました。



私たちが持っているもの(モデルの簡略版):



クラスUser {

パブリック長いID {get; セット; }

パブリック文字列Name {get; セット; }

public IEnumerable <Parameter>パラメーター{get; セット; }

}



クラスパラメータ{

public long UserId {get; セット; }

パブリック文字列Name {get; セット; }

パブリック文字列値{get; セット; }

}



データを取得するには、UserRepositoryクラスを作成します。



クラスUserRepository:MyProjectDataContext {

public IEnumerable GetUsers(){

return this.Users.ToModelUsers();

}

}



静的クラスRepositoryHelper {

public static IEnumerable <Model.User> ToModelUsers(このIEnumerable <DataAccess.User>ユーザー){

return users.Select(u => new Model.User {Id = u.Id、Name = u.Name、Parameters = u.Parameters.ToModelParameters()});

}



public static IEnumerable <Model.Parameter> ToModelParameters(このIEnumerable <DataAccess.Parameter>パラメーター){

パラメータを返します。Select(u => new Model.Parameter {...});

}

}



書きます

var users = userRepository.GetUsers()。ToList();



プロファイラーを見ると、驚いたことに、 10人のユーザーとそのパラメーターをダウンロードするために、 11ものリクエストが行われました。



この問題を解決しようとしています。リポジトリコードを次のように変更します。



public IEnumerable <User> GetUsers(){

return this.Users.ToModelUsers()。Select(u => new Model.User {

Id = u.Id、Name = u.Name、Parameters = u.Parameters.Select(p => new Model.Parameter {...})

});

}



状況は劇的に変化しています。 ユーザーとパラメーターの両方がロードされる1つのリクエストのみ



犬はどこに埋葬されていますか?



元のバージョンでは、GetUsersメソッドを呼び出した後、Linq2SqlとLinq2Objectの2つの異なる式を含むリクエストを受信しました。



そして今、結論



判明したように、IEnumerable型とIQueryable型の変数を使用すると、Linq拡張機能の動作が大きく異なりますが、これは偶然ではありません。 実際には、System.Linq.EnumerableクラスとSystem.Linq.Queryableクラスの両方にそれぞれuser.Select(...)メソッドがありますが、実装はもちろん異なります(Reflectorを使用して簡単に検証できます)。



どうする



戻り値にIQueryable <T>型を指定するには、2つの方法があります



静的クラスRepositoryHelper {

public static IQueryable <Model.User> ToModelUsers(このIQueryable <DataAccess.User>ユーザー){

return users.Select(u => new Model.User {Id = u.Id、Name = u.Name、Parameters = u.Parameters.ToModelParameters()});

}

}



.AsQueryable <T>()メソッドを呼び出して、IEnumerable <T>をIQueryable <T>に明示的にキャストします。



そして、最も重要なことは、注意を払い続けることであり、構文上のシュガー機能の背後に隠されているものを忘れないことです。Net3.5 / 4.0



All Articles