【问题标题】:does converting IQueryable to IEnumerable execute the query again?将 IQueryable 转换为 IEnumerable 会再次执行查询吗?
【发布时间】:2011-05-02 23:52:38
【问题描述】:

在我的查询中,我需要返回IEnumerable,但我不知道此操作是否会使查询再次执行?

var data = Repository<Person>.Find().AsEnumerable();

Find() 返回IQueryable 并且因为IQueryable 继承IEnumerable。我怀疑AsEnumerable 是否会重复执行。

我知道 var data = Repository<Person>.Find().ToList() 执行两次查询。一个用于Find(),第二个用于Tolist()

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    AsEnumerable 除了将as 运算符应用于您的 IQueryable 之外,实际上并没有做任何事情。因此,您应用于对象的任何未来方法都将使用 System.Linq.Enumerable 扩展方法集,而不是 System.Linq.Queryable 方法。

    这都是关于延迟执行的。在您尝试枚举之前,不会对您的可查询源(大概是数据库)执行任何操作。

    换句话说:

    var data=Repository.Find().AsEnumerable() 
    /* The query is only actually performed AFTER here */  
    .ToList();
    

    如果你的代码:

    var data=Repository.Find().ToList();
    

    执行两次查询,这是因为您在 Find() 方法中做错了事情,绝对不应该是这种情况。

    var data = Respository.Find();
    

    应该执行查询零次。

    var result = data.ToList(); // THIS is what should execute the query.
    

    【讨论】:

    • 你是对的,我在 find 方法的末尾有 tolist(),我没有注意到。sry
    • 您提到了 IQueryable 如何从 IEnumerable 继承,因此 AsEnumerable 不会保证对数据库的任何运行。但是,您还提到了对象上的后续方法将如何使用 IEnumerable 上的方法而不是 IQueryable。从这个意义上说,是否意味着一旦我运行了 IEnumerable 方法,查询就会执行,返回并在内存中被查询?还是“只有在调用 GetEnumerator() 时才在数据库上执行”的规则仍然成立?
    【解决方案2】:

    将 linq 视为“流”,聚合函数是“冲洗”。 “linq to db”流只能刷新一次。 .AsEnumerable(), .Where(), .... 是一种准备查询的方法 .ToList(), .First(), .Max() 是一个聚合 但如果你不调用聚合,那么你的 linq 结果将不会运行。它只有在被枚举时才开始工作。

    var result = users.Select(usr => usr.Name);
    

    直到

    1 个聚合被调用

    result.First()
    

    或正在枚举 2 个结果

    result.ToList().ForEach(...)
    

    回答你的问题 - .Find(), .AsEnumerable() 不是聚合函数

    【讨论】:

      【解决方案3】:

      一个 IQueryable 一个 IEnumerable。没有转换,因此没有任何工作正在进行。

      当你调用GetEnumerator()时,工作就会发生,无论是显式调用还是调用foreach

      另外,您确认Repository.Find().ToList() 两次调用SQL 了吗?这对我来说听起来不对。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-16
      • 2023-02-23
      • 1970-01-01
      • 2016-01-09
      • 1970-01-01
      相关资源
      最近更新 更多