《项目经验》--简单三层使用DataTable向数据库表批量导入数据---向SqlServer多张张表中导入数据

2023-05-16

    前面已经介绍过如何向数据库的一张表中批量导入数据,详情见博客《项目经验---简单三层使用DataTable向数据库表批量导入数据---向SqlServer一张表中导入数据》;本文主要介绍如何向SqlServer的多张表中批量导入数据。


    如今有这样一个需求,需要批量导入建筑信息,依据数据库表结构设计,批量导入建筑信息,需要向数据库相应的三张表都写入数据。

看一下数据库表结构设计:

   在建筑表(TB_Building)中,BuildingID是主键,在建筑类型表(TB_BuildingType)中BuildingTypeID是主键,建筑表与建筑类型之间的关系通过第三张表(建筑类型关系表《TBR_BuildingTypeLink》)来维护,建筑与建筑类型关系表保证了数据的唯一性!  导入建筑信息,需要同时导入建筑与建筑类型的关系,还需要导入建筑与校区的关系(哪一个校区的建筑)。

   

  


下面借助《批量导入建筑信息》的实例讲解批量向数据库多张表导入数据的方法。

1.界面设计

  观看一下批量导入建筑信息的界面设计:

    

2.框架结构

   此项目的实现,我依然采用简单的三层,看一下项目框架

     


3.批量向数据库多张表导入数据的实现

  下面逐层介绍向数据库导入数据各层的代码实现:

  3.1 SqlHelper数据库助手类中添加向数据库表导入数据的方法(SqlHelper.cs)

 #region 批量导入DataTable
        /// <summary>批量导入DataTable
        /// 批量导入DataTable
        /// </summary>
        /// <param name="dt">DataTable数据表</param>
        /// <param name="tableName">表名</param>
        /// <param name="dtColum">数据列集合</param>
        /// <return>Boolean值:true成功,false失败</return>
        public Boolean InsertTable(DataTable dt, string tableName, DataColumnCollection dtColum)
        {
            //打开数据库
            GetConn();

            try
            {

                //声明SqlBulkCopy ,using释放非托管资源
                using (SqlBulkCopy sqlBC = new SqlBulkCopy(sqlConn))
                {


                    //一次批量的插入的数据量
                    sqlBC.BatchSize = 1000;
                    //超时之前操作完成所允许的秒数,如果超时则事务不会提交 ,数据将回滚,所有已复制的行都会从目标表中移除
                    sqlBC.BulkCopyTimeout = 60;

                    //設定 NotifyAfter 属性,以便在每插入10000 条数据时,呼叫相应事件。 
                    //sqlBC.NotifyAfter = 10000;
                    // sqlBC.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnSqlRowsCopied);

                    //设置要批量写入的表
                    sqlBC.DestinationTableName = tableName;

                    //自定义的datatable和数据库的字段进行对应
                    //sqlBC.ColumnMappings.Add("id", "tel");
                    //sqlBC.ColumnMappings.Add("name", "neirong");
                    for (int i = 0; i < dtColum.Count; i++)
                    {
                        sqlBC.ColumnMappings.Add(dtColum[i].ColumnName.ToString(), dtColum[i].ColumnName.ToString());
                    }
                    //批量写入
                    sqlBC.WriteToServer(dt);
                }
                //  conn.Dispose();
                //GetConn();
                return true;
            }
            catch
            {
                return false;

            }
            finally
            {
                //关闭数据库
                sqlConn.Close();
            }
        }
        #endregion

 3.2 DAL层批量导入数据的代码(BuildingDAL.cs)

  

 #region 批量添加建筑信息
        /// <summary>
        /// 建筑管理:批量添加建筑信息:
        /// 1.向建筑表添加建筑基本信息 
        /// 2.向建筑与建筑类型关联表添加建筑与建筑类型的关联信息 
        /// 3.向建筑与校区关联表添加建筑与校区的关联信息
        /// </summary>
        /// <summary>
        /// 批量导入建筑信息
        /// </summary>
        /// <param name="ds">DataSet-ds;</param>
        public Boolean ImportBuilding(DataSet ds)
        {
            //定义布尔型标记变量,记录建筑是否添加成功
            //添加建筑信息
            Boolean flagAddBuilding;
            //添加建筑与建筑类型的关系
            Boolean flagAddBuildingType;
            //添加建筑与校区的关系
            Boolean flagAddBuildingCampus;

            //执行隐式事务:报错--此操作对该状态的事务无效 的错误于是去掉了事务
            //using (TransactionScope scope = new TransactionScope())
            //{
                //调用sqlHelper的"批量导入datatable表"的方法
                flagAddBuilding = sqlHelper.InsertTable(ds.Tables["dt_AddBuilding"], "TB_Building", ds.Tables["dt_AddBuilding"].Columns);
                //调用sqlHelper的"批量导入datatable表"的方法
                flagAddBuildingType = sqlHelper.InsertTable(ds.Tables["dt_AddBuildingType"], "TBR_BuildingTypeLink", ds.Tables["dt_AddBuildingType"].Columns);
                //调用sqlHelper的"批量导入datatable表"的方法
                flagAddBuildingCampus = sqlHelper.InsertTable(ds.Tables["dt_AddBuildingCampus"], "TBR_BuildingCampusLink", ds.Tables["dt_AddBuildingCampus"].Columns);
            //}

            //返回结果
            return (flagAddBuilding && flagAddBuildingType && flagAddBuildingCampus);
        }


        #endregion

 3.3 BLL层批量导入数据的代码(BuildingBLL.cs)

