即使用ADO.NET,也要轻量级动态生成更新SQL,比Ormlite性能更高
先上测试结果:
//测试1000次针对同一个表同一个字段更新,比Ormlite平均快2.34倍
//生成SQL+ExecuteNonQuery Ormlite 倍数
//6513ms 15158ms 2.327
//6461ms 15303ms 2.369
//6624ms 15424ms 2.329
//6591ms 15468ms 2.347 //测试1000次针对同一个表同一个字段更新,比EF平均快1.68倍
//生成SQL+ExecuteNonQuery EF 倍数
//6622ms 11113ms 1.678
//6577ms 11117ms 1.690
//6756ms 11258ms 1.666
//6603ms 11184ms 1.694
不管出于什么原因,有时候框架人员摒弃了NH或EF,而使用原生数据库访问对象。
为了优美的编程,用上我写的轻量级动态生成更新SQL扩展方法吧
还记得在EF中只更新修改过的字段时,我们这么写:
var e = db.Entry(d);
e.State = EntityState.Unchanged;
d.UploadTime = DateTime.Now;
e.Property("UploadTime").IsModified = true;
db.SaveChanges();
目的是,使生成的更新SQL只更新UploadTime字段,否则会更新所有字段,那么就需要先查询一遍再更新。
既然提到数据仓储,我们更新一个实体在数据层最好只有一个方法,但是一个更新的SQL能满足要求吗?
出于以上目的,我写了这样的轻量级扩展方法:
/// <summary>
///
/// </summary>
public static class SqlStringEx
{
#region 静态私有成员 private static object _obj = new object(); private static Dictionary<int, PropertyInfo[]> propertiesCache = new Dictionary<int, PropertyInfo[]>(); /// <summary>
/// 从缓存中获取属性信息
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
private static PropertyInfo[] GetPropertiesFromCache(Type t)
{
var code = t.GetHashCode();
if (!propertiesCache.ContainsKey(code))
{
lock (_obj)
{
if (!propertiesCache.ContainsKey(code))
{
propertiesCache.Add(code, t.GetProperties());
}
}
}
return propertiesCache[code];
}
#endregion /// <summary>
/// 根据实体模型的赋值情况,动态生成更新SQL。避免要先获取再保存,或者避免按需写多个更新SQL
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <param name="tableName">数据表名称</param>
/// <param name="conditionColumnName">更新时条件列名称,该列名需包含在parameters中</param>
/// <param name="parameters"></param>
/// <returns></returns>
public static string GenerateUpdateSql<T>(this T t, string tableName, string conditionColumnName, out List<SqlParameter> parameters)
where T : new()
{ parameters = new List<SqlParameter>();
StringBuilder res = new StringBuilder();
res.AppendFormat("update {0} set ", tableName);
var props = GetPropertiesFromCache(t.GetType());
string wherePart = null;
foreach (PropertyInfo item in props)
{
var propVal = item.GetValue(t, null);
var hasValue = propVal != null && !propVal.Equals();
if (hasValue)
{
var filedname = item.GetFieldName();
parameters.Add(new SqlParameter { Value = propVal, ParameterName = filedname });
if (filedname.Equals(conditionColumnName.ToLower()))
{
wherePart = string.Format(" where {0}=@{0} ", filedname);
}
else
{
res.AppendFormat(" {0}=@{0} ,", filedname);
}
}
}
res.Remove(res.Length - , );
res.Append(wherePart);
return res.ToString();
}
}
其中的GetFieldName()方法见上一篇
有了这个方法,数据层一个实体就只需要一个更新的方法,也不需要自己去拼接更新的SQL了。
List<SqlParameter> parameters =null;
var saveSql = model.GenerateUpdateSql("TableName", "ID", out parameters);
注意,model的属性的默认值分两种,值类型默认值为0,引用类型和非空值类型的默认值是null,当model属性的值不是默认值的时候会参与值的更新。
saveSql就是我们要更新的SQL,parameters是对应更新的参数。ID参数也可以是别的列,但在model中作为条件的列的值不能为默认值。
有没有很方便,欢迎抛砖。
虽然重复造轮子,但方便性是不是可以弥补一切。
性能要求高的,请慎重考虑,因为内部使用了反射。但是性能总的来说比Ormlite更快,执行1000次更新,本扩展方法耗时6513毫秒,而Ormlite耗时15158毫秒。

EF相比Ormlite更快:

即使用ADO.NET,也要轻量级动态生成更新SQL,比Ormlite性能更高的更多相关文章
- graphicview和widgets没本质区别。它只是更轻量级,更灵活,性能更高的widgets
graphicview和widgets没本质区别.它只是更轻量级,更灵活,性能更高的widgets.核心就是把widgets变成了更轻量级的graphicitem,把QWidget的各种事件转换成了g ...
- 寻找性能更优秀的动态 Getter 和 Setter 方案
反射获取 PropertyInfo 可以对对象的属性值进行读取或者写入,但是这样性能不好.所以,我们需要更快的方案. 方案说明 就是用表达式编译一个 Action<TObj,TValue> ...
- 百度echart如何动态生成图表
百度echart如何动态生成图表 一.总结 一句话总结: clear hideloading setOption 主要是下面三行代码: myChart.clear(); //清空画布myChart.h ...
- Aop动态生成代理类时支持带参数构造函数
一.背景 在某些情况下,我们需要植入AOP代码的类并没有默认构造函数.那么此时动态生成的代理类也需要相同签名的构造函数,并且内部调用原始类的构造函数.自己折腾了1晚上没搞定,现在搞定了发出来供大家一起 ...
- dynamic-css 动态 CSS 库,使得你可以借助 MVVM 模式动态生成和更新 css,从 js 事件和 css 选择器的苦海中脱离出来
dynamic-css 使得你可以借助 MVVM 模式动态生成和更新 css,从而将本插件到来之前,打散.嵌套在 js 中的修改样式的代码剥离出来.比如你要做元素跟随鼠标移动,或者根据滚动条位置的变化 ...
- ABP(现代ASP.NET样板开发框架)系列之20、ABP展现层——动态生成WebApi
点这里进入ABP系列文章总目录 ABP(现代ASP.NET样板开发框架)系列之20.ABP展现层——动态生成WebApi ABP是“ASP.NET Boilerplate Project (ASP.N ...
- 【.NET深呼吸】Zip文件操作(2):动态生成Zip文档
通过前面一篇烂文的介绍,大伙儿知道,ZipArchive类表示一个zip文档实例,除了用上一篇文章中所列的方法来读写zip文件外,还可以直接通过ZipArchive类,动态生成zip文件. 文件流操作 ...
- jquery动态生成的元素添加事件的方法
动态生成的元素如果要添加事件,要写成 $(document).on("click", "#txtName", function() { alert(this.v ...
- 利用Java动态生成 PDF 文档
利用Java动态生成 PDF 文档,则需要开源的API.首先我们先想象需求,在企业应用中,客户会提出一些复杂的需求,比如会针对具体的业务,构建比较典型的具备文档性质的内容,一般会导出PDF进行存档.那 ...
随机推荐
- mysql存储过程详解
mysql存储过程详解 1. 存储过程简介 我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的S ...
- android四大组件之Broadcast
广播的概念 现实中:我们常常使用电台通过发送广播发布消息,买个收音机,就能收听 Android:系统在产生某个事件时发送广播,应用程序使用广播接收者接收这个广播,就知道系统产生了什么事件.Androi ...
- Servlet的生命周期+实现方式
1.Servlet的生命周期: (1)被创建: 默认情况下,Servlet第一次被访问时,被服务器创建.会调用init()方法. 一个 ...
- iOS--UIAlertView与UIAlertController和UIAlertAction之间的事儿
iOS 8的新特性之一就是让接口更有适应性.更灵活,因此许多视图控制器的实现方式发生了巨大的变化.全新的UIPresentationController在实现视图控制器间的过渡动画效果和自适应设备 ...
- XML语言基础2 DTD
XML DTD 文档类型定义(DTD)可定义合法的XML文档构建模块.它使用一系列合法的元素来定义文档结构. DTD可被声明于XML文档中,也可以作为一个外部的引用. 内部的DOCTYPE声明 假如D ...
- Oracle表的几种连接方式
1,排序 - - 合并连接(Sort Merge Join, SMJ) 2,嵌套循环(Nested Loops, NL) 3,哈希连接(Hash Join, HJ) Join是一种试图将两个表结合在一 ...
- java中遍历map的两种方式
1.先将map对象转成set,然后再转为迭代器 Iterator iterator = map.entrySet().iterator(); while(iterator.hasNext()){ En ...
- 从零自学Hadoop(04):Linux准备下
阅读目录 序 搭建环境 系列索引 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 序 我们已经准 ...
- 通过JazzyViewPager来实现Fragment页面间的动画切效果
JazzyViewPager 开源项目地址: https://github.com/jfeinstein10/JazzyViewPager 其实实现它还是蛮简单的,有两个关键点,一是使用扩展Fragm ...
- Tomcat关闭日志catalina.out
catalina.out文件会越来越大,对系统的稳定造成了一定的影响.conf/logging.properties 一般在部署Tomcat后,运行久了,catalina.out文件会越来越大,对系统 ...