实现IDisposable接口的类中,IDbCommand会被自动释放吗?

5
我有一个数据访问类的基类。这个类实现了IDisposable接口。这个基类包含IDbConnection并在构造函数中实例化它。
public class DALBase : IDisposable
{
    protected IDbConnection cn;
    public DALBase()
    {
        cn = new MySqlConnection(connString);
    }
    public void Dispose()
    {
        if (cn != null)
        {
            if (cn.State != ConnectionState.Closed)
            {
                try
                {
                    cn.Close();
                }
                catch
                {
                }
            }
            cn.Dispose();
        }
    }
}

继承自该类的类实际上访问数据库:

public class FooDAL : DALBase
{
    public int CreateFoo()
    {
        // Notice that the cmd here is not wrapped in a using or try-finally.
        IDbCommand cmd = CreateCommand("create foo with sql", cn);
        Open();
        int ident = int.Parse(cmd.ExecuteScalar().ToString());
        Close();
        cmd.Dispose();
        return ident;
    }
}

使用FooDAL的类使用using模式来确保在像这样的代码上调用Dispose:

using(FooDAL dal = new FooDAL())
{
    return dal.CreateFoo();
}

我的问题是,即使IDbCommand没有被包裹在using模式或try-finally中,这是否也确保它被正确地处理了?如果执行命令时发生异常会发生什么?
另外,为了提高性能,在CreateFoo中实例化连接是否比在基类的构造函数中更好?
感谢任何帮助。
2个回答

3

考虑到连接已经被汇集,只需在CreateFOO方法中创建MySqlConnection(使用一个using块)。

不必担心关闭它,因为它将在using块结束时自动释放/关闭。

public int CreateFoo()
{
    using (var cn = new MySqlConnection(connString))
    {
        // Notice that the cmd here is not wrapped in a using or try-finally.
        using (IDbCommand cmd = CreateCommand("create foo with sql", cn))
        {
            cn.Open();
            return int.Parse(cmd.ExecuteScalar().ToString());
        }
     }
}

顺便提一句,如果你有一个具有 IDisposable 字段的类,那么这个类也应该是 IDisposable(参见:http://msdn.microsoft.com/zh-cn/library/ms182172%28v=vs.80%29.aspx)。 - yorah

0

如果这一切都是为了效率,你可以做出的最大改变是避免在每个DbCommand上打开和关闭db连接对象。


在 .Net 中,连接是被池化的,因此当您调用 Open() 时,您实际上只会在池中第一次打开连接。从性能角度来看,“打开”连接的成本并不重要(大多数情况下)。 - yorah
除了调用Close(),我假设它是关闭db连接。您可以通过检查DbConnection的ConnectionState来避免这种情况。 - steinberg
当您在连接上调用Close或Dispose时,连接将释放回池中。(http://msdn.microsoft.com/en-us/library/8xx3tyca%28v=VS.100%29.aspx) => 这适用于 .Net 1.1。 - yorah
我实际上担心在异常情况下IDbCommand没有被正确处理。 - Brett Bim
@Brett Bim:不用担心。如果没有引用指向它,实现了IDisposable接口的类会在某个时刻被垃圾回收。如果你想要确保,可以在using() {...}块中使用IDbCommand => 这与try ... finally {}相同,所以即使出现异常情况,它也将始终在finally块中被处理。 - yorah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接