#region 批量导入建筑信息
        /// <summary>
        /// 批量导入建筑信息
        /// </summary>
        /// <param name="ds">DataSet</param>
        /// <returns>是否导入成功:true成功,false失败</returns>
        public Boolean ImportBuiding(DataSet ds)
        {
            return buildingDAL.ImportBuilding(ds);
        }
        #endregion

  3.4 界面层构造DataSet数据,向BLL层传递

   这里我依然采用从界面上传Excel,然后从Excel获取输入然后存入DataSet的各DataTable表中。

   3.4.1 界面层HTML代码(AddBuilding.aspx)

   

<div class="block">
        <div class="h">
            <span class="icon-sprite icon-list"></span>
            <h3>批量导入建筑</h3>
            <div class="bar">
                <a class="btn-lit" href="javascript:history.go('<% =returnCount %>')"><span>返回</span></a>
            </div>
        </div>
        <div class="tl corner"></div>
        <div class="tr corner"></div>
        <div class="bl corner"></div>
        <div class="br corner"></div>
        <div class="cnt-wp">
            <div class="cnt form">
                <%--<form method="post" enctype="multipart/form-data" action="">--%>
                <table class="data-form" cellspacing="0" cellpadding="0">
                    <tr><td>
                    <asp:Label ID="Label1" runat="server" Text="提示:请导入扩展名为.xls的文件【工作薄名:Sheet1;表头(如下):】"></asp:Label>
                   </td>
                    </tr>
                    <tr><td>
                    <img src="../uploadFileImage/importBuilding.jpg"  alt=""/></td>
                    </tr> 

                    <tr>
                        <asp:FileUpload ID="fupImportBuilding" runat="server" />
                        <asp:Button ID="btnImportBuilding" runat="server" Text="批量导入" OnClick="btnImportBuilding_Click" />                   
                     </tr>
                    
                </table>
               <%-- </form>--%>
            </div>
        </div>
    </div>
 

   3.4.2 从界面传入Excel,调用BLL层Excel转换成DataTable的方法(AddBuilding.aspx.cs)

 #region 批量导入建筑信息
    protected void btnImportBuilding_Click(object sender,EventArgs e) {
        //建筑业务逻辑层
        BuildingBLL buildingBLL = new BuildingBLL();
        //BLL层把Excel转化为datatable类
        CreateExcelDataBLL createExcelData = new CreateExcelDataBLL();
   
        //获取上传文件地址
        string url = fupImportBuilding.PostedFile.FileName.ToString();

        if (url == "")
        {
            //数据源为空,弹出提示:请选择Excel文件!
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('请选择Excel文件!');</script>");
            return;
        }

        string urlLocation = url.Substring(url.LastIndexOf("\\") + 1);//获取文件名

        DataTable dtAllBuildingCampusType;
        //在系统中建文件夹up,并将excel文件另存
        this.fupImportBuilding.SaveAs(Server.MapPath("~\\UploadFile") + "\\" + urlLocation);//记录文件名到服务器相对应的文件夹中

        //获得文件路径
        string strpath = Server.MapPath("~\\UploadFile") + "\\" + urlLocation;
       
        //把上传的Excel转换为datatable
        dtAllBuildingCampusType = createExcelData.CreateExcelDataSource(strpath);

        DataSet dsBuildingCampusType = new DataSet("ds_BuilingCampusType"); //创建一个名为ds_BuilingCampusType的DataSet

        //手动创建的新数据表-建筑数据表
        DataTable dtAddBuilding = new DataTable("dt_AddBuilding"); //创建一个名为dt_AddBuilding的DataTalbe
        //为dt_AddBuilding表内建立Column(表头),添加数据列:建筑ID、建筑代码、建筑名、是否可用、备注、操作类型、操作内容、操作原因、操作人、操作时间
        dtAddBuilding.Columns.Add(new DataColumn("BuildingID", typeof(string)));
        dtAddBuilding.Columns.Add(new DataColumn("BuildingCode", typeof(string)));
        dtAddBuilding.Columns.Add(new DataColumn("BuildingName", typeof(string)));
        dtAddBuilding.Columns.Add(new DataColumn("IsAvailable", typeof(string)));
        dtAddBuilding.Columns.Add(new DataColumn("Descriptions",typeof(string)));
        dtAddBuilding.Columns.Add(new DataColumn("ActionType", typeof(string)));
        dtAddBuilding.Columns.Add(new DataColumn("ActionContent", typeof(string)));
        dtAddBuilding.Columns.Add(new DataColumn("ActionReason", typeof(string)));
        dtAddBuilding.Columns.Add(new DataColumn("Operator", typeof(string)));
        dtAddBuilding.Columns.Add(new DataColumn("SetDatetime", typeof(DateTime)));

        //手动创建的新数据表-建筑、建筑类型关系数据表
        DataTable dtAddBuildingType = new DataTable("dt_AddBuildingType"); //创建一个名为dt_AddBuildingType的DataTalbe
        //为dt_AddBuildingType表内建立Column(表头),添加数据列:建筑ID、建筑类型ID、是否可用
        dtAddBuildingType.Columns.Add(new DataColumn("BuildingID", typeof(string)));
        dtAddBuildingType.Columns.Add(new DataColumn("BuildingTypeID", typeof(string)));
        dtAddBuildingType.Columns.Add(new DataColumn("IsAvailable", typeof(string)));

        //手动创建的新数据表-建筑、校区关系数据表
        DataTable dtAddBuildingCampus = new DataTable("dt_AddBuildingCampus"); //创建一个名为dt_AddBuildingCampus的DataTalbe
        //为dt_AddBuildingCampus表内建立Column(表头),添加数据列:建筑ID、校区ID、是否可用
        dtAddBuildingCampus.Columns.Add(new DataColumn("BuildingID", typeof(string)));
        dtAddBuildingCampus.Columns.Add(new DataColumn("CampusID", typeof(string)));
        dtAddBuildingCampus.Columns.Add(new DataColumn("IsAvailable", typeof(string)));

        //从上传的Excel转换为的datatable表中取出数据,分别放入建筑信息表、建筑与建筑类型关系表、建筑与校区关系表
        for (int intRow = 0; intRow < dtAllBuildingCampusType.Rows.Count; intRow++)
			{
            //建筑ID
            string strBuildingID = Guid.NewGuid().ToString();
            //建筑代码
			string strBuildingCode= dtAllBuildingCampusType.Rows[intRow]["建筑代码"].ToString();
            //建筑名
            string strBuildingName = dtAllBuildingCampusType.Rows[intRow]["建筑名"].ToString();	
            //建筑备注
            string strBuildingDescription=dtAllBuildingCampusType.Rows[intRow]["备注"].ToString();
            //建筑类型代码
            string strBuildingTypeCode = dtAllBuildingCampusType.Rows[intRow]["建筑类型代码"].ToString();
            //校区代码
            string strCampusCode=dtAllBuildingCampusType.Rows[intRow]["校区代码"].ToString();

           
            //根据建筑类型代码获取建筑类型ID
            BuildingTypeEntity enBuildingType = new BuildingTypeEntity();
            //建筑类型代码
            enBuildingType.BuildingTypeCode = strBuildingTypeCode;
            //建筑业务逻辑层,按建筑类型代码查询建筑类型ID
            DataTable dtBuildingType = new BuildingBLL().QueryBuildingTypeByCode(enBuildingType);
            //建筑类型ID为
            string strBuildingTypeID = dtBuildingType.Rows[0]["BuildingTypeID"].ToString();

           
            //根据校区代码获取校区ID
            CampusEntity enCampus = new CampusEntity();
            //校区代码
            enCampus.CampusCode = strCampusCode;
            //建筑业务逻辑层,按校区代码查询校区ID
            DataTable dtCampus = new BuildingBLL().QueryCampusByCode(enCampus);
            //校区ID
            string strCampusID=dtCampus.Rows[0]["CampusID"].ToString();

            //添加建筑信息表的新行
            DataRow drAddBuilding = dtAddBuilding.NewRow();//注意这边创建dt的新行的方法。指定类型是DataRow而不是TableRow,然后不用new直接的用创建的DataTable下面的NewRow方法。
            //建筑信息表对应的各列值
            drAddBuilding["BuildingID"]=strBuildingID;
            drAddBuilding["BuildingCode"] = strBuildingCode;
            drAddBuilding["BuildingName"] = strBuildingName;
            drAddBuilding["IsAvailable"] = "是";
            drAddBuilding["Descriptions"] = strBuildingDescription;
            drAddBuilding["ActionType"] = null;
            drAddBuilding["ActionContent"] = null;
            drAddBuilding["ActionReason"] = null;
            drAddBuilding["Operator"] = null;
            drAddBuilding["SetDatetime"] = DateTime.Now; //当前日期时间
            dtAddBuilding.Rows.Add(drAddBuilding);  //将一整条数据写入表中

            //添加建筑与建筑类型关系信息表的新行
            DataRow drAddBuildingType = dtAddBuildingType.NewRow();
            //建筑与建筑类型关系信息表对应的各列值
            drAddBuildingType["BuildingID"] = strBuildingID;
            drAddBuildingType["BuildingTypeID"] = strBuildingTypeID;
            drAddBuildingType["IsAvailable"] = "是";
            dtAddBuildingType.Rows.Add(drAddBuildingType); //将一整条数据写入表中

            //添加建筑与校区关系信息表的新行
            DataRow drAddBuildingCampus = dtAddBuildingCampus.NewRow();
            //建筑与校区关系信息表对应的各列值
            drAddBuildingCampus["BuildingID"] = strBuildingID;
            drAddBuildingCampus["CampusID"] = strCampusID;
            drAddBuildingCampus["IsAvailable"] = "是";
            dtAddBuildingCampus.Rows.Add(drAddBuildingCampus); //将一整条数据写入表中
        }
        
        //将各表加入DataSet中:建筑信息、建筑与建筑类型关系信息、建筑与校区关系信息
        dsBuildingCampusType.Tables.Add(dtAddBuilding);
        dsBuildingCampusType.Tables.Add(dtAddBuildingType);
        dsBuildingCampusType.Tables.Add(dtAddBuildingCampus);

       

        //将DataSet中数据表导入数据库
        Boolean flagImportBuilding = buildingBLL.ImportBuiding(dsBuildingCampusType);

        if (true==flagImportBuilding)
        {
            //导入成功,弹出提示
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('建筑信息导入成功!');</script>");


        }
        else
        {
            //导入失败,弹出提示
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('建筑信息导入失败!');</script>");


        }
    }
    #endregion

   3.4.3 BLL层Excel转换成DataTable的类(MgrCreateExcelData.cs)

