EF架构~性能高效的批量操作(Update篇)
很多时间之长,我写了EF架构~性能高效的批量操作(Insert篇),而今天我把Update篇也写一下,这对于批量处理数据很有帮助,它解决了EF与linq to sql批量更新数据上的效率问题。
对于EF架构中的批量更新操作,需要我们为实体的导航属性进行手动的标示,因为EF生成的实体中没有一个特殊的说明,所以,我们必须要告诉系统,哪个属性是导航属性,而导航属性是我们不去进行update的。
1 /// <summary> 2 /// 属性的导航属性 3 /// </summary> 4 public class NavigationAttribute : Attribute 5 { 6 7 }
而对于要进行批量更新的实体,我们需要为导航属性添加这个特性
1 public class User 2 { 3 public int UserID { get; set; } 4 [Navigation] 5 public User_Extension User_Extension { get; set; } 6 }
而对于我们构建批量Update语句,请看代码,它需要对导航属性进行过滤
1 /// <summary> 2 /// 构建Update语句串 3 /// </summary> 4 /// <typeparam name="TEntity"></typeparam> 5 /// <param name="entity"></param> 6 /// <returns></returns> 7 private Tuple<string, object[]> CreateUpdateSQL<TEntity>(TEntity entity) where TEntity : class 8 { 9 if (entity == null) 10 throw new ArgumentException("The database entity can not be null."); 11 List<string> pkList = GetPrimaryKey<TEntity>().Select(i => i.Name).ToList(); 12 13 Type entityType = entity.GetType(); 14 var table = entityType.GetProperties().Where(i => 15 !pkList.Contains(i.Name) 16 && i.GetValue(entity, null) != null 17 && i.PropertyType != typeof(EntityState) 18 && !(i.GetCustomAttributes(false).Length > 0 19 && i.GetCustomAttributes(false).Where(j => j.GetType() == typeof(NavigationAttribute)) != null) 20 && (i.PropertyType.IsValueType || i.PropertyType == typeof(string)) //过滤导航属性 21 ).ToArray(); 22 23 //过滤主键,航行属性,状态属性等 24 if (pkList == null || pkList.Count == 0) 25 throw new ArgumentException("The Table entity have not a primary key."); 26 List<object> arguments = new List<object>(); 27 StringBuilder builder = new StringBuilder(); 28 29 foreach (var change in table) 30 { 31 if (pkList.Contains(change.Name)) 32 continue; 33 if (arguments.Count != 0) 34 builder.Append(", "); 35 builder.Append(change.Name + " = {" + arguments.Count + "}"); 36 if (change.PropertyType == typeof(string) || change.PropertyType == typeof(DateTime)) 37 arguments.Add("'" + change.GetValue(entity, null).ToString().Replace("'", "char(39)") + "'"); 38 else 39 arguments.Add(change.GetValue(entity, null)); 40 } 41 42 if (builder.Length == 0) 43 throw new Exception("没有任何属性进行更新"); 44 45 builder.Insert(0, " UPDATE " + string.Format("[{0}]", entityType.Name) + " SET "); 46 47 builder.Append(" WHERE "); 48 bool firstPrimaryKey = true; 49 50 foreach (var primaryField in pkList) 51 { 52 if (firstPrimaryKey) 53 firstPrimaryKey = false; 54 else 55 builder.Append(" AND "); 56 57 object val = entityType.GetProperty(primaryField).GetValue(entity, null); 58 builder.Append(GetEqualStatment(primaryField, arguments.Count)); 59 arguments.Add(val); 60 } 61 return new Tuple<string, object[]>(builder.ToString(), arguments.ToArray()); 62 63 }
而对子类公开的Update方法,我们进行了一个封装,它通过操作枚举来确实你是要insert,update还是delete,看代码
1 /// <summary> 2 /// 执行SQL,根据SQL操作的类型 3 /// </summary> 4 /// <typeparam name="TEntity"></typeparam> 5 /// <param name="list"></param> 6 /// <param name="sqlType"></param> 7 /// <returns></returns> 8 protected string DoSQL<TEntity>(IEnumerable<TEntity> list, SQLType sqlType) where TEntity : class 9 { 10 StringBuilder sqlstr = new StringBuilder(); 11 switch (sqlType) 12 { 13 case SQLType.Insert: 14 list.ToList().ForEach(i => 15 { 16 Tuple<string, object[]> sql = CreateInsertSQL(i); 17 sqlstr.AppendFormat(sql.Item1, sql.Item2); 18 }); 19 break; 20 case SQLType.Update: 21 list.ToList().ForEach(i => 22 { 23 Tuple<string, object[]> sql = CreateUpdateSQL(i); 24 sqlstr.AppendFormat(sql.Item1, sql.Item2); 25 }); 26 break; 27 case SQLType.Delete: 28 list.ToList().ForEach(i => 29 { 30 Tuple<string, object[]> sql = CreateDeleteSQL(i); 31 sqlstr.AppendFormat(sql.Item1, sql.Item2); 32 }); 33 break; 34 default: 35 throw new ArgumentException("请输入正确的参数"); 36 } 37 return sqlstr.ToString(); 38 }
代码完成,这个批量操作经过测试,在速度上远远超过EF自带的方法,原因,当然是减少了与数据库交互的次数。
EF批量操作数据,增删改查
12-28
该项目用了VS2017 使用了三种方法进行对数据库的批量操作, SqlBulkCopy , EntityFramework.Extended.6.1.0.168 ,Dapper.1.50.5,EFUtilities.1.0.2 , Z.EntityFramework.Extensions.3.16.17
EF 批量更新/删除数据
热门推荐

在网上找了很久,得到的答案是”Entity Framework 中不能同时更新多条记录”,历经这么多版本,居然还没有这种基本功能,我真的很无语了.还
转 https://blog.csdn.net/weixin_33767813/article/details/85534978
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
2021-06-22 mysql安装之初始化报错:mysqld: [ERROR] Found option without preceding group in config file G:\mysql\my.ini at
2021-06-22 .NET面试题大全(C#面试题)2020更新
2021-06-22 mysql 高版本 sql_mode=only_full_group_by 问题解决方法
2021-06-22 Mysql8.0出现this is incompatible with sql_mode=only_full_group_by
2021-06-22 mysql8 设置sql_mode后不能启动
2021-06-22 mysql.ini 配置
2021-06-22 解决Mysql安装之后没有my.ini配置文件问题