• IQueryable和IEnumerable的区别


    IEnumerable接口

    公开枚举器,该枚举器支持在指定类型的集合上进行简单迭代。也就是说:实现了此接口的object,就可以直接使用foreach遍历此object;

    IQueryable 接口

    它继承 IEnumerable 接口,而因为.net版本加入Linq和IQueryable后,使得IEnumerable不再那么单调,变得更加强大和丰富。

    1、IQueryable只是代表一个"可以放到数据库服务器去执行的查询",它没有立即执行,只是"可以被执行"而已

    2、对于IQueryable接口调用非终结方法的时候不会执行查询,而调用终结方法的时候则会立即执行查询

    3、终结方法:遍历、ToArray()、ToList()、Min()、Max()、Count()等

    4、非终结方法:GroupBy()、OrderBy()、Include()、Skip()、Take()等

    5、简单判断:一个方法的返回值类型如果是IQueryable类型,那么这个方法一般就是非终结方法,否则就是终结方法

    为了区别两个接口,我们通过一个实际的例子来解释一下。

    [TestMethod]
           public void LinqTest()
           {
               var db = new SecurityRepositoryContext(new HSLogger());
               var ur = new UserRepository(db);
               //查询的结果放入IQueryable接口的集合中
               IQueryable<User> querys = (from c in db.Context.Set<User>()
                                          orderby c.Code
                                          select c).Skip<User>(2).Take<User>(2);
               //注意这个AsEnumerable<User>()在分页查询之前,先将其转换成IEnumerable类型
               IEnumerable<User> enumers = (from c in db.Context.Set<User>()
                                            orderby c.Code
                                            select c).AsEnumerable<User>().Skip<User>(2).Take<User>(2);
               //因为启用了延迟加载机制,所以下面调用一下,才会真正去读取数据库
               foreach (var c in querys)
               {
                   //TODO
               }
               foreach (var c in enumers)
               { 
                   //TODO
               }
           }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    跟踪一下代码,看一下这两段在执行时所生成的SQL代码:
    第一段,返回IQueryable接口类型:

    SELECT
        [Extent1].[Id] AS [Id], 
        [Extent1].[Code] AS [Code], 
        [Extent1].[Name] AS [Name], 
        [Extent1].[Status] AS [Status], 
        [Extent1].[IsOnline] AS [IsOnline], 
        [Extent1].[SystemVersion] AS [SystemVersion], 
        [Extent1].[CreatedBy] AS [CreatedBy], 
        [Extent1].[CreatedOn] AS [CreatedOn], 
        [Extent1].[ModifiedBy] AS [ModifiedBy], 
        [Extent1].[ModifiedOn] AS [ModifiedOn], 
        [Extent1].[VersionNumber] AS [VersionNumber]
        FROM [dbo].[User] AS [Extent1]
        ORDER BY [Extent1].[Code] ASC
        OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    第二段,返回IEnumerable接口类型:

    SELECT
        [Extent1].[Id] AS [Id], 
        [Extent1].[Code] AS [Code], 
        [Extent1].[Name] AS [Name], 
        [Extent1].[Status] AS [Status], 
        [Extent1].[IsOnline] AS [IsOnline], 
        [Extent1].[SystemVersion] AS [SystemVersion], 
        [Extent1].[CreatedBy] AS [CreatedBy], 
        [Extent1].[CreatedOn] AS [CreatedOn], 
        [Extent1].[ModifiedBy] AS [ModifiedBy], 
        [Extent1].[ModifiedOn] AS [ModifiedOn], 
        [Extent1].[VersionNumber] AS [VersionNumber]
        FROM [dbo].[User] AS [Extent1]
        ORDER BY [Extent1].[Code] ASC
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    通过上面两个例子我总结了一下,IQueryable接口与IEnumberable接口的区别:

    IEnumerable 泛型类在调用自己的SKip 和 Take 等扩展方法之前数据就已经加载在本地内存里了,而IQueryable 是将Skip ,take 这些方法表达式翻译成T-SQL语句之后再向SQL服务器发送命令,它并不是把所有数据都加载到内存里来才进行条件过滤。

    转自

    EFCore中所谓IQueryable
    IQueryable和IEnumerable的区别

  • 相关阅读:
    砥砺的前行|基于labview的机器视觉图像处理|NI Vision Assisant(二)——界面介绍
    抽象类和接口
    全球城市汇总【最新】
    Vue项目上线打包优化
    BeeV1.11 拦截器,多租户、Redis 缓存、注册器、类型转换器和结果处理器(上传 Maven 2022.5)
    STM32之HAL开发——FSMC控制带控制器LCD(8080时序)
    益智类游戏关卡设计:逆推法--巧解益智类游戏关卡设计
    贴近摄影测量,如何让平遥古城焕发生机?
    Win10 如何禁用BitLocker加密cmd命令
    简要介绍django框架
  • 原文地址:https://blog.csdn.net/weixin_44231544/article/details/125388023