zoukankan      html  css  js  c++  java
  • IBatis.Net 下使用SqlBulkCopy 大批量导入数据 问题解决

    SQLBulkCopy是继承SQLClient空间下的一个特殊类,它可以帮助我们以映射的方式把DataTable和DataReader数据大批量导入到数据库对应表中

     1 public void Inert2DBBySqlBulkCopy(DataTable data, string tableName)
     2 {
     3 BaseDao basdd = new BaseDao();
     4 using (SqlConnection conn = new SqlConnection(basdd.SqlNormMap.DataSource.ConnectionString))
     5 {
     6 if (conn.State != ConnectionState.Open)
     7 conn.Open();
     8 using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(conn))
     9 {
    10 sqlBulkCopy.ColumnMappings.Add(0, "CarModelID");
    11 sqlBulkCopy.ColumnMappings.Add(1, "TranConfID");
    12 sqlBulkCopy.ColumnMappings.Add(2, "TranValue");
    13 sqlBulkCopy.ColumnMappings.Add(3, "CreatorID");
    14 sqlBulkCopy.ColumnMappings.Add(4, "Creator");
    15 sqlBulkCopy.ColumnMappings.Add(5, "OptDataType");
    16 sqlBulkCopy.BatchSize = data.Rows.Count;
    17 sqlBulkCopy.BulkCopyTimeout = 30;
    18 sqlBulkCopy.DestinationTableName = tableName;
    19 sqlBulkCopy.WriteToServer(data);
    20 }
    21 if (conn.State != ConnectionState.Closed)
    22 conn.Close();
    23 }
    24 }

    其中要注意都是:

    Table表中的字段名称,字段顺序,字段类型 必须和插入的sqlBulkCopy.ColumnMappings.Add的插入顺序是一模一样的,如下图,自定义一个Class

     public class JJJModel
        {
            public int? CarModelID { get; set; }
            public int TranConfID { get; set; }
            public string TranValue { get; set; }
            public int CreatorID { get; set; }
            public string Creator { get; set; }
            public int OptDataType { get; set; }
        }
    

    插入的时候的代码

     1   //匹配款式Id和配置ID  拼成二维表数据
     2                             for (int i = 0; i < listCarModelID.Count(); i++)
     3                             {
     4                                 msindex = i;
     5                                 for (int j = 0; j < listTranF.Count(); j++)
     6                                 {
     7                                     JJJModel jj = new JJJModel();
     8                                     jj.CarModelID = Convert.ToInt32(listCarModelID[i]);        //款型ID
     9                                     jj.TranConfID = Convert.ToInt32(listTranF[j].ToString());   //配置ID
    10                                     jj.TranValue = dtCMTranConf.Rows[i][j + 2].ToString().ToUpper();//
    11                                     jj.CreatorID = UserId;
    12                                     jj.Creator = UserName;
    13                                     jj.OptDataType = CarConst.OptDataType20;
    14                                     listTranExcel.Add(jj);
    15                                 }
    16                             }

    异常信息:楼主刚开始写的时候也是按照上边开发,百万数据数据也是轻轻松松分分钟搞定的。可是后来,产品有提到一个要求,就是要大批量更新数据,而且也是速度很快的时间内完成。

    解决SQLBulkCopy批量更新问题

    于是就想先删除 那些要插入的数据,再批量插入要更新的数据,于是乎就捋起胳膊大干一场,当然删除和批量插入肯定是同一张表(Table_A),也肯定是在同一个事务中,后来,后来竟然插入不成功,

    就一直在sqlBulkCopy.WriteToServer(data);这句代码里边一直转悠,一直到sql连接超时结束调试程序。我就郁了个闷的,同样的代码怎么会出现这个问题。

    后来仔细查看对比一下,原来问题是由于对同一个表(Table_A) 先删除,再批量插入的时候  都是在同一个事务中 ,因为删除的时候 就把表给lock了,当然只能插入失败了.

    那怎么办呢,于是楼主就扔然 还让先删除,再插入 在同一个事务中,只是在数据做了个操作,建立一个同样和目标表(Table_A)一样的临时表(Table_Temp),在执行事务开始时候,

    先把要插入的数据插入到临时表Table_Temp,然后执行存储过程,再存储过程中 删除目标表(Table_A)中的存在于临时表(Table_Temp)里边的ID条件数据.

    然后再用Insert Into  目标表(Table_A) select  from 临时表(Table_Temp) 的方法把临时表的数据插入到目标表(Table_A)中.这样就妥妥的完成了。

    PS:存储过程中写个事务,完成不完成都要把临时表(Table_Temp)的数据清空哦 ,这个可不能忘记了

  • 相关阅读:
    Phar与Composer
    [转]一张图帮你搞定职业规划
    Yii2初谈
    阿里前端框架Alice是个不错的选择
    PHP的PSR系列规范都有啥内容
    最新微信公众平台js sdk整合PHP版
    何时该开始写测试代码
    我们太匆忙
    今日思考
    Scala确实是门好语言
  • 原文地址:https://www.cnblogs.com/kangzi/p/4191342.html
Copyright © 2011-2022 走看看