【温故知新】C#中 IEnumerable 与IQueryable

微信公众号:趣编程ACE
关注可了解更多的.NET日常实战开发技巧,如需源码 后台回复 源码 即可;
如果觉得对你有帮助,欢迎关注

老生常谈 C#中 IEnumerable 与IQueryable

IEnumerableIQueryable 对于.Neter来说并不陌生,今天我就着重阐述下两者加载方式的异同。


前文回顾

【温故知新】C# Linq中 Select && SelectMany 使用技巧

IEnumerable<T>

a35790335fa278aa150fe9574885d5b4.jpeg

  • 1.接口位于命名空间System.Collections中,是可以使用foreach进行枚举集合的基接口

  • 2.里面有一个GetEnumeartor()方法用来迭代集合,不是线程安全的 调用MoveNext()来顺序读取下一个集合中对象

  • 3.不支持在集合上添加、删除对象

  • 4.支持延迟执行,主要是yield 关键字

  • 5.不支持延迟加载,不适用于分页场景

  • 6.读取数据库或者服务数据时,IEnumerable将所有数据查询出放置内存中,然后再进行相应筛选操作

  • 7.对于内存中的数据,我们使用IEnumerable来操作

好了,那我们通过代码来演示下IEnumerable为啥不在服务端进行过滤筛选操作?

  1. 新建一个基于.net6的控制台程序

  2. 379e0421001db448e63960ea37ad3eef.png

2.安装SqlLite的EFCore依赖包

1Install-Package Microsoft.EntityFrameworkCore.Sqlite

3.创建实体

1public class BloggingContext : DbContext2{3    public DbSet<Blog> Blogs { get; set; }4    public DbSet<Post> Posts { get; set; }56    public string DbPath { get; }78    public BloggingContext()9    {
10        var folder = Environment.SpecialFolder.LocalApplicationData;
11        var path = Environment.GetFolderPath(folder);
12        DbPath = System.IO.Path.Join(path, "blogging.db");
13    }
14
15    // The following configures EF to create a Sqlite database file in the
16    // special "local" folder for your platform.
17    protected override void OnConfiguring(DbContextOptionsBuilder options)
18        => options.UseSqlite($"Data Source={DbPath}");
19}
20
21public class Blog
22{
23    public int BlogId { get; set; }
24    public string Url { get; set; }
25
26    public List<Post> Posts { get; } = new();
27}
28
29public class Post
30{
31    public int PostId { get; set; }
32    public string Title { get; set; }
33    public string Content { get; set; }
34
35    public int BlogId { get; set; }
36    public Blog Blog { get; set; }
37}

4.创建数据库

1Install-Package Microsoft.EntityFrameworkCore.Tools
2Add-Migration InitialCreate
3Update-Database

5.对数据库进行插入和读取操作

1using System;2using System.Linq;34using var db = new BloggingContext();56Console.WriteLine($"数据库路径: {db.DbPath}.");78// Create9Console.WriteLine("Inserting a new blog");
10db.Add(new Blog { Url = "http://blogs.msdn.com/adonet" });
11db.SaveChanges();
12
13// Read
14Console.WriteLine("Querying for a blog");
15IEnumerable<Blog> blog = db.Blogs;
16
17var data = blog.
18    Where(b => b.Url == "http://blogs.msdn.com/adonet").Take(2);
19
20foreach (var item in data)
21{
22    Console.WriteLine(item);
23}

6.为项目集成日志
一、建立一个ConsoleLogger日志类并继承ILogger接口

public IDisposable BeginScope<TState>(TState state)2{3            return null;4}56public bool IsEnabled(LogLevel logLevel)7{8   switch (logLevel)9   {
10    case LogLevel.Trace:
11    case LogLevel.Information:
12    case LogLevel.None:
13        return false;
14    case LogLevel.Debug:
15    case LogLevel.Warning:
16    case LogLevel.Error:
17    case LogLevel.Critical:
18    default:
19        return true;
20   }
21}
22
23public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
24{
25        Console.WriteLine($"Level:{logLevel},EventId:{eventId.Id},EventName:{eventId.Name}");
26        if(state !=null)
27        {
28            Console.WriteLine($"State:{state}");
29        }
30
31        if(exception!=null)
32        {
33            Console.WriteLine($"Exception:{exception.Message}");
34        }
35}

二、创建一个ConsoleLoggerProvider类并继承ILoggerProvider接口

