zoukankan      html  css  js  c++  java
  • Linq To SQL和Linq To Object的批量操作InsertAllOnSubmit介绍

    无论是Linq To SQL还是Linq To Object(Entity frameworks)它们都为开发人员提供了Insert操作,及Insert集合操作,即InsertOnSubmit和InsertAllOnSubmit,前者是将一个实体标记为一个插入状态,而后都是将一个集合标记为插入状态,...

          无论是Linq To SQL还是Linq To Object(Entity frameworks)它们都为开发人员提供了Insert操作,及Insert集合操作,即InsertOnSubmit和InsertAllOnSubmit,前者是将一个实体标记为一个插入状态,而后都是将一个集合标记为插入状态,而当前进行这两种操作时,你并没有与数据库进行连接,这就是LINQ提倡的延时加载,那它们什么时候与数据库进行真正的交互呢,实现上,实验表明,是在触发SubmitChanges方法时,才会真实与数据库进行操作,这是正常的,也没有什么可以说的。 

         而今天我主要说的就是,当我们进行批量插入时,用linq给我们提供的InsertAllOnSubmit方法是否可以实现我们的操作,如果实现了,那是否是我们能够接受的方式,我们在做一个实验吧 

    一个列表: 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    List userList=new List();
                        
     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的延时插入方式: 

    1
    2
    3
    4
    5
    public virtual void Insert(TEntity entity) where TEntity : class
           {
              DB.GetTable().InsertOnSubmit(entity);
               this.SubmitChanges();
          }

    二 批量插入实体,我们采用拼接字符串,并向数据服务器发命令的方式,这个也是我比较满足的作品,它是一个通用的方式,并且不需要修改原来插入代码,它的 

    方法签名是一个列表,这样做是正确的,对于程序员来说是非常友好的。 

    先看之前的LINQ批量插入: 


    public virtual void Insert(IEnumerable list) where TEntity : class 
           { 
               DB.GetTable().InsertAllOnSubmit(list); 
               this.SubmitChanges(); 
           } 
    而在我们修改后,方法签名是不变的,所以原来调用它的方法,不需要进行修改: 


    1         /// 


    2         /// ADO优化的批量添加 
    3         ///


    4         ///


    5         ///


    6         public virtual void Insert

    (IEnumerable list) where TEntity : class 
    7         { 
    8             this.InsertForADO(list); 
    9         } 
    所需要的辅助方法: 


    1 #region LINQ调用T-SQL实现批量添加 
    2         ///
    3         /// 得到数据库表或视图的抽象 
    4         ///
    5         /// 
    6         /// 
    7         MetaTable GetMetaTable(Type rowType) 
    8         { 
    9             return DB.Mapping.GetTable(rowType); 
    10         } 
    11 
    12         ///
    13         /// 建立SQL语句 
    14         ///
    15         /// 
    16         /// 
    17         Tuple<string,> CreateInsertArguments(TEntity entity) 
    18         { 
    19             if (entity == null) 
    20                 throw new ArgumentException("The database entity can not be null."); 
    21 
    22             Type entityType = entity.GetType(); 
    23             MetaTable table = GetMetaTable(entityType); 
    24             MetaDataMember identityDatamember = table.RowType.DBGeneratedIdentityMember; 
    25 
    26             List arguments = new List(); 
    27             StringBuilder fieldbuilder = new StringBuilder(); 
    28             StringBuilder valuebuilder = new StringBuilder(); 
    29 
    30             fieldbuilder.Append("INSERT INTO " + table.TableName + " ("); 
    31 
    32             foreach (var member in table.RowType.PersistentDataMembers) 
    33             { 
    34 
    35                 if (!member.IsAssociation && !member.IsDbGenerated) 
    36                 { 
    37                     object value = entityType.GetProperty(member.Name).GetValue(entity, null); 
    38                     if (value != null) 
    39                     { 
    40                         if (arguments.Count != 0) 
    41                         { 
    42                             fieldbuilder.Append(", "); 
    43                             valuebuilder.Append(", "); 
    44                         } 
    45 
    46                         fieldbuilder.Append(member.MappedName); 
    47                         if (member.Type == typeof(string) || member.Type == typeof(DateTime)) 
    48                             valuebuilder.Append("'{" + arguments.Count + "}'"); 
    49                         else 
    50                             valuebuilder.Append("{" + arguments.Count + "}"); 
    51                         if (value.GetType() == typeof(string)) 
    52                             value = value.ToString().Replace("'", "char(39)"); 
    53                         arguments.Add(value); 
    54 
    55                     } 
    56                 } 
    57             } 
    58 
    59 
    60             fieldbuilder.Append(") Values ("); 
    61 
    62             fieldbuilder.Append(valuebuilder.ToString()); 
    63             fieldbuilder.Append(");"); 
    64             return new Tuple<string,>(fieldbuilder.ToString(), arguments.ToArray()); 
    65         } 
    66 
    67         void InsertForADO(IEnumerable list) 
    68         { 
    69             StringBuilder sqlstr = new StringBuilder(); 
    70             list.ToList().ForEach(i =>
    71             { 
    72                 Tuple<string,> insert = CreateInsertArguments(i); 
    73                 sqlstr.AppendFormat(insert.Item1, insert.Item2); 
    74             }); 
    75             DB.ExecuteCommand(sqlstr.ToString()); 
    76         } 
    77 
    78         #endregion
  • 相关阅读:
    linux recv 返回值与linux socket 错误分析
    位域
    mysql修改root密码的方法
    mysql Plugin ‘InnoDB’ init function returned error
    centos查看版本
    CentOS 7.0 使用 yum 安装 MariaDB 及 简单配置
    CentOS 7.X 中systemctl命令用法详解
    phpMyAdmin关于PHP 5.5+ is required. Currently installed version is: 5.4.16问题
    linux下tar.gz、tar、bz2、zip等解压缩、压缩命令小结
    自动设置IP地址bat脚本
  • 原文地址:https://www.cnblogs.com/lvdongjie/p/5511068.html
Copyright © 2011-2022 走看看