我有一个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都将被正确处理掉。感谢。
答案 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废话。