【唠叨两句】如何将一张树型结构的Excel表格中的数据导入到多张数据库表中
小弟昨天遇到一个相对比较棘手的问题,就像标题说的那样、如何将一张树型结构的Excel表格中的数据导入到多张数据库表中,在现实中实际是七张数据库表,这七张表之间有着有着相对比较复杂的主外键关系,对于我这么洼的水平,刚遇到时确实愣了一下。不过还好、等冷静下来之后,慢慢的找到的了解决的办法。现在与大家分享一下处理思路及方法。
先说一下这里用到的一些主要的东东吧:
一、DataView类:
构造函数 DataView(dataTable)
方法
dataView.ToTable(String, Boolean, String[]) 【已重载】
方法解释:根据现有 DataView 中的行,创建并返回一个新的 DataTable。
二、DataTable类
dataTable.Merge(dataTable);[已重载]
方法解释:将指定的 DataTable 与当前的 DataTable 合并
三、DataRelation类:该类是用来表示两个DataTable中间的关系的。
DataRelation 的一项主要功能就是在 DataSet 中从一个 DataTable 浏览到另一个。 它使您能够在给定相关 DataTable 中的单个 DataRow 的情况下检索一个 DataTable 中的所有相关 DataRow 对象。
DataRelation 常用的构造函数,还有其他构造函数哦
名称 |
说明 |
DataRelation(String, DataColumn, DataColumn) |
使用指定的 DataRelation 名称,父级和子级 DataColumn 对象,初始化 DataRelation 类的新实例。 |
DataRelation(String, DataColumn[], DataColumn[]) |
使用指定的 DataRelation 名称以及父级和子级 DataColumn 对象的匹配的数组,初始化 DataRelation 类的新实例。 |
DataRelation中的常用属性
ChildColumns |
获取此关系的子 DataColumn 对象。 |
ChildTable |
获取此关系的子表。 |
DataSet |
获取 DataRelation 所属的 DataSet。 |
ParentColumns |
获取作为此 DataRelation 的父列的 DataColumn 对象的数组。 |
ParentTable |
获取此 DataRelation 的父级 DataTable。 |
RelationName |
获取或设置用于从 DataRelationCollection 中检索 DataRelation 的名称。 |
|
|
关于DataRelation的一个MSDN上的简单例子:
DataRelation customerOrdersRelation =
customerOrders.Relations.Add("CustOrders",
customerOrders.Tables["Customers"].Columns["CustomerID"],
customerOrders.Tables["Orders"].Columns["CustomerID"]);
foreach (DataRow custRow in customerOrders.Tables["Customers"].Rows)
{
Console.WriteLine(custRow["CustomerID"].ToString());
foreach (DataRow orderRow in custRow.GetChildRows(customerOrdersRelation))
{
Console.WriteLine(orderRow["OrderID"].ToString());
}
}
四、SqlBulkCopy 对象【适用于MSSQL】:用于极速插入数据
有了上述的这些东西我们就可以实现将一张树型结构的Excel表格中的数据导入到多张数据库表中了,下面我简单的说一下我的思路 及 处理方法。
在此以 类 、项、 种 为例,其中类是项的上一级,项是种的上一级。
类 数据库 表名:Classcification 字段名:ClassificationID【PK】,ClassificationName
项 数据库 表名:Term 字段名:TermID【PK】, TermName, ClassificationID
种 数据库 表名:Kind 字段名:KindID【PK】, KindName, TermID
先定义两个全局私有字段
#region 全局私有字段
/// <summary>
/// 源数据视图
/// </summary>
private DataView dvSource;
/// <summary>
/// 全部变量用来临时存放三个表及三个表之间的关系DataRelation
/// </summary>
private DataSet dsTemp;
#endregion
//全局阶段(1)
//类
DataTable Classification =new DataTable("Classification");
Classification.Columns.Add("ClassificationID");
Classification.Columns.Add("ClassificationName");
this.dsTemp.Tables.Add(Classification);
//项
DataTable Term =new DataTable("Term");
Term.Columns.Add("TermID");
Term.Columns.Add("TermName");
Term.Columns.Add("ClassificationID");
//辅助作用
Term.Columns.Add("ClassificationName");
//保存DataTable至全局变量DataSet中
this.dsTemp.Tables.Add(Term);
//建立类与项之间的关系
DataRelation ReClassTerm =new DataRelation("ReClassTerm", Classification.Columns["ClassificationName"], Term.Columns["ClassificationName"]);
//保存关系至DataSet
this.dsTemp.Relations.Add(ReClassTerm);
//种
DataTable Kind =new DataTable("Kind");
Kind.Columns.Add("KindID");
Kind.Columns.Add("KindName");
Kind.Columns.Add("TermID");
//辅助作用
Kind.Columns.Add("TermName");
//保存DataTable至全局变量DataSet中
this.dsTemp.Tables.Add(Kind);
//建立关系
DataRelation ReTermKind =new DataRelation("ReTermKind", Term.Columns["TermName"], Kind.Columns["TermName"]);
//保存关系至Dataset
this.dsTemp.Relations.Add(ReTermKind);
#endregion
处理方式见下:
、、前台工作 // 全局阶段 // (1)生成 七张数据表DataTable 及他们之间的关系保存到全局DataSet中 // (2)源数据视图.ToTable()生成一个新的Table实例【此时的表中含有辅助作用的数据列】【Merge到 全局DateSet的相应表中】 //
// 类-阶段 // (1)【获取全局DateSet中相应的表中的数据】 保存到DataTable // (2)获取数据库中已有的数据行 // (3)Foreach循环对比过滤重复数据行、将数据库中已经存在的数据行从当前的DataTable中移除。 // (4)写入主键值DateTime.Now.Ticks.ToString(); 用自动加一的方式赋值主键 // (5)用数据库框架结构表Merge(当前的数据表) // (6)SqlBulkCopy。WriteToServer(数据库框架结构表)【向数据库中插入数据】 // (7)清空当前DateSet中的当前表的所有记录 // (8)从数据库中读取所有的新记录,然后再次保存到全局DataSet中的相应表中
// 项-阶段 // (9) 【获取全局DateSet中相应的表中的数据】 保存到DataTable // (10)获取数据库中已有的数据行 // (11)Foreach循环对比过滤重复数据行即将数据库中已经存在的数据行从当前的DataTable中移除。 // (12)将父表的主键值写入到当前表的相应的数据列中【此时需要借助DataRelation连接父表】 // (13)注意:移除辅助作用数据列【因为数据库中不存在该数据列】 // (14)用数据库框架结构表Merge(当前的数据表) // (15)SqlBulkCopy。WriteToServer(数据库框架结构表)【插入数据】 // (16)清空当前DateSet中的当前表的所有记录 // (17)从数据库中读取所有的新记录,然后再次保存到全局DataSet中的相应表中
// 种-阶段 类似于项阶段 |
OK,到此结束了。。。
最后再唠叨两句,对于三个表而言这样做是有点繁琐了,但是对于多表而言,这样做我感觉还是不错的。
在整个过程中有两点需要注意:
(1)Merge的使用,这个方法使用来合并相识的两个DataTable,此方法不但能够改变Table中的数据而且可以改变table的结构。
(2)关于DateSet的,千万不能 用新DataTable 去赋值 全局DataSet中的DataTable,否则其DataRelation将会失效。此时如果想对DataSet中的某一个DataTable 用DataTable去赋值,请选用Merge方法。
如果大侠们还有好的建议或者想法 欢迎指教。。。
嘿嘿,我要休息喽。。。