1public class ConsoleLoggerProvider : ILoggerProvider2{3   public ILogger CreateLogger(string categoryName)4   {5      return new ConsoleLogger();6   }78   public void Dispose()9   {
10
11   }
12}

三、控制台引入日志服务

1var loggerFactory=db.GetService<ILoggerFactory>();
2loggerFactory.AddProvider(new ConsoleLoggerProvider());

48ba08b435dfd6a4a21e6b7560834f9b.jpeg

通过上图箭头指向的控制台输出的sql语句,可以显然的看见IEnumerable在查询数据库是只进行了 select * from 操作,并没有在数据库里面进行我们相应的过滤操作,而是将所有的数据一窝蜂查出来然后灌入内存中,最后在内存中进行过滤操作。
那么我们将db.Blogs 改为IQueryable类型呢

1IQueryable<Blog> blog = db.Blogs;

963145362646d411acd8abbbe43c5792.jpeg

很明显可以看出,IQueryable将语句转为了我们需要的sql,因为IQueryable接受一个表达式树,表达式树将我们语句拼接,最后转化为查询sql,就实现了在数据库层次的过滤筛选。

IQueryable

a6691a21bee5b2470d7c42990bbb5b21.jpeg

  • 1.IQueryable 位于System.Linq命名空间

  • 2.IQueryable 支持延迟执行

  • 3.IQueryable 支持延迟加载,因此适用于类分页的场景。

  • 4.本身也是扩展自IEnumerable

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283495.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5个知识点,让 Vue3 开发更加丝滑

一、setup name 增强 Vue3的setup语法糖是个好东西&#xff0c;但使用setup语法带来的第一个问题就是无法自定义name&#xff0c;而我们使用keep-alive往往是需要name的&#xff0c;解决这个问题通常是通过写两个script标签来解决&#xff0c;一个使用setup&#xff0c;一个不使…

石子归并 51Nod - 1021

N堆石子摆成一条线。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆&#xff0c;并将新的一堆石子数记为该次合并的代价。计算将N堆石子合并成一堆的最小代价。 例如&#xff1a; 1 2 3 4&#xff0c;有不少合并方法1 2 3 4 > 3 3 4(3) > 6 4…

Scala基础 - _root_ package的作用

2019独角兽企业重金招聘Python工程师标准>>> 在Scala中引入类时支持相对路径&#xff0c;例如&#xff1a; import play.api.libs.json._ import play.api.libs.json.util.LazyHelper可以简写成&#xff1a; import play.api.libs.json._ import util.LazyHelper通常…

使用.NET简单实现一个Redis的高性能克隆版(六)

译者注该原文是Ayende Rahien大佬业余自己在使用C# 和 .NET构建一个简单、高性能兼容Redis协议的数据库的经历。首先这个"Redis"是非常简单的实现&#xff0c;但是他在优化这个简单"Redis"路程很有趣&#xff0c;也能给我们在从事性能优化工作时带来一些启…

Netty 4.x – ByteBuf

2019独角兽企业重金招聘Python工程师标准>>> 1、ByteBuf与Java NIO Buffer ByteBuf则是Java NIO Buffer的新轮子&#xff0c;官方列出了一些ByteBuf的特性&#xff1a; 需要的话&#xff0c;可以自定义buffer类型&#xff1b;通过组合buffer类型&#xff0c;可实现透…

Vue3关于响应式数据类型(ref、reactive、toRef、以及toRefs)

ref 接受一个内部值&#xff0c;返回一个响应式的、可更改的 ref 对象&#xff0c;此对象只有一个指向其内部值的 property .value。类型function ref<T>(value: T): Ref<UnwrapRef<T>>interface Ref<T> {value: T }详细信息ref 对象是可更改的&#x…

智能路由器-OpenWRT 系列四 (挂载移动设备)

每次ssh登陆OpenWRT安装新软件时&#xff0c;都必须更新opkg opkg update安装驱动 为了可以识别U盘/移动硬盘&#xff0c;必须安装相关的驱动。 一类是usb相关的驱动 opkg install kmod-usb-core #usb驱动 opkg install kmod-scsi-core #SCSI总线驱动 opkg install kmod-scs…

jstl 处理Date 时间

1、引入 <% taglib prefix"fmt" uri"http://java.sun.com/jsp/jstl/fmt" %> <fmt:formatDate value"${Date}" pattern"yyyy-MM" /><!-- 这里的value只能是date类型--> pattern 随意发挥了&#xff01;转载于:https:…

