本人创建了一个程序,大致框架如下:触发button事件--->导入一张excel表,最终将excel表的数据导入sql server 2000button事件大略如下:{  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()也无济于事。请问问题出现在哪?解决办法是什么呢?

解决方案 »

  1.   

    LZ 你代码最好贴全
    从问题来看你最好跟一下 第二次BUTTON 时的 DATATABLE的内容。估计没错的话,应该是第一个BUTTON后,EXCEL 没有释放~然后第二BUTTON时 EXCEL 的SHEET发生合并了
      

  2.   

    代码比较长: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();
                }
            
            }
            
        }
    }
           
      

  3.   

    发现一个现象,就是第一次打开的Excel表,在程序关闭前一直驻留在内存,而第二次以上打开的表调用完成后会自动回收。
      

  4.   

    datatable结果也是
    表1+表1+表2
      

  5.   

    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
    既然你是新填数据,这里完全没有必要从原来的表中获取数据                           
      

  6.   

    我估计你这里select * from LifeInsuranceCompany的目的是想获取“LifeInsuranceCompany”这张表的结构(因为BULKCOPY这样要求,否则添加不了)你完全可以通过这样的方法构建DATATABLE的结构
    DataTable dt = new DataTable();
    dt.Columns.Add("year", typeof(DateTime));
      

  7.   


    谢谢您耐心的帮助!您指出的的"select * from LifeInsuranceCompany"的确是根源所在。您说的“好好的提升一下自己代码编写的习惯”是指我目前的代码缺乏精简吗?