先上测试结果:

        //测试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. 配置 Oracle 11g侦听器来使用SQL操作ST_Geometry(DLL路径问题)

    注:http://resources.arcgis.com/zh-cn/help/main/10.2/index.html#/na/00qn0000001p000000/ (ArcGIS 帮助库) 1 ...

  2. C#操作Excell常用方法

    这是在博客园看的文章,写的很好,所以转一下,方便自己以后用到的时候可以随时查看. range.NumberFormatLocal = "@";     //设置单元格格式为文本 r ...

  3. iOS 10 :用 UIViewPropertyAnimator 编写动画

    英文:shinobicontrols 译文:戴仓薯 链接:http://www.jianshu.com/p/4244cf130478 [iOS 10 day by day] Day 1:开发 iMes ...

  4. RoundedBitmapDrawable生成圆角图片

    Bitmap src = BitmapFactory.decodeResource(getResources(), imageId); //获取Bitmap图片 RoundedBitmapDrawab ...

  5. python之(re)正则表达式上

    python正则表达式知识预备 正则表达式使用反斜杠" \ "来代表特殊形式或用作转义字符,这里跟Python的语法冲突,因此,Python用" \\\\ "表 ...

  6. 在CentOS7上安装JDK1.8

    在CentOS7上安装JDK1.8 1 通过 SecureCRT 连接到阿里云 CentOS7 服务器: 2 进入到目录 /usr/local/ 中: cd /usr/local/ 3 创建目录 to ...

  7. 正则表达式的JS验证

    /判断输入内容是否为空    function IsNull(){        var str = document.getElementById('str').value.trim();      ...

  8. .Net Core 之 图形验证码 本文介绍.Net Core下用第三方ZKWeb.System.Drawing实现验证码功能。

    本文介绍.Net Core下用第三方ZKWeb.System.Drawing实现验证码功能. 通过测试的系统: Windows 8.1 64bit Ubuntu Server 16.04 LTS 64 ...

  9. 下一代Asp.net开发规范OWIN(2)—— Katana介绍以及使用

    接上篇OWIN产生的背景以及简单介绍,在了解了OWIN规范的来龙去脉后,接下来看一下Katana这个OWIN规范的实现,并看看如何使用在我们的Web开发中. 阅读目录: 一. Katana项目的结构和 ...

  10. SQL Server 2008 R2——使用数字辅助表(master..spt_values)实现用计数字段对记录进行重复显示

    =================================版权声明================================= 版权声明:原创文章 谢绝转载  请通过右侧公告中的“联系邮 ...