none
请教一个LINQ的反射问题 RRS feed

  • 问题

  • db.sd.Where("it.fr>0").Take(1).Single();是可以执行的

    db, sd已知的情况下(sd是db里的一个实体)

    反射出Where("it.fr>0").Take(1).Single();的结果

    要如何反射?


    var db = new Entities1()
      object sd = db.sd;.....

      if (db != null)
      {
      MethodInfo miWhere = db.PropertyType.GetMethod("Where"); //反射Where方法

      if (miWhere != null)  

      {
      var wh = miWhere.Invoke(sd, new object[] { "it.fr>0", new System.Data.Objects.ObjectParameter[] { } }); //Where("it.fr>0")
      //现在怎样反射出.Take(1).Single()方法?

      }
      }

    2011年8月29日 5:45

答案

全部回复

  • Take 和 Single 是定义在 IEnumerable<T> 或者 IQueryable<T> 接口上的扩展方法,其实现类为 EnumerableExtensions 或者 QueryableExtensions,您需要确定您的 Linq to SQL 调用是延迟执行 (Deferred Execution) 或者是立即执行 (Immediate Execution) 的,延迟执行的,使用 IQueryable 的实现,否则使用 IEnumerable 的实现。
    Mark Zhou
    2011年8月29日 9:41
  • Hi tonny,

    首先如果你使用的是LINQ的Where, Take, Single方法,那么表达式写的并不正确,应该是db.sd.Where(it => it.fr > 0).First()。

    然后,由于Where, First都是扩展方法,所以可以在Queryable类型上来调用。

    请参考 How to: Use Expression Trees to Build Dynamic Queries (C# and Visual Basic)


    Tech Blog: http://gildor.cnblogs.com
    2011年8月29日 10:04
  • 如果我没有理解错的话,下面的代码可以实现你的目的(假设实体类型是Entity):

     

    var db = new Entities1();
    var sd = db.sd.AsQueryable();
    
    // 创建查询表达式
    Expression<Func<Entity, bool>> filter = p => p.fr > 0;
    
    // 在Queryable类上调用Where方法
    var whereExpression= Expression.Call(typeof(Queryable), "Where", new[] { typeof(Entity) }, sd.Expression, filter);
    
    // 创建查询
    var resultQuery = sd.Provider.CreateQuery<Entity>(whereExpression);
    
    //最后执行查询:
    Console.WriteLine(resultQuery.First());
    
    db.Dispose();
    
    //其他扩展方法依次类推
    


     


    Tech Blog: http://gildor.cnblogs.com
    2011年8月29日 10:16
  • Hi tonny,

    首先如果你使用的是LINQ的Where, Take, Single方法,那么表达式写的并不正确,应该是db.sd.Where(it => it.fr > 0).First()。

    然后,由于Where, First都是扩展方法,所以可以在Queryable类型上来调用。

    请参考 How to: Use Expression Trees to Build Dynamic Queries (C# and Visual Basic)


    Tech Blog: http://gildor.cnblogs.com

    db.sd.Where(it => it.fr > 0).First()。能用反射的方法反射出First()方法吗?
    2011年8月29日 12:42
  • 如果我没有理解错的话,下面的代码可以实现你的目的(假设实体类型是Entity):

     

    var db = new Entities1();
    var sd = db.sd.AsQueryable();
    
    // 创建查询表达式
    Expression<Func<Entity, bool>> filter = p => p.fr > 0;
    
    // 在Queryable类上调用Where方法
    var whereExpression= Expression.Call(typeof(Queryable), "Where", new[] { typeof(Entity) }, sd.Expression, filter);
    
    // 创建查询
    var resultQuery = sd.Provider.CreateQuery<Entity>(whereExpression);
    
    //最后执行查询:
    Console.WriteLine(resultQuery.First());
    
    db.Dispose();
    
    //其他扩展方法依次类推
    


     


    Tech Blog: http://gildor.cnblogs.com
    因为我的Where是字符串"it.fr>0" 不是表达式,所以你这方法没办法用
    2011年8月29日 12:43
  • 因为我的Where是字符串"it.fr>0" 不是表达式,所以你这方法没办法用

    那你可以(1)手动拼装Expression Tree,或者(2)用CodeDom来运行时将字符串拼接后编译成Expression,然后再作为Where的参数传递。

    参考:

    http://msdn.microsoft.com/en-us/library/bb397951.aspx

    http://msdn.microsoft.com/en-us/library/y2k85ax6.aspx


    Tech Blog: http://gildor.cnblogs.com
    • 已标记为答案 tonny2003 2011年8月30日 1:03
    2011年8月29日 13:43
  • db.sd.Where(it => it.fr > 0).First()。能用反射的方法反射出First()方法吗?
    可以,有两个地方可以调用First,一个是在CreateQuery之后,另一个是在CreateQuery所传入的query中。不过如果要作为CreateQuery方法的参数Expression的话,必须是返回IQueryable的方法才可以,所以可以用Take(1),而且这样最后还是需要一个First()或者foreach来触发查询。
    Tech Blog: http://gildor.cnblogs.com
    2011年8月29日 13:48