/*******************************************************************************
 *文    件:CreateExcelDataBLL.cs
 *作    者:mzj
 *所属小组:评教小组
 *文件说明:基础系统-把excel转化为datatable
 *创建日期:2013年1月23日9:43:16
 *修改作者:
 *修改日期:
 *修改描述:
 *版 本 号:V1.0
 *版本号变更记录:     
********************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//引用各命名空间
using System.Data;
using System.Data.OleDb;
using System.Data.SqlClient;
using System.IO;

namespace TeachSystem.BLL.CreateExcelDataBLL
{
    public class CreateExcelDataBLL
    {
        //构造方法
        public CreateExcelDataBLL()
        {

        }
        /// <summary>
        /// 传入excel路径,转换为datatable
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public DataTable CreateExcelDataSource(string url)
        {
            //定义一个DataTable数据表
            DataTable dt = null;

            //获得excel数据
            string connetionStr = "Provider=Microsoft.Jet.OleDb.4.0;" + "data source=" + url + ";Extended Properties='Excel 8.0; HDR=YES; IMEX=1'";
            //从Excel表的Sheet1单元格获取数据
            string strSql = "select * from [Sheet1$]";
            OleDbConnection oleConn = new OleDbConnection(connetionStr);

            OleDbDataAdapter oleAdapter = new OleDbDataAdapter(strSql, connetionStr);
            try
            {
                //把Excel数据填充给DataTable
                dt = new DataTable();
                oleAdapter.Fill(dt);
                //返回数据表
                return dt;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                oleAdapter.Dispose();
                oleConn.Close();
                oleConn.Dispose();
                //删除上传的Excel文件(因为该文件的存在会占用多余的网站空间)
                if (File.Exists(url))
                {
                    File.Delete(url);
                }
            }
        }
    }
}

   至此批量向数据库多张表导入数据的功能已完成了,对想数据库表导入的数据的合法性还需要自己通过代码进进行判断!


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

《项目经验》--简单三层使用DataTable向数据库表批量导入数据---向SqlServer多张张表中导入数据 的相关文章

  • 解决Unable to add window -- token android.os.BinderProxy is not valid; is your activity running?

    运行项目有时候在dialog这里一直报错 xff0c 按照日志在网上找解决方案 很多都跑到了底层去解决这问题 然而我不懂底层 xff0c 没办法 继续找咯 苍天明鉴 xff01 找到问题了 原因一般是展示dialog的时候用的是异步 xff
  • centos系统中php Curl 无法访问https ,更换ssl_version NSS为openssl

    在centos 6上面 curl模块的ssl 支持默认为NSS xff0c 涉及到的程序里有https xff0c 是需要双向认证的 xff0c 这时使用NSS会报错 所以需要更换为openssl 一 查看系统自带的curl的版本 root
  • python-求三角形的面积

    计算三角形的面积 法一 xff1a 计算三角形的面积 a 61 float input 39 输入三角形第一边长 xff1a 39 b 61 float input 39 输入三角形第二边长 39 c 61 float input 39 输
  • 如何把达梦8数据库安装在root用户下管理

    达梦数据库一般安装在dmdba用户下 xff0c 官方文档也是这么推荐的 那么有没有办法不创建dmdba用户 xff0c 直接安装在root下呢 xff1f 希望我不要把大家带偏 xff0c 只是本着研究学习的心态 xff0c 做个实验 结
  • The word 'localhost' is not correctly spelled 这个问题怎么解决

    有时工程中有下划线并提示 The word is not correctly spelled 此问题是MyEclipse校验单词拼写造成 xff0c 如果出在配置文件中 xff0c 一般会影响到程序的正常执行 解决方法 xff1a 在MyE
  • Seaship数据集+yolov5

    在SeaShip数据集上验证YoloV5 操作系统 xff1a ArchLinux 需要代理 1 conda安装配置 已经完成的小伙伴可以直接跳过 安装Anaconda yay安装 yay S anaconda 激活Anaconda环境 s
  • 对抗样本生成方法学习总结

    title 对抗样本生成方法 date 2023 03 21 15 08 46 tags pytorch 对抗样本 cover https s2 loli net 2023 03 20 TkeiAjqp3Jdg9tI png categor
  • 划词翻译简单实现

    环境 xff1a archlinux xff0c 其余linux系统类似 安装依赖 span class token function sudo span pacman S xsel span class token function su
  • 平凡的人生or开挂的人生——对知乎相关问题的回答

    知乎原题 xff1a 为什么有些人的人生和开了挂一样 xff1f https www zhihu com question 37106162 楼上说的都特别好 xff0c 我很想补充一点 我先抛出一个背景概念 我认为开挂人生 xff0c 本
  • ARM64启动过程分析

    文章目录 arm64启动过程分析arm64启动过程分析 xff08 一 xff09 boot protocolarm64启动过程分析 xff08 二 xff09 内核启动第一步arm64启动过程分析 xff08 三 xff09 创建启动阶段
  • Android Studio: Kotlin使用DataBinding异常

    异常 Error 7 30 Unresolved reference databinding E test Android Jetpack app src main java com mazaiting jetpack architectu
  • H5C3__元素垂直居中的方法

    在 CSS 中对元素进行水平居中是非常简单的 xff1a 如果它是一个行内元素 xff0c 就对它的父元素应用 text align center 如果它是一个块级元素 xff0c 就对它自身应用 margin auto 还有没有其他的方法
  • 2013年期中总结 2013年9月10日20:17:49

    题目中的时间 xff0c 我改了几次 xff0c 一直在想这半年来的经历 xff0c 我想我是成长着的吧 xff01 继上次总结 2012年年度总结 2013年2月25日21 49 44 xff0c 眨眼过去了半年 xff0c 细细想来这半
  • VMware安装Ubuntu20.04.5常见问题及解决方案

    文章目录 使用Xftp连接ubuntu系统ubuntu上安装指定版本nodejsubuntu设置连网ubuntu安装Java8ubuntu安装 deb格式软件ubuntu卸载 deb格式软件ubuntu中electron框架安装的缓存在如下
  • 关于行业代码对应表的数据库设计及导入(4位行业代码)

    最近使用asp net 43 sqlserver 43 layui前端框架完成了一个小页面 xff0c 其中有一个功能是需要将行业代码表导入倒数据库 看到这个行业代码表 xff0c 刚开始还真是无从下手 xff0c 经过查询找到一个页面是关
  • 当你不想学习的时候,来看看大脑是怎么想的《摘抄与所想》

    尽管科学家一个接一个的科研成果让我们对记忆有了越来越多的了解 xff0c 但直到今天 xff0c 科学家所发现的所谓大脑的秘密也只是冰山一角 xff0c 在很大程度上 xff0c 大脑和记忆仍是神秘的 研究人员认为 xff0c 记忆是一个过
  • English learning method ---学英语重中之重打通“任督二脉”

    漫漫十年艰辛路 xff0c 英语学习之旅 曾经秉承 路漫漫其修远兮 xff0c 吾将上下而求索 的信念 xff0c 初一那年了解到原来 xff08 a b c d e f g xff09 不仅仅读作 xff08 啊 xff0c 波 xff0
  • DRP过后,感受知识间的通性

    DRP视频看了不短的时间 xff0c 真正开始DRP的时间是7月17号 xff0c 至今两个月了 由于暑假期间英语的学习占得时间比较多 xff0c 所以DRP视频进行的很慢 9月11号看完了DRP所有的视频 xff0c 这个项目完成后最大的
  • English learning method ---我谈音标学习

    最近在想这样一个问题 xff1a 每个地方都有自己的方言 xff0c 有些方言我们完全听不懂 xff0c 但是他们当地人却可以交流的很好 xff1b 而非本地人说方言 xff0c 就要模仿他们的腔调 xff0c 模仿的多了说出来的味也就像了
  • English learning method ---如何加强听力

    在之前的一篇博客 English learning method 学英语重中之重打通 任督二脉 中主要讲述的是听力的重要性 xff0c 在这篇博客中主要讲述如何加强听力 学习理论 语言学习始于听 xff0c 小孩首先通过近两年的听来学习语言

随机推荐