当前位置: 首页 > news >正文

汉中做网站公司温州百度推广公司

汉中做网站公司,温州百度推广公司,关键词收录查询工具,手机报价网站大全前言.net 环境近些年也算是稳步发展。在开发的过程中#xff0c;与数据库打交道是必不可少的。早期的开发者都是DbHelper一撸到底#xff0c;到现在的各种各样的ORM框架大行其道。孰优孰劣谁也说不清楚#xff0c;文无第一武无第二说的就是这个理。没有什么最好的#xff0… 前言.net 环境近些年也算是稳步发展。在开发的过程中与数据库打交道是必不可少的。早期的开发者都是DbHelper一撸到底到现在的各种各样的ORM框架大行其道。孰优孰劣谁也说不清楚文无第一武无第二说的就是这个理。没有什么最好的只有最适合你的。本人也是从DbHelper开始期间用过SugarSql再到EFCODE。本着学习分享的初衷分享本人工作中总结的一些小技巧希望能帮助更多开发者期望能达到共同进步。文中若有错误地方欢迎大家不吝赐教。1. DbContext配置在asp.net中通常情况下通过在Startup类的ConfigureServices方法中将ef服务注入。示例代码如下services.AddDbContextDemoDbContext(optopt.UseMySql(server.;Databasedemo;Uidroot;Pwd123;Port3306;));以上代码表示使用MySql数据库。如果使用SqlServer数据库可以把UseMySql改为UseSqlServer其他数据库的使用方式也是通过调用不同的方法进行选择。但需要安装对应的扩展方法的程序包如 Microsoft.EntityFrameworkCore.SqlServer 或 Microsoft.EntityFrameworkCore.Sqlite。另外UseMySql方法还包含了一个可空的Action 类型的参数可以通过此参数进行一些个性化的配置比如配置重试机制。如下所示services.AddDbContextDemoDbContext(opt opt.UseMySql(server.;Databasedemo;Uidroot;Pwd123456;Port3306;, provideropt provideropt.EnableRetryOnFailure(3,TimeSpan.FromSeconds(10),new List(){0} )));这个重试机制在某些场景下还是比较有用的。比如由于网络波动或访问量导致的一瞬间的连接超时。如果不设置重试机制则会直接触发异常设置了超时后则会根据设置的时间间隔以及重试次数进行重试。EnableRetryOnFailure方法的最后一个参数是用来设置错误代码的只有设置了错误代码的错误才会触发重试。获取错误代码的方法有很多种个人比较推荐的是通过异常信息进行获取比如使用MySql数据时触发的异常类型是MySqlException此类的Number属性的值EnableRetryOnFailure方法所需要的Number2. DbContext线程问题efcore不支持在同一个DbContext实例上运行多个并行操作,这包括异步查询的并行执行以及从多个线程进行的任何显式并发使用。因此始终 await 异步调用或对并行执行的操作使用单独的 DbContext 实例。当 EF Core 检测到并行操作或多个线程同时尝试使用 DbContext 实例时你将看到一条 InvalidOperationException其中包含类似于下面的消息A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.意思是在上一个操作没有执行完毕之前又启动了一个新的操作所以不能保证线程是安全的。下面是一段错误的可以触发这个异常的示例代码所以请始终await异步调用。如果在多个多个线程中使用DbContext需保证每个线程的DbContext的实例是唯一的。3. 数据库使用连接池使用 services.AddDbContextPool比使用 services.AddDbContext吞吐量提升在10~20的百分点(非官方说法对性能提高数据是本人测试后得到的结果)。需要注意的是连接池大小并不是越大越好。4. 日志记录在使用ef时基本上绝大多数和数据库的交互都是通过linq实现的然后ef将linq翻译成对应的sql语句在排查问题的时候在开发或者排查问题时往往需要关注最终执行的sql脚本所以就需要通过日志的方式查看。在efcore2.x的版本默认是注入日志服务所以不需要额外的操作就可以查看对应的sql脚本。但efcore3.x的版本默认移除了日志服务具体原因参照https://docs.microsoft.com/zh-cn/ef/core/what-is-new/ef-core-3.0/breaking-changes#adddbc。可通过自定义DbContext的方式注入日志任务,示例代码如下public static readonly ILoggerFactory MyLoggerFactory LoggerFactory.Create(builder { builder.AddConsole(); });protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){ base.OnConfiguring(optionsBuilder); optionsBuilder.UseLoggerFactory(MyLoggerFactory);}当执行ef代码时可在控制台中查看相关的sql脚本如下图所示5. 增插入数据到数据库常用的场景有普通单表单行插入多表级联插入批量插入。普通单表单行插入比较简单实例代码如下var student new Student {CreateTime DateTime.Now, Name zjjjjjj};await _context.Students.AddAsync(student);await _context.SaveChangesAsync();多表级联插入需要在实体映射中配置属性导航。比如Blog表和Post是的关系是1对多的关系。则在Blog的实体中定义一个类型为List 的属性。示例代码如下[Table(blog)]public class Blog { [Column(id)] public long Id { get; set; } [Column(title)] public string Title { get; set; } public ListPost Posts { get; set; } [Column(create_date)] public DateTime CreateDate { get; set; }}对应的插入语句如下所示var blog new Blog{ Title 测试标题, Posts new ListPost { new Post{Content 评论1}, new Post{Content 评论2}, new Post{Content 评论3}, }};await _context.Blog.AddAsync(blog);await _context.SaveChangesAsync();执行此代码会生成如下的日志从日志中可以看出通过这种方式实现了级联插入的效果。批量插入实现方式有两种一种是EF默认实现适用于数据源较少的情况。另一种我们基于EF开发一个大数据量批量插入的服务适合于数据源大于1000的场景。在万级及以上的数据量上较EF默认的批量插入性能上有非常明显的提升。具体参考https://www.cnblogs.com/fulu/p/13370335.htmlEF默认实现var list new ListStudent();for (int i 0; i num; i){ list.Add(new Student { CreateTime DateTime.Now, Name zjjjjjj });}await _context.Students.AddRangeAsync(list);await _context.SaveChangesAsync();ISqlBulk实现var list new ListStudent();for (int i 0; i 100000; i){ list.Add(new Student { CreateTime DateTime.Now, Name zjjjjjj });}await _bulk.InsertAsync(list);自增 OR GUIDint自增的优点1、需要很小的数据存储空间仅仅需要4 byte 。2、insert和update操作时使用INT的性能比GUID好所以使用int将会提高应用程序的性能。3、index和Join 操作int的性能最好。4、容易记忆。int自增的缺点1、使用INT数据范围有限制。如果存在大量的数据可能会超出INT的取值范围。2、很难处理分布式存储的数据表。GUID做主键的优点1、唯一性。2、适合大量数据中的插入和更新操作。3、跨服务器数据合并非常方便。GUID做主键的缺点1、存储空间大(16 byte)因此它将会占用更多的磁盘大小。2、很难记忆。join操作性能比int要低。3、没有内置的函数获取最新产生的guid主键。4、EF默认生成的GUID是无序的会影响数据插入性能。结论在数据量比较少的场景下建议使用int自增比如分类。对于大数据量建议使用有序GUID。因为默认.net生成GUID是无序的而数据库中主键默认是聚集索引而聚集索引在物理上的存储是有序的当插入数据时如果插入的是无序的GUID,可能就会涉及到移动数据的情况进而影响插入的性能特别是百万级数据量的时候性能影响则较为明显。参考资料https://www.cnblogs.com/CameronWu/p/guids-as-fast-primary-keys-under-multiple-database.html其他可选方案经过个人多番了解目前市面上常用的分布式id生成算法和Twitter发布的雪花算法大同小异个人也在项目中使用过雪花算法有兴趣的朋友可以在博客园找下相关的内容。不过目前用.net封装的雪花算法普遍较基础很难在docker或者k8s环境下简单的使用所以在此预告下本人根据雪花算法编写的可用于k8s环境的即将开源敬请期待。6. 查EF使用Linq查询数据库中的数据使用Linq可编写强类型的查询。当命令执行时EF先将Linq表达式转换成sql脚本然后再提交给数据库执行。可在日志中查看生成的sql脚本。根据条件查询await _context.Blog.Where(xx.Id0).ToListAsync();上述代码执行时生成的sql脚本如下所示SELECT x.id, x.create_date, x.title FROM blog AS x WHERE x.id 0获取单个实体可实现获取单个实体的方式有FirstFirstOrDefaultSingleSingleOrDefault其中FirstFirstOrDefault执行时生成的sql脚本如下 SELECT x.id, x.create_date, x.title FROM blog AS x WHERE x.id 10 LIMIT 1SingleSingleOrDefault执行时生成的sql脚本如下 SELECT x.id, x.create_date, x.title FROM blog AS x WHERE x.id 10 LIMIT 2细心的你应该已经发现了两者的区别Single需要查询2条数据当返回的数据多余一条时SingleSingleOrDefault方法就会报Source sequence contains more than one element.异常。所以Single方法仅适用于查询条件对应的数据只有一条的场景比如查询主键的值。如下所示await _context.Blog.SingleOrDefaultAsync(x x.Id100);后缀带OrDefault和不带后缀的区别是当sql脚本执行查询不到数据时带后缀的会返回空值而不带后缀的则会直接报异常。判断数据库是否存在可通过Any()和Count()方法实现是否存在数据。示例代码如下await _context.Blog.AnyAsync(x x.Id 100);await _context.Blog.CountAsync(x x.Id 100)0;生成的sql脚本对应如下SELECT CASE WHEN EXISTS ( SELECT 1 FROM blog AS x WHERE x.id 100) THEN TRUE ELSE FALSE ENDSELECT COUNT(*) FROM blog AS x WHERE x.id 100乍一看Any方法生成的脚本貌似更复杂些但实际上Any方法的性能在大数据量下比Count方法高了很多。所以在判断是否存在时请使用Any方法。连接查询连接查询是关系数据库中最主要的查询主要包括内连接、外连接(左连接、外连接)和交叉连接等。通过连接运算符可以实现多个表查询。本文主要讲解下常用的内连接和左连接。内连接的示例代码如下var query from post in _context.Post join blog in _context.Blog on post.BlogId equals blog.Id where blog.Id 0 select new {blog, post};左连接的示例代码如下var query from post in _context.Post join blog in _context.Blog on post.BlogId equals blog.Id into pbs from pb in pbs.DefaultIfEmpty() where pb.Id0 post.Content.Contains(1) select new {post,pb.Title};级联查询在很多场景中可能会涉及到查询与父表关联的子表数据在这样的场景中会有一部分人先查出主表数据然后根据主表的主键再去查询子表的数据笔者在使用ef初期也是这种处理方式的。但借助Include的方法可以让我们更方便的解决父子表级联查询的问题。示例代码如下var result await _context.Blog.Include(b b.Posts) .SingleOrDefaultAsync(xx.Id157);如果有更多的层级可以借助ThenInclude进行查询。有的时候还有这样的场景我们不是简单的查询子表的数据而是需要查询满足指定条件的数据那就要求咱们在调用Include的方法时传入参数示例代码如下 var filteredBlogs await _context.Blogs .Include(blog blog.Posts .Where(post post.BlogId 1) .OrderByDescending(post post.Title) .Take(5)) .ToListAsync();注以上方法仅在.net5中支持。所以efcore也是在一个发展的过程中随着时间与版本的更新功能也会渐渐趋于完善。相关内容请参考https://docs.microsoft.com/zh-cn/ef/core/querying/related-data7. 改使用过EF的应该都了解查询的跟踪与非跟踪的概念吧(纳尼你没听说过老衲给您指条明路吧https://docs.microsoft.com/zh-cn/ef/core/querying/tracking)。通常来讲更新的流程大概是这样查询出数据修改某些字段的值调用Update方法然后调用SaveChange方法。看上去毫无破绽但如果你仔细观察过生成的sql脚本的话或许你就应该有更好的方法咱们先来看看示例代码var school await _context.Schools.FirstAsync(x x.Id 0);school.Name 6666;_context.Schools.Update(school);await _context.SaveChangesAsync();如下图所示的是执行以上代码生成的update的sql语句我们发现明明代码中只对Name重新赋了值但生成的脚本却将此记录的所有字段进行了更新显然这不是我们想要的结果。其实如果实体是通过跟踪查询得到的则可直接调用SaveChage方法而不用多余调用Update方法此时EF内部会自动判断哪些字段进行了更新从而只生成值改变了的sql语句。结论当要更新的实体开启了跟踪则更新时无需调用Update方法 直接调用SaveChange方法此时之后更新值发生改变的字段。如果先调用Update则SaveChange则不管实体的字段有没有更新生成的sql脚本依旧会更新所有的字段牺牲了性能。假如你的实体不是通过数据库的跟踪查询获取的则在调用时才需要调用Update方法。福禄ICH.架构出品作者福尔斯2020年8月
http://www.zqtcl.cn/news/76016/

