将不确定变为确定系列~Linq的批量操作靠的住吗?
2012-09-22 23:18
302 查看
回到目录
无论是Linq To SQL还是Linq To Object(Entity frameworks)它们都为开发人员提供了Insert操作,及Insert集合操作,即InsertOnSubmit和InsertAllOnSubmit,前者是将一个实体标记为一个插入状态,而后都是将一个集合标记为插入状态,而当前进行这两种操作时,你并没有与数据库进行连接,这就是LINQ提倡的延时加载,那它们什么时候与数据库进行真正的交互呢,实现上,实验表明,是在触发SubmitChanges方法时,才会真实与数据库进行操作,这是正常的,也没有什么可以说的。
而今天我主要说的就是,当我们进行批量插入时,用linq给我们提供的InsertAllOnSubmit方法是否可以实现我们的操作,如果实现了,那是否是我们能够接受的方式,我们在做一个实验吧
一个列表:
结果怎么样呢?经过我的观察,结果是正确的,10万条数据可以插入到数据库中,LINQ确实是帮助我们完成了列表的插入工作,但过程我们是否可以接受?
一 单个实体的Insert,我们采用LINQ的延时插入方式:
二 批量插入实体,我们采用拼接字符串,并向数据服务器发命令的方式,这个也是我比较满足的作品,它是一个通用的方式,并且不需要修改原来插入代码,它的
方法签名是一个列表,这样做是正确的,对于程序员来说是非常友好的。
先看之前的LINQ批量插入:
而在我们修改后,方法签名是不变的,所以原来调用它的方法,不需要进行修改:
所需要的辅助方法:
接下来的时间,我将会继续写一个批量更新和批量删除,敬请收看,呵呵。
回到目录
无论是Linq To SQL还是Linq To Object(Entity frameworks)它们都为开发人员提供了Insert操作,及Insert集合操作,即InsertOnSubmit和InsertAllOnSubmit,前者是将一个实体标记为一个插入状态,而后都是将一个集合标记为插入状态,而当前进行这两种操作时,你并没有与数据库进行连接,这就是LINQ提倡的延时加载,那它们什么时候与数据库进行真正的交互呢,实现上,实验表明,是在触发SubmitChanges方法时,才会真实与数据库进行操作,这是正常的,也没有什么可以说的。
而今天我主要说的就是,当我们进行批量插入时,用linq给我们提供的InsertAllOnSubmit方法是否可以实现我们的操作,如果实现了,那是否是我们能够接受的方式,我们在做一个实验吧
一个列表:
List<User> userList=new List<User>(); for(int i=0;i<100000;i++) { userList.Add(new User{Name="zzl"+i}); } _db.InsertAllOnSubmit(userList); _db.SubmitChanges();
结果怎么样呢?经过我的观察,结果是正确的,10万条数据可以插入到数据库中,LINQ确实是帮助我们完成了列表的插入工作,但过程我们是否可以接受?
可以肯定的说,不可以,而且是非常不可以,对于这个插入操作,它对数据服务器的压力是惊人的,它建立“链接”次为10万次,即每个Insert语句就建立一个链接,这是我们不能接受的,所以,LINQ的批量操作确实靠不住。
OK,既然LINQ的方式是不可取的,那我们只好自己去动手写了,呵呵,我们的思想去将10条Insert合并在一起,一次性发给服务器,一次性执行,对于目前的网络带宽这10条数据不成问题,呵呵。一 单个实体的Insert,我们采用LINQ的延时插入方式:
public virtual void Insert<TEntity>(TEntity entity) where TEntity : class { DB.GetTable<TEntity>().InsertOnSubmit(entity); this.SubmitChanges(); }
二 批量插入实体,我们采用拼接字符串,并向数据服务器发命令的方式,这个也是我比较满足的作品,它是一个通用的方式,并且不需要修改原来插入代码,它的
方法签名是一个列表,这样做是正确的,对于程序员来说是非常友好的。
先看之前的LINQ批量插入:
public virtual void Insert<TEntity>(IEnumerable<TEntity> list) where TEntity : class { DB.GetTable<TEntity>().InsertAllOnSubmit(list); this.SubmitChanges(); }
而在我们修改后,方法签名是不变的,所以原来调用它的方法,不需要进行修改:
/// <summary> /// ADO优化的批量添加 /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="list"></param> public virtual void Insert<TEntity>(IEnumerable<TEntity> list) where TEntity : class { this.InsertForADO<TEntity>(list); }
所需要的辅助方法:
#region LINQ调用T-SQL实现批量添加 /// <summary> /// 得到数据库表或视图的抽象 /// </summary> /// <param name="rowType"></param> /// <returns></returns> MetaTable GetMetaTable(Type rowType) { return DB.Mapping.GetTable(rowType); } /// <summary> /// 建立SQL语句 /// </summary> /// <param name="entity"></param> /// <returns></returns> Tuple<string, object[]> CreateInsertArguments<TEntity>(TEntity entity) { if (entity == null) throw new ArgumentException("The database entity can not be null."); Type entityType = entity.GetType(); MetaTable table = GetMetaTable(entityType); MetaDataMember identityDatamember = table.RowType.DBGeneratedIdentityMember; List<object> arguments = new List<object>(); StringBuilder fieldbuilder = new StringBuilder(); StringBuilder valuebuilder = new StringBuilder(); fieldbuilder.Append("INSERT INTO " + table.TableName + " ("); foreach (var member in table.RowType.PersistentDataMembers) { if (!member.IsAssociation && !member.IsDbGenerated) { object value = entityType.GetProperty(member.Name).GetValue(entity, null); if (value != null) { if (arguments.Count != 0) { fieldbuilder.Append(", "); valuebuilder.Append(", "); } fieldbuilder.Append(member.MappedName); if (member.Type == typeof(string) || member.Type == typeof(DateTime)) valuebuilder.Append("'{" + arguments.Count + "}'"); else valuebuilder.Append("{" + arguments.Count + "}"); if (value.GetType() == typeof(string)) value = value.ToString().Replace("'", "char(39)"); arguments.Add(value); } } } fieldbuilder.Append(") Values ("); fieldbuilder.Append(valuebuilder.ToString()); fieldbuilder.Append(");"); return new Tuple<string, object[]>(fieldbuilder.ToString(), arguments.ToArray()); } void InsertForADO<TEntity>(IEnumerable<TEntity> list) { StringBuilder sqlstr = new StringBuilder(); list.ToList().ForEach(i => { Tuple<string, object[]> insert = CreateInsertArguments(i); sqlstr.AppendFormat(insert.Item1, insert.Item2); }); DB.ExecuteCommand(sqlstr.ToString()); } #endregion
接下来的时间,我将会继续写一个批量更新和批量删除,敬请收看,呵呵。
回到目录
相关文章推荐
- 将不确定变为确定系列~目录(“机器最能证明一切”)
- 将不确定变为确定~Linq的Group是否可以根据多个字段进行分组
- 将不确定变为确定~Linq to SQL不能随机排序吗?
- 将不确定变为确定~Linq-Distinct()方法是否可以对复杂结果集进行去重?
- 将不确定变为确定系列~目录(“机器最能证明一切”)
- 将不确定变为确定~LINQ查询包含对不同数据上下文上所定义项的引用
- 将不确定变为确定~Razor视图中是否可以嵌套JS代码
- 将不确定变为确定~老赵写的CodeTimer是代码性能测试的利器
- 将不确定变为确定~SQLSERVER是否可以进行位运算?
- C#3.0入门系列(LinQ)(六)-之OrderBy操作
- LINQ To SQL在N层应用程序中的CUD操作、批量删除、批量更新
- MP实战系列(十三)之批量修改操作(前后台异步交互)
- Linq无聊练习系列7----Insert,delete,update,attach操作练习
- 将不确定变为确定~transactionscope何时提升为分布式事务~续
- (LINQ 学习系列)(4)Linq教程实例: LINQ单表操作
- XML系列之--Linq操作带属性的XML(四)
- 将不确定变为确定~表达式树是否可以有个集合,条件过滤有了新方向
- LINQ系列:LINQ to DataSet的DataTable操作
- 将不确定变为确定~感谢异或,是你让我彻底摆脱“否定式”
- LINQ系列:LINQ to DataSet的DataTable操作