将SQLCommand作为参数传递是否可以?

时间:2010-04-23 13:49:39

标签: c# sql

我有一个Business Layer,它将Conn字符串和SQLCommand传递给数据层,如此

    public void PopulateLocalData()
    {
       System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
       cmd.CommandType = System.Data.CommandType.StoredProcedure;
       cmd.CommandText = "usp_PopulateServiceSurveyLocal";
       DataLayer.DataProvider.ExecSQL(ConnString, cmd);
    }

然后DataLayer只执行sql

        public static int ExecSQL(string sqlConnString, System.Data.SqlClient.SqlCommand cmd)
    { 
        int rowsAffected;
        using (SqlConnection conn = new SqlConnection(sqlConnString))
        {
            conn.Open();
            cmd.Connection = conn;
            rowsAffected = cmd.ExecuteNonQuery();
            cmd.Dispose();
        }
        return rowsAffected;
    }

我可以将SQLCommand作为这样的参数传递,还是有更好的接受方式。 我担心的一个问题是,如果在执行查询时发生错误,cmd.dispose行将永远不会执行。这是否意味着它会继续耗尽永远不会释放的内存?

更新

根据Eric的建议,我更明确划分了业务层和数据层,因此业务层中的方法看起来像这样

    public void PopulateLocalData()
    {
        DataLayer Data = new DataLayer(this.ConnString);
        Data.UpdateLocalData();
    }

和DataLayer中调用的方法如下所示。

        public void UpdateLocalData()
    {
        using (SqlConnection conn = new SqlConnection(this.ConnString))
        using(SqlCommand cmd = new SqlCommand())
        {
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.CommandText = "usp_PopulateServiceSurveyLocal";
            conn.Open();
            cmd.Connection = conn;
            cmd.ExecuteNonQuery();
        }
    }

这样很清楚,SQLCommand和SQLConnection都将被正确处理掉。感谢。

4 个答案:

答案 0 :(得分:6)

理想情况下,您的业务层不应该了解数据层的实施细节。因此,无论是使用SqlCommand对象还是使用NHibernate等实现数据层,都应该与业务层无关。这使得理论上讲它很容易“移出”你的数据层并用另一个替换它。

总结:在我看来,将SqlCommand从业务层传递到数据层并不是一种好的做法。

关于Dispose():如果您使用的是using语句(如using(SqlConnection ...)),则会在using语句的末尾自动调用Dispose()方法。您不必手动执行此操作。

答案 1 :(得分:0)

为什么不将其更改为:

public static int ExecProcedure(string sqlConnString, string procedureName)
{
    using (var cmd = new System.Data.SqlClient.SqlCommand())
    {
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.CommandText = procedureName;
        int rowsAffected;
        using (SqlConnection conn = new SqlConnection(sqlConnString))
        {
            conn.Open();
            cmd.Connection = conn;
            return cmd.ExecuteNonQuery();
        }
    }
}

您想要其他参数吗?创建重载,重构。在共同功能中共享最多代码。在任何地方创建new System.Data.SqlClient.SqlCommand()都是错误的做法。

答案 2 :(得分:0)

创建Command的人应该负责处理它。最简单的方法是从cmd.Dispose移除对ExecSql的调用,而是像这样调用您的函数:

public void PopulateLocalData() 
{ 
   using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand())
   {
       cmd.CommandType = System.Data.CommandType.StoredProcedure; 
       cmd.CommandText = "usp_PopulateServiceSurveyLocal"; 
       DataLayer.DataProvider.ExecSQL(ConnString, cmd);
   }
} 
  

我担心的一个问题是,如果在执行查询时发生错误,cmd.dispose行将永远不会执行。这是否意味着它会继续耗尽永远不会释放的内存?

巧合的是,SqlClient.SqlCommand不需要处理。但是,这是一个你不应该依赖的实现细节 - 一般规则仍然是:如果它实现IDisposable,则将其处理掉。(SqlCeClient.SqlCeCommand,例如, 需要处理...)

答案 3 :(得分:-1)

首先,您可以将其更改为:

public static int ExecSQL(string sqlConnString, System.Data.SqlClient.SqlCommand cmd)
{ 
    int rowsAffected;
    try
    {
        using (SqlConnection conn = new SqlConnection(sqlConnString))
        {
            conn.Open();
            cmd.Connection = conn;
            rowsAffected = cmd.ExecuteNonQuery();
        }
    } finally {
        cmd.Dispose();
    }
    return rowsAffected;
}

此外,我通常会比您更多地分离业务和数据层。我的业务层将在数据层中调用方法“GetLocalSurvey”,它将处理所有SQL废话。