先上测试结果:

        //测试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性能更高的更多相关文章

  1. graphicview和widgets没本质区别。它只是更轻量级,更灵活,性能更高的widgets

    graphicview和widgets没本质区别.它只是更轻量级,更灵活,性能更高的widgets.核心就是把widgets变成了更轻量级的graphicitem,把QWidget的各种事件转换成了g ...

  2. 寻找性能更优秀的动态 Getter 和 Setter 方案

    反射获取 PropertyInfo 可以对对象的属性值进行读取或者写入,但是这样性能不好.所以,我们需要更快的方案. 方案说明 就是用表达式编译一个 Action<TObj,TValue> ...

  3. 百度echart如何动态生成图表

    百度echart如何动态生成图表 一.总结 一句话总结: clear hideloading setOption 主要是下面三行代码: myChart.clear(); //清空画布myChart.h ...

  4. Aop动态生成代理类时支持带参数构造函数

    一.背景 在某些情况下,我们需要植入AOP代码的类并没有默认构造函数.那么此时动态生成的代理类也需要相同签名的构造函数,并且内部调用原始类的构造函数.自己折腾了1晚上没搞定,现在搞定了发出来供大家一起 ...

  5. dynamic-css 动态 CSS 库,使得你可以借助 MVVM 模式动态生成和更新 css,从 js 事件和 css 选择器的苦海中脱离出来

    dynamic-css 使得你可以借助 MVVM 模式动态生成和更新 css,从而将本插件到来之前,打散.嵌套在 js 中的修改样式的代码剥离出来.比如你要做元素跟随鼠标移动,或者根据滚动条位置的变化 ...

  6. ABP(现代ASP.NET样板开发框架)系列之20、ABP展现层——动态生成WebApi

    点这里进入ABP系列文章总目录 ABP(现代ASP.NET样板开发框架)系列之20.ABP展现层——动态生成WebApi ABP是“ASP.NET Boilerplate Project (ASP.N ...

  7. 【.NET深呼吸】Zip文件操作(2):动态生成Zip文档

    通过前面一篇烂文的介绍,大伙儿知道,ZipArchive类表示一个zip文档实例,除了用上一篇文章中所列的方法来读写zip文件外,还可以直接通过ZipArchive类,动态生成zip文件. 文件流操作 ...

  8. jquery动态生成的元素添加事件的方法

    动态生成的元素如果要添加事件,要写成 $(document).on("click", "#txtName", function() { alert(this.v ...

  9. 利用Java动态生成 PDF 文档

    利用Java动态生成 PDF 文档,则需要开源的API.首先我们先想象需求,在企业应用中,客户会提出一些复杂的需求,比如会针对具体的业务,构建比较典型的具备文档性质的内容,一般会导出PDF进行存档.那 ...

随机推荐

  1. mysql存储过程详解

    mysql存储过程详解 1.      存储过程简介   我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的S ...

  2. android四大组件之Broadcast

    广播的概念 现实中:我们常常使用电台通过发送广播发布消息,买个收音机,就能收听 Android:系统在产生某个事件时发送广播,应用程序使用广播接收者接收这个广播,就知道系统产生了什么事件.Androi ...

  3. Servlet的生命周期+实现方式

    1.Servlet的生命周期:        (1)被创建:            默认情况下,Servlet第一次被访问时,被服务器创建.会调用init()方法.                一个 ...

  4. iOS--UIAlertView与UIAlertController和UIAlertAction之间的事儿

      iOS 8的新特性之一就是让接口更有适应性.更灵活,因此许多视图控制器的实现方式发生了巨大的变化.全新的UIPresentationController在实现视图控制器间的过渡动画效果和自适应设备 ...

  5. XML语言基础2 DTD

    XML DTD 文档类型定义(DTD)可定义合法的XML文档构建模块.它使用一系列合法的元素来定义文档结构. DTD可被声明于XML文档中,也可以作为一个外部的引用. 内部的DOCTYPE声明 假如D ...

  6. Oracle表的几种连接方式

    1,排序 - - 合并连接(Sort Merge Join, SMJ) 2,嵌套循环(Nested Loops, NL) 3,哈希连接(Hash Join, HJ) Join是一种试图将两个表结合在一 ...

  7. java中遍历map的两种方式

    1.先将map对象转成set,然后再转为迭代器 Iterator iterator = map.entrySet().iterator(); while(iterator.hasNext()){ En ...

  8. 从零自学Hadoop(04):Linux准备下

    阅读目录 序 搭建环境 系列索引 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 序 我们已经准 ...

  9. 通过JazzyViewPager来实现Fragment页面间的动画切效果

    JazzyViewPager 开源项目地址: https://github.com/jfeinstein10/JazzyViewPager 其实实现它还是蛮简单的,有两个关键点,一是使用扩展Fragm ...

  10. Tomcat关闭日志catalina.out

    catalina.out文件会越来越大,对系统的稳定造成了一定的影响.conf/logging.properties 一般在部署Tomcat后,运行久了,catalina.out文件会越来越大,对系统 ...