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

Connor 币安app官网下载 2022-09-26 119 0

微信公众号: 趣编程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

评论