C#win表单应用挂起

时间:2017-03-09 16:16:22

标签: c# sql visual-studio access

以下代码用于从Access DB读取并传输到SQL DB。

有谁可以告诉我为什么这段代码在运行后会挂起?

private void readWriteRefuseDay()
{
    OleDbDataReader dr;
    oCon = new OleDbConnection(oConStr);
    sqlCon = new SqlConnection(sqlConStr);
    oQuery = "SELECT UPRN, RefuseDay, RefuseWeek FROM RefuseDay";
    sqlQuery = "INSERT INTO Ref_RefuseDay (UPRN, RefuseDay, RefuseWeek) VALUES (@UPRN, @RefuseDay, @RefuseWeek)";
    oCmd = new OleDbCommand(oQuery, oCon);

    string sUPRN;
    string sRefuseDay;
    Int32 iRefuseWeek;

    try
    {
        oCon.Open();
        sqlCon.Open();
        count = 0;
        lblProcessing.Text = count.ToString();

        dr = oCmd.ExecuteReader();

        while (dr.Read())
        {
            lblProcessing.Text = "Processing: RefuseDay " + count.ToString();
            sUPRN = dr.GetString(0);
            sRefuseDay = dr.GetString(1);
            iRefuseWeek = dr.GetInt32(2);

            sqlCmd = new SqlCommand(sqlQuery, sqlCon);
            sqlCmd.Parameters.AddWithValue("@UPRN", sUPRN);
            sqlCmd.Parameters.AddWithValue("@RefuseDay", sRefuseDay);
            sqlCmd.Parameters.AddWithValue("@RefuseWeek", iRefuseWeek);
            sqlCmd.ExecuteNonQuery();

            count++;
        }

        dr.Close();

        oCon.Close();
        oCmd.Dispose();
        oCon.Dispose();

        sqlCon.Close();
        sqlCmd.Dispose();
        sqlCon.Dispose();
    }
    catch (Exception ex) { MessageBox.Show(ex.Message); }

我有一个标签,应该更改告诉我正在处理的行,但是只要我点击按钮,表格就会停止并变得无法响应。

一切正常,它只是冻结的形式。

我对所有改进代码的建议持开放态度。我注意到有人使用:

using (SqlConnection sqlCon = new SqlConnection(connectionString)) 
例如,

。从未真正理解这一点。好点吗 ?我已经看到它也用于SqlCommand对象。

任何方式都可以改进此代码,让我们听听。

提前致谢。

1 个答案:

答案 0 :(得分:2)

  1. 您应该始终对实现using的任何内容使用IDisposable语句,它确保即使在发生异常时也会释放资源。在这种情况下,它可以确保您的数据库连接已关闭。
  2. 将Ado.Net类型放在方法的范围内,而不是类。不要担心尝试重用连接对象,这几乎总是一个坏主意,大多数RDBM如Sql Server处理连接池,所以你不必这样做。
  3. 如果需要一段时间,您的屏幕似乎会挂起。最好的解决方案是使您的事件处理程序(例如按钮单击)标记为异步。签名的外观可能取决于UI(winforms,wpf,其他),但其目的是从主消息窗口卸载工作。由于没有立即清楚这是什么以及在哪里被调用,我没有更新代码以反映这一点。
  4. const string oQuery = "SELECT UPRN, RefuseDay, RefuseWeek FROM RefuseDay";
    const string sqlQuery = "INSERT INTO Ref_RefuseDay (UPRN, RefuseDay, RefuseWeek) VALUES (@UPRN, @RefuseDay, @RefuseWeek)";
    try
    {
        using(var oCon = new OleDbConnection(oConStr))
        using(var sqlCon = new SqlConnection(sqlConStr))
        using(var oCmd = new OleDbCommand(oQuery, oCon))
        {
            oCon.Open();
            sqlCon.Open();
            count = 0;
            lblProcessing.Text = count.ToString();
    
            using(var dr = oCmd.ExecuteReader())
            {
                while (dr.Read())
                {
                    lblProcessing.Text = "Processing: RefuseDay " + count.ToString();
                    var sUPRN = dr.GetString(0);
                    var sRefuseDay = dr.GetString(1);
                    var iRefuseWeek = dr.GetInt32(2);
    
                    using(var sqlCmd = new SqlCommand(sqlQuery, sqlCon))
                    {
                       sqlCmd.Parameters.AddWithValue("@UPRN", sUPRN);
                       sqlCmd.Parameters.AddWithValue("@RefuseDay", sRefuseDay);
                       sqlCmd.Parameters.AddWithValue("@RefuseWeek", iRefuseWeek);
                       sqlCmd.ExecuteNonQuery();
                    }
                    count++;
                }
            }
        }
    }
    catch (Exception ex) { 
      MessageBox.Show(ex.Message); 
    }
    

    使用Task编辑和async / await

    为了缓存冻结窗口,您可以利用ado.net类型提供的几种异步方法。当遇到await时与async / await一起使用时,执行被挂起并且控制返回到主消息窗口。这是相同的代码,但已更新,以便它利用异步方法。它还说明了如何通过按钮单击方法调用它。

    private async void button_Click(object sender, EventArgs e)
    {
        await readWriteRefuseDayAsync();
    }
    
    private async Task readWriteRefuseDayAsync() {
      const string oQuery = "SELECT UPRN, RefuseDay, RefuseWeek FROM RefuseDay";
      const string sqlQuery = "INSERT INTO Ref_RefuseDay (UPRN, RefuseDay, RefuseWeek) VALUES (@UPRN, @RefuseDay, @RefuseWeek)";
      try {
        using(var oCon = new OleDbConnection(oConStr))
        using(var sqlCon = new SqlConnection(sqlConStr))
        using(var oCmd = new OleDbCommand(oQuery, oCon))
        {
            await oCon.OpenAsync();
            await sqlCon.OpenAsync();
            count = 0;
            lblProcessing.Text = count.ToString();
    
            using(var dr = await oCmd.ExecuteReaderAsync())
            {
                while (await dr.ReadAsync())
                {
                    lblProcessing.Text = "Processing: RefuseDay " + count.ToString();
    
                    var sUPRN = dr.GetString(0);
                    var sRefuseDay = dr.GetString(1);
                    var iRefuseWeek = dr.GetInt32(2);
    
                    using(var sqlCmd = new SqlCommand(sqlQuery, sqlCon))
                    {
                       sqlCmd.Parameters.AddWithValue("@UPRN", sUPRN);
                       sqlCmd.Parameters.AddWithValue("@RefuseDay", sRefuseDay);
                       sqlCmd.Parameters.AddWithValue("@RefuseWeek", iRefuseWeek);
                       await sqlCmd.ExecuteNonQueryAsync();
                    }
                    count++;
                }
            }
        }
      }
      catch (Exception ex) {
        MessageBox.Show(ex.Message); 
      }
    }