【温故知新】C#中 IEnumerable 与IQueryable
微信公众号: 趣编程ACE
关注可了解更多的.NET日常实战开发技巧numeraire,如需源码 后台回复 源码即可;
如果觉得对你有帮助numeraire,欢迎关注
微信公众号: 趣编程ACE
关注可了解更多的.NET日常实战开发技巧numeraire,如需源码 后台回复 源码即可;
如果觉得对你有帮助numeraire,欢迎关注
IEnumerable与 IQueryable对于.Neter来说并不陌生,今天我就着重阐述下两者加载方式的异同numeraire。
前文回顾【温故知新】C# Linq中 Select && SelectMany 使用技巧 IEnumerable<T>
1.接口位于命名空间 System.Collections 中numeraire,是可以使用foreach进行枚举集合的基接口
2.里面有一个 GetEnumeartor 方法用来迭代集合numeraire,不是线程安全的 调用 MoveNext 来顺序读取下一个集合中对象
3.不支持在集合上添加、删除对象
4.支持延迟执行numeraire,主要是yield 关键字
5.不支持延迟加载numeraire,不适用于分页场景
6.读取数据库或者服务数据时numeraire,IEnumerable将所有数据查询出放置内存中,然后再进行相应筛选操作
7.对于内存中的数据numeraire,我们使用IEnumerable来操作
好了numeraire,那我们通过代码来演示下IEnumerable为啥不在服务端进行过滤筛选操作?
2.安装SqlLite的EFCore依赖包
1Install-PackageMicrosoft.EntityFrameworkCore.Sqlite
3.创建实体
1publicclassBloggingContext: DbContext
2{
3publicDbSet<Blog> Blogs { get; set; }
4publicDbSet<Post> Posts { get; set; }
展开全文
5
6publicstringDbPath { get; }
7
8publicBloggingContext( )
9{
10varfolder = Environment.SpecialFolder.LocalApplicationData;
11varpath = Environment.GetFolderPath(folder);
12DbPath = 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.
17protectedoverridevoidOnConfiguring( DbContextOptionsBuilder options)
18=> options.UseSqlite( $"Data Source= {DbPath}" );
19}
20
21publicclassBlog
22{
23publicintBlogId { get; set; }
24publicstringUrl { get; set; }
25
26publicList<Post> Posts { get; } = new;
27}
28
29publicclassPost
30{
31publicintPostId { get; set; }
32publicstringTitle { get; set; }
33publicstringContent { get; set; }
34
35publicintBlogId { get; set; }
36publicBlog Blog { get; set; }
37}
4.创建数据库
1Install- PackageMicrosoft.EntityFrameworkCore.Tools
2Add- MigrationInitialCreate
3Update- Database
5.对数据库进行插入和读取操作
1usingSystem;
2usingSystem.Linq;
3
4usingvardb = newBloggingContext;
5
6Console.WriteLine( $"数据库路径: {db.DbPath}." );
7
8// Create
9Console.WriteLine( "Inserting a new blog");
10db.Add( newBlog { Url = ""});
11db.SaveChanges;
12
13// Read
14Console.WriteLine( "Querying for a blog");
15IEnumerable<Blog> blog = db.Blogs;
16
17vardata = blog.
18Where(b => b.Url == ");
19
20foreach( varitem indata)
21{
22Console.WriteLine(item);
23}
6.为项目集成日志
一、建立一个 ConsoleLogger日志类并继承 ILogger接口
publicIDisposable BeginScope<TState>(TState state)
2{
3returnnull;
4}
5
6publicboolIsEnabled( LogLevel logLevel)
7{
8switch(logLevel)
9{
10caseLogLevel.Trace:
11caseLogLevel.Information:
12caseLogLevel.None:
13returnfalse;
14caseLogLevel.Debug:
15caseLogLevel.Warning:
16caseLogLevel.Error:
17caseLogLevel.Critical:
18default:
19returntrue;
20}
21}
22
23publicvoidLog<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
24{
25Console.WriteLine($"Level: {logLevel},EventId: {eventId.Id},EventName: {eventId.Name}" );
26if(state !=null)
27{
28Console.WriteLine($"State: {state}" );
29}
30
31if(exception!=null)
32{
33Console.WriteLine($"Exception: {exception.Message}" );
34}
35}
二、创建一个 ConsoleLoggerProvider类并继承 ILoggerProvider接口
1publicclassConsoleLoggerProvider: ILoggerProvider
2{
3publicILogger CreateLogger( stringcategoryName)
4{
5returnnewConsoleLogger;
6}
7
8publicvoidDispose
9{
10
11}
12}
三、控制台引入日志服务
1varloggerFactory=db.GetService<ILoggerFactory>;
2loggerFactory.AddProvider( newConsoleLoggerProvider);
通过上图箭头指向的控制台输出的sql语句,可以显然的看见IEnumerable在查询数据库是只进行了 select * from 操作,并没有在数据库里面进行我们相应的过滤操作,而是将所有的数据一窝蜂查出来然后灌入内存中,最后在内存中进行过滤操作numeraire。
那么numeraire我们将db.Blogs 改为IQueryable类型呢
1IQueryable < Blog> blog = db.Blogs;
很明显可以看出,IQueryable将语句转为了我们需要的sql,因为IQueryable接受一个表达式树,表达式树将我们语句拼接,最后转化为查询sql,就实现了在数据库层次的过滤筛选numeraire。
IQueryable
1.IQueryable 位于 System.Linq 命名空间
2.IQueryable 支持延迟执行
3.IQueryable 支持延迟加载,因此适用于类分页的场景numeraire。
4.本身也是扩展自IEnumerable
评论