先上测试结果:

  1. //测试1000次针对同一个表同一个字段更新,比Ormlite平均快2.34倍
  2. //生成SQL+ExecuteNonQuery Ormlite 倍数
  3. //6513ms 15158ms 2.327
  4. //6461ms 15303ms 2.369
  5. //6624ms 15424ms 2.329
  6. //6591ms 15468ms 2.347
  7.  
  8. //测试1000次针对同一个表同一个字段更新,比EF平均快1.68倍
  9. //生成SQL+ExecuteNonQuery EF 倍数
  10. //6622ms 11113ms 1.678
  11. //6577ms 11117ms 1.690
  12. //6756ms 11258ms 1.666
  13. //6603ms 11184ms 1.694

不管出于什么原因,有时候框架人员摒弃了NH或EF,而使用原生数据库访问对象。

为了优美的编程,用上我写的轻量级动态生成更新SQL扩展方法吧

还记得在EF中只更新修改过的字段时,我们这么写:

  1. var e = db.Entry(d);
  2. e.State = EntityState.Unchanged;
  3. d.UploadTime = DateTime.Now;
  4. e.Property("UploadTime").IsModified = true;
  5. db.SaveChanges();

目的是,使生成的更新SQL只更新UploadTime字段,否则会更新所有字段,那么就需要先查询一遍再更新。
既然提到数据仓储,我们更新一个实体在数据层最好只有一个方法,但是一个更新的SQL能满足要求吗?

出于以上目的,我写了这样的轻量级扩展方法:

  1. /// <summary>
  2. ///
  3. /// </summary>
  4. public static class SqlStringEx
  5. {
  6. #region 静态私有成员
  7.  
  8. private static object _obj = new object();
  9.  
  10. private static Dictionary<int, PropertyInfo[]> propertiesCache = new Dictionary<int, PropertyInfo[]>();
  11.  
  12. /// <summary>
  13. /// 从缓存中获取属性信息
  14. /// </summary>
  15. /// <param name="t"></param>
  16. /// <returns></returns>
  17. private static PropertyInfo[] GetPropertiesFromCache(Type t)
  18. {
  19. var code = t.GetHashCode();
  20. if (!propertiesCache.ContainsKey(code))
  21. {
  22. lock (_obj)
  23. {
  24. if (!propertiesCache.ContainsKey(code))
  25. {
  26. propertiesCache.Add(code, t.GetProperties());
  27. }
  28. }
  29. }
  30. return propertiesCache[code];
  31. }
  32. #endregion
  33.  
  34. /// <summary>
  35. /// 根据实体模型的赋值情况,动态生成更新SQL。避免要先获取再保存,或者避免按需写多个更新SQL
  36. /// </summary>
  37. /// <typeparam name="T"></typeparam>
  38. /// <param name="t"></param>
  39. /// <param name="tableName">数据表名称</param>
  40. /// <param name="conditionColumnName">更新时条件列名称,该列名需包含在parameters中</param>
  41. /// <param name="parameters"></param>
  42. /// <returns></returns>
  43. public static string GenerateUpdateSql<T>(this T t, string tableName, string conditionColumnName, out List<SqlParameter> parameters)
  44. where T : new()
  45. {
  46.  
  47. parameters = new List<SqlParameter>();
  48. StringBuilder res = new StringBuilder();
  49. res.AppendFormat("update {0} set ", tableName);
  50. var props = GetPropertiesFromCache(t.GetType());
  51. string wherePart = null;
  52. foreach (PropertyInfo item in props)
  53. {
  54. var propVal = item.GetValue(t, null);
  55. var hasValue = propVal != null && !propVal.Equals();
  56. if (hasValue)
  57. {
  58. var filedname = item.GetFieldName();
  59. parameters.Add(new SqlParameter { Value = propVal, ParameterName = filedname });
  60. if (filedname.Equals(conditionColumnName.ToLower()))
  61. {
  62. wherePart = string.Format(" where {0}=@{0} ", filedname);
  63. }
  64. else
  65. {
  66. res.AppendFormat(" {0}=@{0} ,", filedname);
  67. }
  68. }
  69. }
  70. res.Remove(res.Length - , );
  71. res.Append(wherePart);
  72. return res.ToString();
  73. }
  74. }

其中的GetFieldName()方法见上一篇

有了这个方法,数据层一个实体就只需要一个更新的方法,也不需要自己去拼接更新的SQL了。

  1.             List<SqlParameter> parameters =null;
  2. 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. Android中的AlertDialog使用示例二(普通选项对话框)

    在Android开发中,我们经常会需要在Android界面上弹出一些对话框,比如询问用户或者让用户选择.这些功能我们叫它Android Dialog对话框,AlertDialog实现方法为建造者模式. ...

  2. PHP魔术常量

    与J2E相比PHP没有九个内置对象,但他有八个魔术变量分别是: '__LINE__' 文件中的当前行号. '__FILE__ 文件的完整路径和文件名. '__DIR__' 文件所在的目录. '__FU ...

  3. 关于iOS10

    iOS10相册相机闪退bughttp://www.jianshu.com/p/5085430b029fiOS 10 因苹果健康导致闪退 crashhttp://www.jianshu.com/p/54 ...

  4. iOS开发之巧用Block和代理方法结合来传值

    好久没写技术博客了,因为996的工作周期已经持续好几个月了.每天晚上回家都没有太多精力学习很多其他的东西,而且很多时候是接着完善工作的项目的模块开发.所以博客停歇了这么久,更新率也低了不少,今天补充一 ...

  5. js 多选 反选

    //$(".435__1").attr("checked", true); //$(".435__0").removeAttr(" ...

  6. Storm基础

    Storm基本概念 Storm是一个开源的实时计算系统,它提供了一系列的基本元素用于进行计算:Topology.Stream.Spout.Bolt等等. 在Storm中,一个实时应用的计算任务被打包作 ...

  7. SQL SERVER 2012链接到SQL SERVER 2000的问题解决案例

    前几天在在桦仔的SQLSERVER走起微信公众帐号看到一篇文章MS SQL Server2014链接MS SQL Server 2000,当时手机上囫囵吞枣看了个大概,知道是由于SQL SERVER ...

  8. winform窗体(二)——控件

    一.窗体的事件 每一个窗体都有一个事件,这个窗体加载完成之后执行哪一段代码 位置:1)右键属性→事件→load 双击进入 2)双击窗体任意一个位置进入 删除事件:先将事件页面里面的挂好的事件删除,再删 ...

  9. web.xml is missing and <failOnMissingWebXml> is set to true 错误解决办法

    对web项目的解决方案: 右击项目——>Java EE Tools——>Generate Deployment Descriptor Stub. 然后系统会在src/main/webapp ...

  10. mysql内置函数大全

    mysql 字符串函数用法集合 ASCII(str)返回字符串str的最左面字符的ASCII代码值. mysql> select ascii('d'); +------------+ | asc ...