2017-08-03 15 views
1

文字列のリストからSELECTのカスタムフィールドを選択するためにSELECT関数を拡張しています。 SelectExtend()ライン201なぜクエリがSystem.Data.Entity.Infrastructure.DbQueryを返す<T> T-SQLクエリ文字列でない

で私がデバッグモードで実行しているとき:

あなたが画像で表示される機能がある怒鳴ります。ウォッチウィンドウのクエリ値は、私が201行目を実行すると異なります。

私はSelectExtend()関数を呼び出す前後の画像を取得しています。

「[Project1]。[ID]、....」を選択するのではなく、「System.Data.Entity.Infrastructure.DbQuery」を返す理由は誰でもわかります。

は、私は、クエリ・リターン "を選択し、[Project1の]。[ID]、...." 読書のための

感謝をしたいです。ここ

After run over line 201

そして

Before run over line 201

は、関数のソースコードです "SelectExtend()"

public static IQueryable<T> SelectExtend<T>(this IQueryable<T> source, List<string> fields) 
    { 
     if (fields == null || fields.Count <= 0) 
      throw new ArgumentException("'fields' can not be null or empty."); 

     var parameter = Expression.Parameter(source.ElementType, "x"); 
     var body = Expression.MemberInit(
      Expression.New(typeof(T)), 
      fields.Select(field => Expression.Bind(
       typeof(T).GetProperty(field), 
       Expression.PropertyOrField(parameter, field)) 
      ) 
     ); 

     var selector = Expression.Lambda(body, parameter); 
     var expression = Expression.Call(
      typeof(Queryable) 
      , "Select" 
      , new[] { source.ElementType, selector.Body.Type } 
      , source.Expression 
      , Expression.Quote(selector) 
     ); 

     return source.Provider.CreateQuery<T>(expression); 
    } 
+0

SQLトランスレータが実行された後にのみSQLを生成する内部表現です。 [DbContext.Database.Logプロパティを設定する](https://stackoverflow.com/questions/16880687/how-can-i-log-the-generated-sql-from-dbcontext-savechanges-in- my-program/20757916#20757916)、インターセプタを実装してください。例については、[EF6.xアプリケーションコードへのSQLの悪い相関の関係](https://romiller.com/2016/02/11/ef6-x-correlating-poor-performing-sql-to-application-code/)を参照してください。 –

+0

また、LINQ式を動的に構築するには[LinqKit](https://github.com/scottksmith95/LINQKit)と[NeinLinq](https://github.com/axelheer/nein-linq)を検討してください。そして、不完全なエンティティを取得するのではなく、DTOを作成したいと思います。 [Automapper](https://github.com/AutoMapper/AutoMapper.EF6)を確認してください –

+0

クエリがSQLに変換できず、エンティティタイプへの投影により実行時例外が生成される可能性が高いと考えられます。 –

答えて

0

何が起こっているのか正確にわかりません。通常、プロバイダを呼び出すメソッドはQueryable.XXXで、それ自体に呼び出しの式を渡します。彼らはどういうわけか別の方法でやるかもしれない。

.Selectを呼び出して返すものを返します(クリーナーコードをボーナスとして返す)ようにメソッドを変更するとどうなりますか?

あなたのケースでは、typeof(T)source.ElementTypeselector.Body.Typeはすべて同じです。

public static IQueryable<T> SelectExtend<T>(this IQueryable<T> source, IList<string> fields) 
{ 
    if (source == null) throw new ArgumentNullException(nameof(source)); 
    if (fields == null) throw new ArgumentNullException(nameof(fields)); 

    var parameter = Expression.Parameter(typeof(T), "x"); 
    var body = Expression.MemberInit(
     Expression.New(typeof(T)), 
     fields.Select(field => Expression.Bind(
      typeof(T).GetProperty(field), 
      Expression.PropertyOrField(parameter, field)) 
     ) 
    ); 
    var selector = Expression.Lambda<Func<T, T>>(body, parameter); 
    return source.Select(selector); 
} 

(あなたのコードはまだそれがになって何を行うことができますので、また、ゼロフィールドのチェックを削除しました。)

それでも同じ結果を得る場合には、すべてがOKかもしれません。結局のところ、デバッガで表示されるものは、クラスが表示することを決定するもので、デフォルトでは.ToString()という結果になります。

関連する問題