Dan*_*n H 5 .net c# using-statement
我有两个问题.
1)您是否应始终在连接上使用using语句?那么,我会在连接上使用它,然后在连接中的读者上使用另一个?所以我将使用两个using语句.
2)假设您在连接上使用using语句,并且还在连接上返回读取器.所以你有两个使用语句.它会创建两个Try {} Finally {}块还是只创建一个?
谢谢!
这里要小心.您应该始终在任何实现IDisposable的本地对象上使用using语句.这不仅包括连接和读者,还包括命令.但有时候,使用语句的确切位置可能会很棘手.如果你不小心它可能会导致问题.例如,在随后的代码中,using语句将在您使用它之前关闭您的阅读器:
DataReader MyQuery()
{
string sql="some query";
using (var cn = new SqlConnection("connection string"))
using (var cmd = new SqlCommand(sql, cn))
{
cn.Open();
using (var rdr = cmd.ExecuteReader())
{
return rdr;
}
}
}
Run Code Online (Sandbox Code Playgroud)
相反,您有四种选择.一种是等到创建使用块,直到你调用该函数:
DataReader MyQuery()
{
string sql="some query";
using (var cn = new SqlConnection("connection string"))
using (var cmd = new SqlCommand(sql, cn))
{
cn.Open();
return cmd.ExecuteReader();
}
}
using (var rdr = MyQuery())
{
while (rdr.Read())
{
//...
}
}
Run Code Online (Sandbox Code Playgroud)
当然,你仍然需要小心你的连接,这意味着记住在你使用该功能的任何地方编写一个使用块.
选项二只是处理方法本身的查询结果,但这会破坏数据层与程序其余部分的分离.第三个选项是让你的MyQuery()函数接受一个Action类型的参数,你可以在while(rdr.Read())循环中调用它,但这只是尴尬.
我通常更喜欢选项四:将数据读取器转换为IEnumerable,如下所示:
IEnumerable<IDataRecord> MyQuery()
{
string sql="some query";
using (var cn = new SqlConnection("connection string"))
using (var cmd = new SqlCommand(sql, cn))
{
cn.Open();
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read())
yield return rdr;
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在一切都将正确关闭,处理它的代码都在一个地方.您还可以获得一个很好的奖励:您的查询结果将适用于任何linq运算符.
最后,我正在玩的新内容,以便下次我构建一个将IEnumerable与传递委托参数相结合的全新项目:
//part of the data layer
private static IEnumerable<IDataRecord> Retrieve(string sql, Action<SqlParameterCollection> addParameters)
{
//DL.ConnectionString is a private static property in the data layer
// depending on the project needs, it can be implementing to read from a config file or elsewhere
using (var cn = new SqlConnection(DL.ConnectionString))
using (var cmd = new SqlCommand(sql, cn))
{
addParameters(cmd.Parameters);
cn.Open();
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read())
yield return rdr;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后我将在数据层中使用它,如下所示:
public IEnumerable<IDataRecord> GetFooChildrenByParentID(int ParentID)
{
//I could easily use a stored procedure name instead, and provide overloads for commandtypes.
return Retrieve(
"SELECT c.*
FROM [ParentTable] p
INNER JOIN [ChildTable] c ON c.ParentID = f.ID
WHERE f.ID= @ParentID", p =>
{
p.Add("@ParentID", SqlDbType.Int).Value = ParentID;
}
);
}
Run Code Online (Sandbox Code Playgroud)
1)您是否应始终在连接上使用using语句?那么,我会在连接上使用它,然后在连接中的读者上使用另一个?所以我将使用两个using语句.
是的,因为他们实施了IDisposable.并且不要忘记using关于命令的声明:
using (DbConnection connection = GetConnection())
using (DbCommand command = connection.CreateCommand())
{
command.CommandText = "SELECT FOO, BAR FROM BAZ";
connection.Open();
using (DbDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
....
}
}
}
Run Code Online (Sandbox Code Playgroud)
2)假设您在连接上使用using语句,并且还在连接上返回读取器.所以你有两个使用语句.它会创建两个Try {} Finally {}块还是只创建一个?
每个using语句都会创建自己的try/finally块
| 归档时间: |
|
| 查看次数: |
591 次 |
| 最近记录: |