相关文章:

  • 微信企业号seo编辑培训
  • 邯郸网站建设包括哪些网站注册都需要什么
  • 工信部 诚信网站备案有哪些做笔译的网站
  • 网站建设公司中企动力推荐信息部网站建设工作计划
  • 做ppt卖给网站网站制作推荐
  • 网站页面组成单本小说网站
  • 做优惠券网站如何引流广告公司起名字大全
  • 廊坊企业网站建设公司记录网站 自己做
  • 北京专业响应式网站建设简述建设一个网站的具体过程
  • 企业网站用什么做二次开发最快会计培训班一般多少钱
  • 做个网站一年要多少钱广州企业500强名单
  • 做一个网站的步骤一键优化表格
  • 网站的虚拟人怎么做的深圳建伟业公司商城
  • 潍坊建站公司百度推广好不好做
  • 东莞市塘厦网站建设自贡做网站公司
  • 江苏景禾瑜博建设工程有限公司网站网站开发vue版本是什么
  • 网站域名空间合同wordpress 模板 分类
  • 有什么网站可以赚钱色母粒
  • 第三方免费做网站宁波建设网官网
  • 平面设计软件下载官方网站有域名了也备案了怎么做网站
  • 商城网站怎么做的婚纱摄影介绍
  • 小程序怎么制作网站网站推广公司就去柚米
  • 四川建设网站公司如何能快速搜到新做网站链接
  • 湖北什么是网站建设用软件做的网站权限管理
  • 商城网站建设公司排名东莞网站建设推广
  • 如何用天地图做网站潍坊专业联轴器收购价格
  • 在局域网服务器建设网站教程在网站做专题
  • 有了阿里云服务器怎么做网站学网页设计制作
  • 小程序开发网站设计制作百度升级最新版本下载安装
  • 灵感网站怎么做商务网站的架构