2017-08-03 120 views
1

我扩展了一个SELECT函数,以便从字符串列表中选择SELECT的自定义字段。为什么查询返回System.Data.Entity.Infrastructure.DbQuery <T>不是T-SQL查询字符串

你会看到图像的功能波纹管:SelectExtend()以线201

当我在调试模式快到。当我通过201行时,Watch窗口中的查询值是不同的。

我在调用SelectExtend()函数之前和之后捕获了图像。

任何人都可以向我解释为什么查询返回“System.Data.Entity.Infrastructure.DbQuery”,而不是“选择[Project1]。[ID],....”?

我希望查询返回的 “选择[PROJECT1]。[ID],......”

感谢您的阅读。

Before run over line 201

After 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-我的程序/ 20757916#20757916)或实现拦截器。有关示例,请参见[EF6.x将较差的SQL执行与应用程序代码关联](https://romiller.com/2016/02/11/ef6-x-correlating-poor-performing-sql-to-application-code/) –

+0

另外,考虑[LinqKit](https://github.com/scottksmith95/LINQKit)和[NeinLinq](https://github.com/axelheer/nein-linq)来动态构建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); 
} 

(也去掉了检查零个域,因为你的代码仍然可以做它应该。)

如果你仍然得到同样的结果,那么一切都可能会确定。毕竟,在调试器中看到的只是一个类决定显示的内容,默认情况下为.ToString()的结果。

相关问题