【问题标题】:Would this code waste resources?这段代码会浪费资源吗?
【发布时间】:2016-06-27 18:05:48
【问题描述】:

我正在使用 gridview 选择多条记录,然后循环播放它以单独将每个记录 ID 发送到数据库并更新它,但我发现它不是很好的实现方法,因为它每次都会打开和关闭连接,所以什么是好方法吗?

foreach (GridViewRow r in grdViewLastHearingDates.Rows)
    {
        int CaseHearingID = Convert.ToInt32(r.Cells[0].Text);
        CheckBox chkBox = r.FindControl("chkBoxIsConveyed") as CheckBox;

        TextBox txtboxConvenienceRemarks = r.FindControl("txtBoxConvenienceRemarks") as TextBox;
        string ConvenienceRemarks = txtboxConvenienceRemarks.Text;

        MngCaseHearings.UpdateCasesIsConveyed(CaseHearingID, ConvenienceRemarks, chkBox.Checked);
    }

MngCaseHearings.UpdateCasesIsConveyed 每次都会发送并执行此代码以更新每个 ID。请查看并提出建议

    public Boolean UpdateCasesIsConveyed(int CaseHearingID, string ConvenienceRemarks, bool IsConveyed)
    {

        try
        {
            SqlCommand SqlCom = new SqlCommand("UpdateCasesIsConveyed", DatabaseConnection.OpenConnection());
            SqlCom.CommandType = CommandType.StoredProcedure;
            SqlCom.Parameters.AddWithValue("@pk_CaseHearings_ID ", CaseHearingID);
            SqlCom.Parameters.AddWithValue("@IsConveyed", IsConveyed);
            SqlCom.Parameters.AddWithValue("@ConvenienceRemarks", ConvenienceRemarks);

            SqlParameter SqlParamReturnStatus = new SqlParameter("@ReturnStatus", SqlDbType.Bit);
            SqlCom.Parameters.Add(SqlParamReturnStatus);
            SqlParamReturnStatus.Direction = ParameterDirection.Output;

            SqlParameter SqlParamReturnStatusMessage = new SqlParameter("@ReturnStatusMessage", SqlDbType.VarChar, -1);
            SqlCom.Parameters.Add(SqlParamReturnStatusMessage);
            SqlParamReturnStatusMessage.Direction = ParameterDirection.Output;

            SqlCom.ExecuteNonQuery();

            string ReturnStatusMessage = Convert.ToString(SqlParamReturnStatusMessage);
            Boolean ReturnStatus = Convert.ToBoolean(SqlParamReturnStatus.Value);

            return ReturnStatus;
        }
 catch (Exception)
            {

                throw;
            }

            finally 
            {
                DatabaseConnection.CloseConnection();
            }

这会浪费资源,所以如果有什么好的解决方法?

【问题讨论】:

  • 什么是DatabaseConnection
  • 调用静态方法打开数据库连接的类对象

标签: c# asp.net c#-4.0 gridview


【解决方案1】:

由于SqlConnectionSqlCommand 对象都实现了IDisposable,因此您可能应该在完成后将它们丢弃。最简单的方法是通过using 语句:

using (var conn = DatabaseConnection.OpenConnection())
using (var SqlCom = new SqlCommand("UpdateCasesIsConveyed", conn))
{
    // setup and execute the SP, can return from in here
}

这将确保对象使用的资源在您完成后立即正确关闭。虽然这不是绝对必要的 - 当垃圾收集器销毁对象时将调用 Dispose 方法 - 它会确保您不会在必要时保持打开数据库对象。根据调用的频率,您最终可能会遇到 SQL 服务器上的资源短缺、句柄使用过多等问题。

一般来说,任何实现IDisposable 的东西都应该尽快处理掉。


(对不起,错过了问题的循环部分)

这种类型的创建/销毁循环对于单个操作来说很好,但在用于更新大量记录时会变得很浪费。我会将循环放在代码中间,而不是从外部重复调用此代码。

我将创建一个包含 SP 参数的记录类或结构,并将该记录类的 IEnumerable 传递给您的更新方法。这样,您可以进行一次设置,处理所有更新,然后在进行所有更改后拆除数据库对象。如果其中一条记录失败,您也可以将其全部撤消。

类似:

public struct UpdateCaseConveyanceRec
{
    public int CaseHearingID;
    public string ConvenienceRemarks;
    public bool IsConveyed;
}

public bool UpdateCasesIsConveyed(IEnumerable<UpdateCaseConveyanceRec> uopdates)
{
    using (SqlConnection conn = DatabaseConnection.OpenConnection())
    using (SqlCommand cmd = new SqlCommand("UpdateCasesIsConveyed", conn))
    using (SqlTransaction trans = conn.BeginTransaction("UpdateCasesIsConveyed"))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        var pID = cmd.Parameters.Add("@pk_CaseHearings_ID", SqlDbType.Int);
        var pConveyed = cmd.Parameters.Add("@IsConveyed", SqlDbType.Bit);
        var pRemarks = cmd.Parameters.Add("@ConvenienceRemarks", SqlDbType.VarChar, -1);

        var retStatus = cmd.Parameters.Add("@ReturnStatus", SqlDbType.Bit);
        retStatus.Direction = ParameterDirection.Output;

        var retStatusMsg = cmd.Parameters.Add("@ReturnStatusMessage", SqlDbType.VarChar, -1);
        retStatusMsg.Direction = ParameterDirection.Output;

        try
        {
            foreach (var row in updates)
            {
                pID.Value = row.CaseHearingID;
                pConveyed.Value = row.IsConveyed;
                pRemarks.Value = row.ConvenienceRemarks;

                cmd.ExecuteNonQuery();

                if (!Convert.ToBoolean(retStatus))
                {
                    trans.Rollback();
                    return false;
                }
            }

            trans.Commit();
        }
        catch ()
        {
            trans.Rollback();
            throw;
        }

        return true;
    }
}

然后您可以使用 LINQ to Objects 查询来提供它:

var source = 
    from r in grdViewLastHearingDates.Rows.OfType<GridViewRow>()
    select new UpdateCaseConveyanceRec
    {
        CaseHearingID = Convert.ToInt32(r.Cells[0].Text),
        ConvenienceRemarks = (r.FindControl("txtBoxConvenienceRemarks") as TextBox).Text;
        IsConveyed = (r.FindControl("chkBoxIsConveyed") as CheckBox).Checked
    };

bool updated = UpdateCasesIsConveyed(source);

【讨论】:

  • 看到我的代码抛出 gridview 并将每一行发送到数据库,然后以更新查询为目标。所以在这种情况下我应该怎么做?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-09
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
  • 2012-02-15
相关资源
最近更新 更多