.NET IDisposable Pattern 意味着如果您编写终结器并实现IDisposable,则终结器需要显式调用Dispose.这是合乎逻辑的,而且在极少数情况下我总是会做终结器的保证.
但是,如果我这样做会发生什么:
class Foo : IDisposable
{
public void Dispose(){ CloseSomeHandle(); }
}
Run Code Online (Sandbox Code Playgroud)
并且不要实现终结器或任何东西.框架会为我调用Dispose方法吗?
是的,我意识到这听起来很愚蠢,而且所有的逻辑都暗示它不会,但我总是有两件事让我不确定.
几年前有人曾告诉我,事实上它会这样做,而且那个人有"非常了解他们的东西"的良好记录.
编译器/框架根据您实现的接口(例如:foreach,扩展方法,基于属性的序列化等)执行其他"神奇"操作,因此这也可能是"魔术".
虽然我已经阅读了很多关于它的内容,并且有很多暗示的内容,但我从来没有能够找到这个问题的肯定是或否答案.
假设某人(除了我)编写以下代码并将其编译为程序集:
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
using (var transaction = conn.BeginTransaction())
{
/* Update something in the database */
/* Then call any registered OnUpdate handlers */
InvokeOnUpdate(conn);
transaction.Commit();
}
}
Run Code Online (Sandbox Code Playgroud)
对InvokeOnUpdate(IDbConnection conn)的调用调用了一个我可以实现并注册的事件处理程序.因此,在这个处理程序中,我将引用IDbConnection对象,但我不会引用挂起的事务.我有什么办法可以控制交易吗?在我的OnUpdate处理程序中,我想执行类似于以下内容的操作:
private void MyOnUpdateHandler(IDbConnection conn)
{
var cmd = conn.CreateCommand();
cmd.CommandText = someSQLString;
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
}
Run Code Online (Sandbox Code Playgroud)
但是,对cmd.ExecuteNonQuery()的调用会抛出InvalidOperationException,抱怨它
"当分配给命令的连接处于挂起的本地事务中时,ExecuteNonQuery要求命令具有事务.该命令的Transaction属性尚未初始化".
我可以以任何方式使用挂起的事务登记我的SqlCommand cmd吗?我可以从IDbConnection对象中检索对待处理事务的引用(如果需要,我很乐意使用反射)?
我已经"继承"了一个C#方法,该方法创建了一个ADO.NET SqlCommand对象,并循环遍历要保存到数据库的项目列表(SQL Server 2005).
现在,使用传统的SqlConnection/SqlCommand方法,为了确保一切正常,两个步骤(删除旧条目,然后插入新条目)被包装到ADO.NET SqlTransaction中.
using (SqlConnection _con = new SqlConnection(_connectionString))
{
using (SqlTransaction _tran = _con.BeginTransaction())
{
try
{
SqlCommand _deleteOld = new SqlCommand(......., _con);
_deleteOld.Transaction = _tran;
_deleteOld.Parameters.AddWithValue("@ID", 5);
_con.Open();
_deleteOld.ExecuteNonQuery();
SqlCommand _insertCmd = new SqlCommand(......, _con);
_insertCmd.Transaction = _tran;
// add parameters to _insertCmd
foreach (Item item in listOfItem)
{
_insertCmd.ExecuteNonQuery();
}
_tran.Commit();
_con.Close();
}
catch (Exception ex)
{
// log exception
_tran.Rollback();
throw;
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我最近一直在阅读很多关于.NET TransactionScope类的内容,我想知道,这里首选的方法是什么?通过切换使用,我可以获得任何东西(可读性,速度,可靠性)
using (TransactionScope _scope = new TransactionScope())
{ …Run Code Online (Sandbox Code Playgroud) 我有以下使用SqlTransaction的代码.我已经在catch中调用dispose并最终阻止了..但是在调用Dispose()之前我还没有检查它是否已经被释放.在调用Dispose()之前,我们如何检查SqlTransaction是否已被释放?
我已经引用了MSDN:SqlTransaction.Dispose方法.但这并不包括我的问题.
另请参阅http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqltransaction.dispose(v=vs.100).aspx
注意:我已经知道它TransactionScope有优势了SqlTransaction.但我试图了解SqlTransaction的配置.
码
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlTransaction transaction = null;
try
{
transaction = connection.BeginTransaction();
sessionID = GetSessionIDForAssociate(connection, empID, transaction);
//Other code
//Commit
transaction.Commit();
}
catch
{
//Rollback
if (transaction != null)
{
transaction.Rollback();
transaction.Dispose();
}
//Throw exception
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)