CRL快速开发框架升级到4.52,谈谈开发过程中的优化
CRL4.5版本已经稳定使用于目前的几个中型项目中,在实际使用中,也发现了不少问题,这些问题都在4.52中提交
CRL具体功能和使用请浏览 CRL快速开发框架系列教程
由于现在项目是一套业务系统,查询需求比较多,CRL带的语法解析都能满足,特殊的可手写SQL,在针对查询的优化,以下几点
对查询调用的监视
由于业务封装写得非常复杂,方法嵌套很严重,无法检查一个方法内有多少查询,需不需要优化,因此使用CallContext进行了监视,并生成报表
public ActionResult RunTime() { var str = CRL.Runtime.RunTimeService.Display(); return Content(str); }
最终如下图:
路径:表示调用方法的路径
DBCall:表示实例化的数据管理类
ALLCall:表示所有数据访问调用
表达式解析内存占用
在一次更新中,为了使解析速度更快,将表达式进行了缓存,只有参数进行了重解析,看上去是省了不少,如下所示
CRLExpression.CRLExpression BinaryExpressionHandler(Expression left, Expression right, ExpressionType expType) var key = string.Format("{0}{1}{2}{3}", __PrefixsAllKey, left, expType, right); var a = BinaryExpressionCache.TryGetValue(key, out cacheItem); if (a) { 返回缓存 }
但是Expression left.ToString()效率并不高,并且占内存,所以这个并没有什么卵用
字符串变量内存占用
因为CRL查询所有参数都需要进行参数化,因此需要对应的参数名,如以下表达式:b=>b.Id==1
参数名为:@p1,若再有参数,依次类推,然而@p1由 string.Format("{0}p{1}","@",1)生成,在对性能测试时发现,这个Format占用了很多内存
于是解决办法,还是缓存参数名,提前生成,重复使用
if (parameDic == null) { parameDic = new Dictionary<int, string>(); for (int i = 0; i <= 5000; i++) { parameDic.Add(i, __DBAdapter.GetParamName("p", i)); } } var _par = parameDic[parIndex]; AddParame(_par, par);
字段格式化内存占用
CRL查询默认是查询所有字段,所以查询为 select t1.Id,t1.Name,t1.Code.....,在没有手动选择查询字段时,这些select其实一直是一样的,通过性能监视发现,好多内存被这重复解析占用了
优化后,当是查询所有字段,从缓存里生成
if (GetPrefix(__MainType) == "t1.") { key = __MainType.ToString(); SelectFieldInfo value; var a = queryFieldCache.TryGetValue(key, out value); if (a) { if (!cacheAllFieldString) { var item = value.Clone(); item.CleanQueryFieldString(); _CurrentSelectFieldCache = item; } else { _CurrentSelectFieldCache = value; } return; } cache = true; }
因为CRL对查询作了关键字处理,包括表名,字段名,所以最终的语句为
以MSSQL为例:select t1.[Name] from [table1] t1
方法为
public override string KeyWordFormat(string value) { return string.Format("[{0}]", value); }
实际上,每个字段只用生成一次就行了,再次使用时从缓存中取,节省了不少内占用
public string FieldNameFormat(Attribute.FieldAttribute field) { if (string.IsNullOrEmpty(field.MapingNameFormat)) { field.MapingNameFormat = KeyWordFormat(field.MapingName); } return field.MapingNameFormat; }
手写语句提取参数
直接将参数拼在SQL里好像不怎么雅观,并且,容易造成语法错误和注入漏洞,如下:
string sql = "select top 10 Id,ProductId,ProductName1 from ProductData a where a.addtime>='2017-09-01' and a.id=234"; var helper = DBExtend; var list = helper.ExecDynamicList(sql);
CRL新增了方法,能重新处理手写的SQL为参数化
int parIndex = 1; /// <summary> /// 提取SQL参数 /// </summary> /// <param name="db"></param> /// <param name="sql"></param> /// <param name="manual"></param> /// <returns></returns> public virtual string ReplaceParameter(CoreHelper.DBHelper db,string sql,bool manual = false) { if (!SettingConfig.ReplaceSqlParameter && !manual) { return sql; } //return sql; var re = @"((\s|,)*)(\w+)\s*(>|<|=|!=|>=|<=)\s*('(.*?)'|([1-9]\d*.\d*|0.\d*[1-9]\d*))(\s|,|\))"; sql = sql + " "; if (!Regex.IsMatch(sql, re, RegexOptions.IgnoreCase)) { return sql; } Regex r = new Regex(re, RegexOptions.IgnoreCase); List<string> pars = new List<string>(); //int index = 1; for (var m = r.Match(sql); m.Success; m = m.NextMatch()) { var name = m.Groups[3]; var op = m.Groups[4]; var value1 = m.Groups[6]; var value2 = m.Groups[7]; var value = string.IsNullOrEmpty(value2.Value) ? value1 : value2; var p = m.Groups[1]; var p2 = m.Groups[8]; var pName = GetParamName("_p", parIndex); db.AddParam(pName, value.ToString()); sql = sql.Replace(m.ToString(), string.Format("{0}{1}{4}{2}{3} ", p, name, pName, p2, op)); parIndex += 1; } return sql; }
在配置为自动替换SQL拼接参数(CRL.SettingConfig.ReplaceSqlParameter=true),实际输出将为:
select top 10 Id,ProductId,ProductName1 from ProductData a where a.addtime>=@p1 and a.id=@p2
异步插入MSMQ的实现
在某个业务中,一张表很频繁的单个插入,占用大量资源,专门为这写个消息队列好像不怎么高明,下次又有这样的情况怎么办
于是有就了,为每个对象定义自已的消息队列和处理,用第三方的不太好集成,就是微软自家的吧
/// <summary> /// 添加一条记录[基本方法] /// 异步时,会定时执行批量插入,依赖MSMQ服务 /// </summary> /// <param name="p"></param> /// <param name="asyn">异步插入</param> public virtual void Add(TModel p, bool asyn = false)
调用参数为true时,则为TModel类型创建消息队列,并异步分批次插入到数据库中,比如在10秒内连续调用了100次此方法
只是将数据存入了消息队列,在队列下个处理周期,将这100条批量插入到数据库,效率倍增
DbSet方式的实现
在Entity Framework里,有DbSet的概念,配置好数据关系后,关联对象直接就能取到了
在CRL里,简单实现一下
public class Order : CRL.IModelBase
{
public CRL.Set.DbSet<ProductData> Products//返回关联的Product { get { return GetDbSet<ProductData>(b => b.Id, ProductId); } } public CRL.Set.EntityRelation<Member> Member//返回关联的Member { get { return GetEntityRelation<Member>(b => b.Id, UserId); } }
}
调用如下:
var order = new Code.Order(); //所有 var product = order.Products.ToList(); //返回关联过的查询,使用完整查询满足更多需求 var product2 = order.Products.GetQuery(); var p = new Code.ProductData() { BarCode = "33333" }; //添加一项 order.Products.Add(p); order.Products.Delete(p);//删除一项 //返回完整的BaseProvider var provider = order.Products.GetProvider(); //返回关联的member,在调用时返回,在循环内调用会多次调用数据库 var member = order.Member.Value;
十年磨一剑,在代码写得越来越深入,再回头看自已的代码,残破不堪.
欢迎下载源码交流讨论
获取CRL最新源码见文章底部下载
CRL快速开发框架升级到4.52,谈谈开发过程中的优化的更多相关文章
- 非关系型数据库来了,CRL快速开发框架升级到版本4
轮子?,我很任性,我要造不一样的轮子,同时支持关系型和非关系型的框架有没有 新版数据查询作了些调整,抽象了LabmdaQueryy和DBExtend,升级到版本4,非关系数据库MongoDB被支持了! ...
- CRL快速开发框架升级到3.1
CRL是一款面向对象的轻量级ORM框架,本着快速开发,使用简便的原则,设计为 无需关心数据库结构,CRL自动维护创建,即写即用(CRL内部有表结构检查机制,保证表结构一致性) 无需第三方工具生成代理类 ...
- CRL快速开发框架开源完全转到Github
CRL简介 CRL是一款面向对象的轻量级ORM框架,本着快速开发,使用简便的原则,设计为 无需关心数据库结构,CRL自动维护创建,即写即用(CRL内部有表结构检查机制,保证表结构一致性) 无需第三方工 ...
- CRL快速开发框架系列教程十三(嵌套查询)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- CRL快速开发框架系列教程十二(MongoDB支持)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- CRL快速开发框架系列教程十一(大数据分库分表解决方案)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- CRL快速开发框架系列教程十(导出对象结构)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- CRL快速开发框架系列教程九(导入/导出数据)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- CRL快速开发框架系列教程七(使用事务)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
随机推荐
- Django总结
Django 中提供了开发网站经常用到的模块,常见的代码都为你写好了,通过减少重复的代码,Django 使你能够专注于 web 应用上有 趣的关键性的东西.为了达到这个目标,Django 提供了通用W ...
- 解决弹出蒙层滑动穿透问题-vue
最近开发过程中遇到一些小问题(似乎问题总是那么多),但一直没什么时间去优化与解决.程序员不能被业务绑架,有时间还是花点在代码上
- linux服务器使用yum安装nginx
一,安装nginx和php-fpm yum install nginx php-fpm 二, 找到nginx.conf find / -name nginx.conf 三,添加解析php配置 在ser ...
- 2746:约瑟夫问题poj
2746:约瑟夫问题 总时间限制: 1000ms 内存限制: 65536kB 描述 约瑟夫问题:有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退 ...
- 免费人脸识别APi
今天对应一些免费的人脸识别的api 做了一下简单的对比,觉得百度开发出来的人脸识别接口还是最符合的我的要求,简单易用,容易上手. 据说百度的一些门禁也使用上了人脸识别的功能了,功能很强大,而且能识别出 ...
- TCP/IP 协议 ----- 协议栈
文章是作者对tcp/ip协议族的一些看法,借鉴TCP/IP详解卷一的内容,进行总结归纳,并阐述自己的一些看法. TCP/IP协议栈· : 整个协议栈被分为了四层,每一层协议负责不同的功能: 链路层:负 ...
- MYSQL瓶颈
一般来说, 在使用的时候 性能从某个数值开始.突然大大下降,说明就到了瓶颈期. mysql 瓶颈有2种,一种是 cpu瓶颈 一种是 io瓶颈.cpu瓶颈多是由io引起. 而io可以通过 show ...
- tensorflow 安装升级
对于已经安装过的tensorflow,执行以下命令升级到最新版: pip3 install -U tensorflow 目前最新版本1.4
- webrc视频数据发送处理流程详解
- LDA主题模型学习笔记5:C源代码理解
1.说明 本文对LDA原始论文的作者所提供的C代码中LDA的主要逻辑部分做凝视,原代码可在这里下载到:https://github.com/Blei-Lab/lda-c 这份代码实现论文<Lat ...