• .Net中DataAdapter批量插入和更新数据总结


    前言

      前段时间一直在忙着项目上线,在做项目的同时遇到了一些之前不曾碰到的问题,因为没有经验,只能从网上找一些相关的解决方案,但是网上提供的资料实在是太杂,有的根本不能用,耗时又耗力。

      我希望把我这段时间遇到的问题记录下来,去帮助那些当时和我一样“饥渴”的人,以减少时间成本,大家放心,遇到的这些问题提供的解决方案都是经过我们测试,现在正在用的,基本上没什么问题。有什么问题,大家也可以进行探讨,因为问题很多,有些记不起来了,我只能写些可以记起来的分享给大家。

      插一句,就是大家在搜问题的时候,尽量用关键字,不是你搜不到问题的答案,而是你搜问题的方式有问题,而且尽量用google,大家用过就知道为什么了,看不懂的有google翻译。

    批量插入

      我们在.net操作大数据的时候,有时候会遇到大量数据插入的情况,遇到这种方式,我们遇到最笨的方式是forearch插入,很少的数据是可以,但是几千条,几万条就死掉了,这种方式性能很差。既然如此,微软不可能没有好的解决方案的,这就是DataAdapter,我贴下批量插入的:

         public static bool MultiInsertData(DataSet ds, string Columns, string tableName)
            {
                using (OracleConnection connection = new OracleConnection(connectionString))
                {
                    string SQLString = string.Format("select {0} from {1} where rownum=0", Columns, tableName);
                    using (OracleCommand cmd = new OracleCommand(SQLString, connection))
                    {
                        try
                        {
                            connection.Open();
                            OracleDataAdapter myDataAdapter = new OracleDataAdapter();
                            myDataAdapter.SelectCommand = new OracleCommand(SQLString, connection);
                            myDataAdapter.UpdateBatchSize = 0;
                            OracleCommandBuilder custCB = new OracleCommandBuilder(myDataAdapter);
                            DataTable dt = ds.Tables[0].Copy();
                            DataTable dtTemp = dt.Clone();
    
                            int times = 0;
                            for (int count = 0; count < dt.Rows.Count; times++)
                            {
                                for (int i = 0; i < 400 && 400 * times + i < dt.Rows.Count; i++, count++)
                                {
                                    dtTemp.Rows.Add(dt.Rows[count].ItemArray);
                                }
                                myDataAdapter.Update(dtTemp);
                                dtTemp.Rows.Clear();
                            }
    
                            dt.Dispose();
                            dtTemp.Dispose();
                            myDataAdapter.Dispose();
                            return true;
                        }
                        catch (System.Data.OracleClient.OracleException E)
                        {
                            connection.Close();
                            return false;
                        }
                    }
                }
            }

      大家都是搞编程的,一看就明白,我就简单的说下,参数ds是要更新的数据集,Columns是要插入的列表,TableName是要插入的表名,这里需要强调的一点是,插入数据集里的表的字段和类型必须和数据库那边一致,这点重要,要不然插入会报错。

      这里还有加了个分段插入,就是那个for,每400条插入一次,这样可以避免插入的数据太大,会发生超时异常。

      我做项目的时候遇到这种情况是:有些数据是要先保存到本地,比如SqlLite,然后再上传到数据库。

      这里给大家个建议,如果用到wcf,就在传输前对数据集进行压缩,然后到服务端再解压下,这样传输速度会很快。有时间给大家提供压缩的方法。

    批量更新

      批量更新和批量插入差不多的逻辑,我先贴下代码:

            public static bool MultiUpdateData(DataTable data, string Columns, string tableName)
            {
                using (OracleConnection connection = new OracleConnection(connectionString))
                {
                    string SQLString = string.Format("select {0} from {1} where rownum=0", Columns, tableName);
                    using (OracleCommand cmd = new OracleCommand(SQLString, connection))
                    {
                        try
                        {
                            connection.Open();
                            OracleDataAdapter myDataAdapter = new OracleDataAdapter();
                            myDataAdapter.SelectCommand = new OracleCommand(SQLString, connection);
                            OracleCommandBuilder custCB = new OracleCommandBuilder(myDataAdapter);
                            custCB.ConflictOption = ConflictOption.OverwriteChanges;
                            custCB.SetAllValues = true;
                            foreach (DataRow dr in data.Rows)
                            {
                                if (dr.RowState == DataRowState.Unchanged)
                                    dr.SetModified();
                            }
                            myDataAdapter.Update(data);
                            data.AcceptChanges();
                            myDataAdapter.Dispose();
                            return true;
                        }
                        catch (System.Data.OracleClient.OracleException E)
                        {
                            connection.Close();
                            return false;
                        }
                    }
                }
            }

      大家看代码发现和上面插入是差不多的,但是有几点注意的地方我说下,数据集行的状态RowState必须是Modified状态,不是的话需要设置一下,还有就是更新的数据集中必须包含主键,没有的话就会报错。

      重要的一点就是data.AcceptChanges();这句代码,如果注释掉的话,虽然myDataAdapter.Update(data);这段代码更新了,但是数据库那边还是不行的,我的理解是这样:Adapter本身是适配器的意思,适配器是连接两个物体之间的桥梁,就像协议一样,两边都通过才可以完成整个过程。data.AcceptChanges();的意思是应用数据集的更改,我测试过在数据集传输之前应用更新,也是可以更新到数据库的,可能就是dr.SetModified();这段代码在控制吧,如果数据库中的数据在数据集中发生变化,就会生成相应的Uodate,执行更新,这些都是我的猜测,底层的东西我不是很了解,这也是我欠缺的地方,等项目上线完一定要恶补下。

      批量更新我应用的场景是:datagridview绑定查询的数据,对数据进行修改,然后批量更新到数据库。

      希望可以帮到需要帮助的朋友。。。

  • 相关阅读:
    20080619 SQL SERVER 输入 NULL 的快捷键
    20090406 Adobe的“此产品的许可已停止工作”错误的解决办法
    20080908 Office Powerpoint 2007 不能输入中文的解决办法
    20080831 ClearGertrude Blog Skin 's cnblogs_code class
    20080603 Facebook 平台正式开放
    20080519 安装 Microsoft SQL Server 2000 时提示 创建挂起的文件操作
    test
    Linux—fork函数学习笔记
    SOA的设计理念
    Why BCP connects to SQL Server instance which start with account of Network Service fail?
  • 原文地址:https://www.cnblogs.com/xishuai/p/3471508.html
Copyright © 2020-2023  润新知