触发button事件--->导入一张excel表,最终将excel表的数据导入sql server 2000
button事件大略如下:
{
OpenFileDialog openFile1 = new OpenFileDialog(); //要求用户导入目标Excel表
new DataSet();
new DataTable();
{
// 将Excel表元数据导入DataTable,生成多条DataRow
}
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conn)) //将DataTable批量导入sql server 2000
{
bulkCopy.WriteToServer(DataTable);
}
}
-----------------------------------------
当点第一次button,导入表1之后,查询sql server,发现有一张表1的内容;
但是,点第二次button,导入表2,再次查询sql server,却发现内容为:
表1+表1+表2
也就是说重复了表1的内容。跟踪SqlBulkCopy的运行次数:总共只为2,不是3。
我试过在SqlBulkCopy之后写Dataset.Clear()和DataTable.Clear()也无济于事。
请问问题出现在哪?解决办法是什么呢?
9 个解决方案
#1
补充一下,数据库中对应的表没有主键,只有两个外键约束
#2
LZ 你代码最好贴全
从问题来看
你最好跟一下 第二次BUTTON 时的 DATATABLE的内容。
估计没错的话,应该是第一个BUTTON后,EXCEL 没有释放~
然后第二BUTTON时 EXCEL 的SHEET发生合并了
从问题来看
你最好跟一下 第二次BUTTON 时的 DATATABLE的内容。
估计没错的话,应该是第一个BUTTON后,EXCEL 没有释放~
然后第二BUTTON时 EXCEL 的SHEET发生合并了
#3
代码比较长:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
using System.Data.SqlClient;
namespace IOdatabase
{
public partial class Form1 : Form
{
public Sheets sheets;
public Worksheet datasheet;
public Range range; //数据表中对应范围的数据
public System.Array Cellarray; //数据表中对应范围的数据转换为数组形式
public SqlConnection conn;
public Form1()
{
InitializeComponent();
this.textBox1.ReadOnly = true; //设置TextBox为只读
this.textBox1.BackColor = Color.White; //设置TextBox的背景色为白色
this.dataGridView1.ReadOnly = true; //设置DataGridView为只读
}
private void button1_Click(object sender, EventArgs e) //按钮:“导入表”
{
this.textBox1.Clear();
OpenFileDialog openFile1 = new OpenFileDialog(); //动态添加OpenFileDialog控件,用于弹出一个窗口提示用户打开文件
openFile1.Filter = "Microsoft Excel 工作表|*.xls";
if (openFile1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
int count = 0;
string OpenFilePath = openFile1.FileName;
Microsoft.Office.Interop.Excel.ApplicationClass app = new ApplicationClass();
app.Visible = false;
WorkbookClass Workbook = (WorkbookClass)app.Workbooks.Open(OpenFilePath);//打开对应路径的Excel
object missing = Type.Missing;
sheets = Workbook.Worksheets;
this.textBox1.Text += "正在解析..." + Environment.NewLine;
//判断导入的表是否是完整sheet的表
foreach (Worksheet sheet in sheets)
{
if (sheet.Name == "寿险公司" || sheet.Name == "财产公司" || sheet.Name == "明细表" || sheet.Name == "赔款")
{
count++;
}
}
if (count > 0 && count < 4)
{
this.textBox1.Text += "导入的表,其中包含的sheet不完整,请重新导入!";
return;
}
else if (count == 0)
{
this.textBox1.Text += "导入了格式完全错误的表,请重新导入!";
return;
}
else
{
this.textBox1.Text += "表的格式完全正确,正在导入数据库!"+Environment.NewLine;
}
// 解析出表的“年”、“月”
datasheet = null;
foreach (Worksheet sheet in sheets)
{
if (sheet.Name == "寿险公司") //读取“寿险公司”的sheet;
{
datasheet = sheet;
break;
}
}
range = datasheet.get_Range("G2");
string data = (System.String)range.Value;
string[] dataArray = data.Split(new char[2] { '年', '月' }); //dataArray[0]为年份,dataArray[1]为月份
/*
要导入填充函数的三个参量:sheets(完整的表)、
dataArray[0](年份)、dataArray[1](月份)
*/
//---------------导入填充函数---------------//
LoadSheetsFunction(Convert.ToInt32(dataArray[0]), Convert.ToInt32(dataArray[1]));
//-------------------回收Excel进程-------------------//
Workbook.Close();
System.Runtime.InteropServices.Marshal.ReleaseComObject(Workbook);
Workbook = null;
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets);
sheets = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(datasheet);
datasheet = null;
GC.Collect();
}
}
void LoadSheetsFunction(int year, int month) //填充函数
{
string connString = @"
server = (local);
integrated security = true;
database = ExcelDatabase
"; // 连接数据库的字符串
using (conn = new SqlConnection(connString))
{
conn.Open();
LoadLifeInsuranceCompany(year, month); //填充“寿险公司”
}
}
void LoadLifeInsuranceCompany(int year, int month) //填充“寿险公司”的函数
{
foreach (Worksheet sheet in sheets)
{
if (sheet.Name == "寿险公司") //读取“寿险公司”的sheet;
{
datasheet = sheet;
}
}
SqlCommand Newcmd = new SqlCommand("select * from LifeInsuranceCompany where (year=" + year.ToString() + ")" + "and (month=" + month.ToString() + ")", conn);
SqlDataReader rdr = Newcmd.ExecuteReader();
if (!rdr.HasRows)
{
rdr.Close();
string sql = @"select * from LifeInsuranceCompany";
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
DataSet ds = new DataSet();
da.Fill(ds, "LifeInsuranceCompany");
System.Data.DataTable dt = ds.Tables["LifeInsuranceCompany"];
int[] Rowarray = new int[6] { 13, 21, 29, 37, 45, 53 };
for (int CompanyID = 1; CompanyID <= 6; CompanyID++) // 填充DataTable
{
range = datasheet.get_Range("D" + Rowarray[CompanyID - 1].ToString(), "K" + (Rowarray[CompanyID - 1]+5).ToString());
Cellarray = (System.Array)range.Value;
for (int InsuranceID = 1; InsuranceID <= 5; InsuranceID++)
{
DataRow newRow = dt.NewRow();
newRow["year"] = year;
newRow["month"] = month;
newRow["CompanyID"] = CompanyID;
newRow["InsuranceID"] = InsuranceID;
newRow["NewInsurancePremium"] = (Cellarray.GetValue(InsuranceID, 1)!= null ? Cellarray.GetValue(InsuranceID,1) : DBNull.Value);
newRow["RenewalPremium"] = (Cellarray.GetValue(InsuranceID, 3) != null ? Cellarray.GetValue(InsuranceID, 3) : DBNull.Value);
newRow["ExpenditureAndPayment"] = (Cellarray.GetValue(InsuranceID, 5) != null ? Cellarray.GetValue(InsuranceID, 5) : DBNull.Value);
newRow["GrossPremiumIncome"] = (Cellarray.GetValue(InsuranceID, 7) != null ? Cellarray.GetValue(InsuranceID, 7) : DBNull.Value);
dt.Rows.Add(newRow);
}
}
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conn)) //用SqlBulkCopy将DataTable的表批量导入到数据源
{
bulkCopy.DestinationTableName =
"LifeInsuranceCompany";
try
{
// Write from the source to the destination.
bulkCopy.WriteToServer(dt);
}
catch (Exception ex)
{
this.textBox1.Clear();
this.textBox1.Text+="数据导入失败!"+Environment.NewLine +ex;
}
}
}
else
{
this.textBox1.Clear();
this.textBox1.Text += "寿险公司" + year.ToString() + "年" + month.ToString() + "月的表已经存在,不需要再次导入!";
rdr.Close();
}
}
}
}
#4
发现一个现象,就是第一次打开的Excel表,在程序关闭前一直驻留在内存,而第二次以上打开的表调用完成后会自动回收。
#5
datatable结果也是
表1+表1+表2
表1+表1+表2
#6
LZ~~~阅读你的代码够费劲-_-
基本把你的意图理解为:
1读取EXCEL
2验证EXCEL数据
3从EXCEL获取 年,月属性
4根据年月属性从数据库中获取指定数据
5数据拼接成新的DATATABLE
6数据入库
目前看下来你的数据填充这块的业务逻辑有问题
string sql = @"select * from LifeInsuranceCompany";
这里你获取了表中所有的数据
当第二次添加时,第一次数据也被取出,然后新的数据追加在了DT的后面。
当执行BULKCOPY时就等于多加了一次数据(1)
而数据库的数据变为 1+1+2了,如果第三次添加数据时则变为 1+1+2+1+1+2+3
既然你是新填数据,这里完全没有必要从原来的表中获取数据
基本把你的意图理解为:
1读取EXCEL
2验证EXCEL数据
3从EXCEL获取 年,月属性
4根据年月属性从数据库中获取指定数据
5数据拼接成新的DATATABLE
6数据入库
目前看下来你的数据填充这块的业务逻辑有问题
string sql = @"select * from LifeInsuranceCompany";
这里你获取了表中所有的数据
当第二次添加时,第一次数据也被取出,然后新的数据追加在了DT的后面。
当执行BULKCOPY时就等于多加了一次数据(1)
而数据库的数据变为 1+1+2了,如果第三次添加数据时则变为 1+1+2+1+1+2+3
既然你是新填数据,这里完全没有必要从原来的表中获取数据
#7
我估计你这里
select * from LifeInsuranceCompany
的目的是想获取“LifeInsuranceCompany”这张表的结构(因为BULKCOPY这样要求,否则添加不了)
你完全可以通过这样的方法构建DATATABLE的结构
select * from LifeInsuranceCompany
的目的是想获取“LifeInsuranceCompany”这张表的结构(因为BULKCOPY这样要求,否则添加不了)
你完全可以通过这样的方法构建DATATABLE的结构
DataTable dt = new DataTable();
dt.Columns.Add("year", typeof(DateTime));
#8
另外给LZ一些额外的建议
1. 好好的提升一下自己代码编写的习惯。不是所有人都有耐心看完你这样的代码的...
2. 学习一下架构的知识(诸如三层架构等)。
3. 好的软件是能反复使用(或者说重用的)。
1. 好好的提升一下自己代码编写的习惯。不是所有人都有耐心看完你这样的代码的...
2. 学习一下架构的知识(诸如三层架构等)。
3. 好的软件是能反复使用(或者说重用的)。
#9
谢谢您耐心的帮助!您指出的的"select * from LifeInsuranceCompany"的确是根源所在。
您说的“好好的提升一下自己代码编写的习惯”是指我目前的代码缺乏精简吗?
#1
补充一下,数据库中对应的表没有主键,只有两个外键约束
#2
LZ 你代码最好贴全
从问题来看
你最好跟一下 第二次BUTTON 时的 DATATABLE的内容。
估计没错的话,应该是第一个BUTTON后,EXCEL 没有释放~
然后第二BUTTON时 EXCEL 的SHEET发生合并了
从问题来看
你最好跟一下 第二次BUTTON 时的 DATATABLE的内容。
估计没错的话,应该是第一个BUTTON后,EXCEL 没有释放~
然后第二BUTTON时 EXCEL 的SHEET发生合并了
#3
代码比较长:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
using System.Data.SqlClient;
namespace IOdatabase
{
public partial class Form1 : Form
{
public Sheets sheets;
public Worksheet datasheet;
public Range range; //数据表中对应范围的数据
public System.Array Cellarray; //数据表中对应范围的数据转换为数组形式
public SqlConnection conn;
public Form1()
{
InitializeComponent();
this.textBox1.ReadOnly = true; //设置TextBox为只读
this.textBox1.BackColor = Color.White; //设置TextBox的背景色为白色
this.dataGridView1.ReadOnly = true; //设置DataGridView为只读
}
private void button1_Click(object sender, EventArgs e) //按钮:“导入表”
{
this.textBox1.Clear();
OpenFileDialog openFile1 = new OpenFileDialog(); //动态添加OpenFileDialog控件,用于弹出一个窗口提示用户打开文件
openFile1.Filter = "Microsoft Excel 工作表|*.xls";
if (openFile1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
int count = 0;
string OpenFilePath = openFile1.FileName;
Microsoft.Office.Interop.Excel.ApplicationClass app = new ApplicationClass();
app.Visible = false;
WorkbookClass Workbook = (WorkbookClass)app.Workbooks.Open(OpenFilePath);//打开对应路径的Excel
object missing = Type.Missing;
sheets = Workbook.Worksheets;
this.textBox1.Text += "正在解析..." + Environment.NewLine;
//判断导入的表是否是完整sheet的表
foreach (Worksheet sheet in sheets)
{
if (sheet.Name == "寿险公司" || sheet.Name == "财产公司" || sheet.Name == "明细表" || sheet.Name == "赔款")
{
count++;
}
}
if (count > 0 && count < 4)
{
this.textBox1.Text += "导入的表,其中包含的sheet不完整,请重新导入!";
return;
}
else if (count == 0)
{
this.textBox1.Text += "导入了格式完全错误的表,请重新导入!";
return;
}
else
{
this.textBox1.Text += "表的格式完全正确,正在导入数据库!"+Environment.NewLine;
}
// 解析出表的“年”、“月”
datasheet = null;
foreach (Worksheet sheet in sheets)
{
if (sheet.Name == "寿险公司") //读取“寿险公司”的sheet;
{
datasheet = sheet;
break;
}
}
range = datasheet.get_Range("G2");
string data = (System.String)range.Value;
string[] dataArray = data.Split(new char[2] { '年', '月' }); //dataArray[0]为年份,dataArray[1]为月份
/*
要导入填充函数的三个参量:sheets(完整的表)、
dataArray[0](年份)、dataArray[1](月份)
*/
//---------------导入填充函数---------------//
LoadSheetsFunction(Convert.ToInt32(dataArray[0]), Convert.ToInt32(dataArray[1]));
//-------------------回收Excel进程-------------------//
Workbook.Close();
System.Runtime.InteropServices.Marshal.ReleaseComObject(Workbook);
Workbook = null;
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets);
sheets = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(datasheet);
datasheet = null;
GC.Collect();
}
}
void LoadSheetsFunction(int year, int month) //填充函数
{
string connString = @"
server = (local);
integrated security = true;
database = ExcelDatabase
"; // 连接数据库的字符串
using (conn = new SqlConnection(connString))
{
conn.Open();
LoadLifeInsuranceCompany(year, month); //填充“寿险公司”
}
}
void LoadLifeInsuranceCompany(int year, int month) //填充“寿险公司”的函数
{
foreach (Worksheet sheet in sheets)
{
if (sheet.Name == "寿险公司") //读取“寿险公司”的sheet;
{
datasheet = sheet;
}
}
SqlCommand Newcmd = new SqlCommand("select * from LifeInsuranceCompany where (year=" + year.ToString() + ")" + "and (month=" + month.ToString() + ")", conn);
SqlDataReader rdr = Newcmd.ExecuteReader();
if (!rdr.HasRows)
{
rdr.Close();
string sql = @"select * from LifeInsuranceCompany";
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
DataSet ds = new DataSet();
da.Fill(ds, "LifeInsuranceCompany");
System.Data.DataTable dt = ds.Tables["LifeInsuranceCompany"];
int[] Rowarray = new int[6] { 13, 21, 29, 37, 45, 53 };
for (int CompanyID = 1; CompanyID <= 6; CompanyID++) // 填充DataTable
{
range = datasheet.get_Range("D" + Rowarray[CompanyID - 1].ToString(), "K" + (Rowarray[CompanyID - 1]+5).ToString());
Cellarray = (System.Array)range.Value;
for (int InsuranceID = 1; InsuranceID <= 5; InsuranceID++)
{
DataRow newRow = dt.NewRow();
newRow["year"] = year;
newRow["month"] = month;
newRow["CompanyID"] = CompanyID;
newRow["InsuranceID"] = InsuranceID;
newRow["NewInsurancePremium"] = (Cellarray.GetValue(InsuranceID, 1)!= null ? Cellarray.GetValue(InsuranceID,1) : DBNull.Value);
newRow["RenewalPremium"] = (Cellarray.GetValue(InsuranceID, 3) != null ? Cellarray.GetValue(InsuranceID, 3) : DBNull.Value);
newRow["ExpenditureAndPayment"] = (Cellarray.GetValue(InsuranceID, 5) != null ? Cellarray.GetValue(InsuranceID, 5) : DBNull.Value);
newRow["GrossPremiumIncome"] = (Cellarray.GetValue(InsuranceID, 7) != null ? Cellarray.GetValue(InsuranceID, 7) : DBNull.Value);
dt.Rows.Add(newRow);
}
}
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conn)) //用SqlBulkCopy将DataTable的表批量导入到数据源
{
bulkCopy.DestinationTableName =
"LifeInsuranceCompany";
try
{
// Write from the source to the destination.
bulkCopy.WriteToServer(dt);
}
catch (Exception ex)
{
this.textBox1.Clear();
this.textBox1.Text+="数据导入失败!"+Environment.NewLine +ex;
}
}
}
else
{
this.textBox1.Clear();
this.textBox1.Text += "寿险公司" + year.ToString() + "年" + month.ToString() + "月的表已经存在,不需要再次导入!";
rdr.Close();
}
}
}
}
#4
发现一个现象,就是第一次打开的Excel表,在程序关闭前一直驻留在内存,而第二次以上打开的表调用完成后会自动回收。
#5
datatable结果也是
表1+表1+表2
表1+表1+表2
#6
LZ~~~阅读你的代码够费劲-_-
基本把你的意图理解为:
1读取EXCEL
2验证EXCEL数据
3从EXCEL获取 年,月属性
4根据年月属性从数据库中获取指定数据
5数据拼接成新的DATATABLE
6数据入库
目前看下来你的数据填充这块的业务逻辑有问题
string sql = @"select * from LifeInsuranceCompany";
这里你获取了表中所有的数据
当第二次添加时,第一次数据也被取出,然后新的数据追加在了DT的后面。
当执行BULKCOPY时就等于多加了一次数据(1)
而数据库的数据变为 1+1+2了,如果第三次添加数据时则变为 1+1+2+1+1+2+3
既然你是新填数据,这里完全没有必要从原来的表中获取数据
基本把你的意图理解为:
1读取EXCEL
2验证EXCEL数据
3从EXCEL获取 年,月属性
4根据年月属性从数据库中获取指定数据
5数据拼接成新的DATATABLE
6数据入库
目前看下来你的数据填充这块的业务逻辑有问题
string sql = @"select * from LifeInsuranceCompany";
这里你获取了表中所有的数据
当第二次添加时,第一次数据也被取出,然后新的数据追加在了DT的后面。
当执行BULKCOPY时就等于多加了一次数据(1)
而数据库的数据变为 1+1+2了,如果第三次添加数据时则变为 1+1+2+1+1+2+3
既然你是新填数据,这里完全没有必要从原来的表中获取数据
#7
我估计你这里
select * from LifeInsuranceCompany
的目的是想获取“LifeInsuranceCompany”这张表的结构(因为BULKCOPY这样要求,否则添加不了)
你完全可以通过这样的方法构建DATATABLE的结构
select * from LifeInsuranceCompany
的目的是想获取“LifeInsuranceCompany”这张表的结构(因为BULKCOPY这样要求,否则添加不了)
你完全可以通过这样的方法构建DATATABLE的结构
DataTable dt = new DataTable();
dt.Columns.Add("year", typeof(DateTime));
#8
另外给LZ一些额外的建议
1. 好好的提升一下自己代码编写的习惯。不是所有人都有耐心看完你这样的代码的...
2. 学习一下架构的知识(诸如三层架构等)。
3. 好的软件是能反复使用(或者说重用的)。
1. 好好的提升一下自己代码编写的习惯。不是所有人都有耐心看完你这样的代码的...
2. 学习一下架构的知识(诸如三层架构等)。
3. 好的软件是能反复使用(或者说重用的)。
#9
谢谢您耐心的帮助!您指出的的"select * from LifeInsuranceCompany"的确是根源所在。
您说的“好好的提升一下自己代码编写的习惯”是指我目前的代码缺乏精简吗?