将数据批量复制到表时文件锁定的原因

时间:2016-02-09 08:13:04

标签: c#

我浏览.MDF文件并将其数据上传到SQL Server数据库表。

我的应用程序有一个浏览按钮,用于选择文件,然后上传按钮以执行批量复制操作。

但是在我使用.mdf选择OpenFileDialog文件的第二次尝试中,它会抛出一个错误,说该文件已被使用。

private void labelBrowse_Click(object sender, System.EventArgs e)
{
    try
    {
        System.Windows.Forms.OpenFileDialog openFileDialog = new System.Windows.Forms.OpenFileDialog();
        openFileDialog.Title = "Select the MDF file to upload";
        openFileDialog.Filter = "Data|*.mdf";
        if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            textBoxMdfFilePath.Text = openFileDialog.FileName.ToString();
    }
    catch (System.Exception ex)
    {
        System.Windows.Forms.MessageBox.Show(ex.ToString());
    }
}

private void labelUpload_Click(object sender, System.EventArgs e)
{
    if (string.IsNullOrEmpty(textBoxMdfFilePath.Text.Trim()))
    {
        System.Windows.Forms.MessageBox.Show("Please select a MDF file to upload");
        textBoxMdfFilePath.Text = "";
        return;
    }
    else if (!(System.IO.Path.GetFileName(textBoxMdfFilePath.Text).Equals("Audit.mdf", System.StringComparison.InvariantCultureIgnoreCase)) && !(System.IO.Path.GetFileName(textBoxMdfFilePath.Text).Equals("IPAUDIT.mdf", System.StringComparison.InvariantCultureIgnoreCase)))
    {
        System.Windows.Forms.MessageBox.Show("Please select the correct MDF file to upload");
        textBoxMdfFilePath.Text = "";
        return;
    }
    else
    {
        uploadToServer(textBoxMdfFilePath.Text);
    }
}

void uploadToServer(string path)
{
    try
    {
        string mdfConnectionString = @"data source=172.16.2.136;attachdbfilename=" + path + ";" + "integrated security=true;" + "connect timeout=30;" + "user instance=true";
        System.Data.SqlClient.SqlConnection sqlconnection = new System.Data.SqlClient.SqlConnection(mdfConnectionString);

        if (System.IO.Path.GetFileName(path).Equals("Audit.mdf", System.StringComparison.InvariantCultureIgnoreCase))
        {
            System.Data.SqlClient.SqlCommand sqlcommand = new System.Data.SqlClient.SqlCommand("select * from [D-Audit]", sqlconnection);

            sqlconnection.Open();
            System.Data.DataTable dataTable = new System.Data.DataTable();
            dataTable.Load(sqlcommand.ExecuteReader());
            sqlconnection.Close();

            System.Data.SqlClient.SqlBulkCopy sqlbulkcopy = new System.Data.SqlClient.SqlBulkCopy(System.Configuration.ConfigurationManager.ConnectionStrings["myServerAudit"].ConnectionString);
            sqlbulkcopy.DestinationTableName = "[dbo].[D-Audit]";
            sqlbulkcopy.BulkCopyTimeout = 1800;
            sqlbulkcopy.WriteToServer(dataTable);
            sqlbulkcopy.Close();

            System.Windows.Forms.MessageBox.Show("Data Uploaded Successfully");
            textBoxMdfFilePath.Text = "";
        }
        else if (System.IO.Path.GetFileName(path).Equals("IPAudit.mdf", System.StringComparison.InvariantCultureIgnoreCase))
        {
            System.Data.SqlClient.SqlCommand sqlcommand = new System.Data.SqlClient.SqlCommand("select * from IpTransaction", sqlconnection);

            sqlconnection.Open();
            System.Data.DataTable dataTable = new System.Data.DataTable();
            dataTable.Load(sqlcommand.ExecuteReader());
            sqlconnection.Close();

            System.Data.SqlClient.SqlBulkCopy sqlbulkcopy = new System.Data.SqlClient.SqlBulkCopy(System.Configuration.ConfigurationManager.ConnectionStrings["myServerIPAudit"].ConnectionString);
            sqlbulkcopy.DestinationTableName = "IpTransaction";
            sqlbulkcopy.BulkCopyTimeout = 1800;
            sqlbulkcopy.WriteToServer(dataTable);
            sqlbulkcopy.Close();

            System.Windows.Forms.MessageBox.Show("Data Uploaded Successfully");
            textBoxMdfFilePath.Text = "";
        }

        sqlconnection.Close();

    }
    catch (System.Exception ex)
    {
        System.Windows.Forms.MessageBox.Show(ex.Message);
    }
}

2 个答案:

答案 0 :(得分:0)

当你说"第二次尝试"时,我假设它适用于第一次点击而不是后续点击。如果是这种情况,那么连接可能没有被释放并且仍然保持在DB上。在离开事件处理程序之前,您可以尝试在代码中处理所有IDisposable。

答案 1 :(得分:0)

您需要在连接字符串中设置Pooling = False

这里发生的事情是SQLBulkcopy正在创建自己的SQLConnection对象,其中包含您提供的连接字符串。默认情况下,连接池是真的...所以当SQLBulkCopy创建sqlconnection对象时,它会被添加到连接池中,并且即使在关闭应用程序之后连接仍然存在。这种机制是为了优化性能,但在你的情况下,这就是导致问题的原因...所以在你的连接中添加Pooling = false应该可以解决你的问题

ConnectionString  = "Data Source=MYSQL;Initial Catalog=MyDatabase;Integrated Security=true;Pooling=false"

添加信息

最好将SQLBulkCopy包装为Using block,因为它类型为IDisposable,因此您无需显式调用close。

相关问题