windows系统vscode检查更新菜单消失且不能自动更新(1.70.0不能自动更新到1.70.2

翻了半天vscode的issues中终于找到了https://github.com/microsoft/vscode/issues/157624 解决方案 不能用管理员身份运行vscode&#xff0c;不然就没有检查更新菜单&#xff0c;关闭后重启vscode就有更新菜单了 相关回答 翻译一下&#xff0c;就是vscode分用户类型和系统类型两…

LinkedHashMap的实现原理

1. LinkedHashMap概述&#xff1a; LinkedHashMap是Map接口的哈希表和链接列表实现&#xff0c;具有可预知的迭代顺序。此实现提供所有可选的映射操作&#xff0c;并允许使用null值和null键。此类不保证映射的顺序&#xff0c;特别是它不保证该顺序恒久不变。 LinkedHashMap…

验证-表单令牌

表单令牌验证规则支持对表单的令牌验证&#xff0c;首先需要在你的表单里面增加下面隐藏域&#xff1a;或者然后在你的验证规则中&#xff0c;添加token验证规则即可&#xff0c;例如&#xff0c;如果使用的是验证器的话&#xff0c;可以改为&#xff1a;如果你的令牌名称不是_…

WPF 用户控件分享之边上带输入框的圆圈

WPF 用户控件分享之边上带输入框的圆圈独立观察员 2022 年 8 月 20 日最近有这样一个需求&#xff0c;有一圈圆形&#xff0c;每个圆形边上有个输入框&#xff0c;以下是完成后的效果图&#xff1a;拿到这个需求后&#xff0c;分析界面上每个圆形和输入框应该视为一个用户控件&…

总统与乞丐

一位总统带着孙子散步&#xff0c;有个乞丐向他鞠躬敬礼&#xff0c;总统马上驻足还礼&#xff0c;而且弯腰更深。孙子不解:“他只是个乞丐啊&#xff01;” 总统回答&#xff1a;“我绝不允许一个乞丐比总统更有礼貌&#xff01;不要以为别人尊敬你&#xff0c;是因为你很优秀…

VUE3 v-show 引起的表单验证问题

<el-form ref"formRef" :rules"rules" :model"form" label-width"80px"><el-form-item label"任务类型" prop"TaskType"><el-radio-group v-model"form.TaskType" change"handleCh…

ThreadPoolExecutor

简述&#xff1a; 有的时候&#xff0c;系统处理很多任务&#xff0c;如何这些任务要是都是通过new Thread来做的话&#xff0c;系统就不得不常常的创建之后还要销毁Thread&#xff0c;这个是非常消耗时间而且还占用资源&#xff0c;所以我们通过创建线程池来管理我们的线程。 …

你总说时间很少

你总说时间很少 没时间看哭泣的骆驼 少了心情 你总说时间很少 没时间撩拨那爱的罗曼史 少了喜欢 你总说时间很少 没时间吮吸印度洋的水清沙白 少了勇敢 你总说时间很少 没时间寻找相伴的野马 少了感觉 可到最后 时间真的很少 有了喜欢 就少了心情 有了感觉 就少了勇敢…

Unity 将是驱动 C# 增长的引擎吗 ?

C# 在中国的采用需要一个杀手级应用的带动&#xff0c; 那么这样的一个杀手级应用是 Unity吗&#xff0c;我这里大胆推测采用CoreCLR 的新一代完全采用C#构建的Unity 将是这样的一个杀手级应用。Unity已被广泛应用于数字孪生、数字城市、数字工厂等场景&#xff0c;成为各产业加…

HTML5video 标签

属性 值 说明 autoplay autoplay 如果出现该属性&#xff0c;则视频在就绪后马上播放。 controls controls 如果出现该属性&#xff0c;则向用户显示控件&#xff0c;比如播放按钮。 preload preload 如果出现该属性&#xff0c;则视频…

Windows 超级开源实用工具:Microsoft PowerToys

实用工具集&#xff1a; Always on Top ​通过 Always on Top&#xff0c;可使用快捷键方式 (⊞ WinCtrlT) 将窗口固定在其他窗口的顶部。 ​ PowerToys Awake PowerToys Awake旨在使计算机保持唤醒状态&#xff0c;且无需管理其电源和睡眠设置。 运行耗时较长的任务时&#…

Python入门之数据类型

字符串 列表 元组 字典 转载于:https://www.cnblogs.com/py17/p/8919495.html