2017-01-25 43 views
1

我很困惑下面的代码和使用语句及其对象处置的范围。使用语句内部成员的范围

using(DbFactory db = new DbFactory()) 
{ 
    Repository repo = new Repository<someobject>(db); 
    result = repo.Get(somecondition); 
} 

在这段代码的使用块执行后会发生什么将DbFactory得到处理?
在using语句中使用的变量的范围是repo
DbFactoryRepository使用,它有一个成员变量,它将容纳DbFactory。 那么这会持有DbFactory的处置吗?

EDIT1:

Repository repo; 
ResultObject result; 
using(DbFactory db = new DbFactory()) 
{ 
    repo = new Repository<someobject>(db); 
    result = repo.Get(somecondition); 
} 

public class Repository 
{ 
    private _dbFactory; 

    public Repository(DbFactory dbFactory) 
    { 
     _dbFactory = dbFactory; 
    } 
} 

现在将DbFactory被设置在使用后声明?

回答

8

repo变量的范围(在第一种情况下)是using声明。你不能在using声明之外引用它,因为它在那里声明。

我们无法辨别result变量的范围,因为您尚未显示其声明,但它至少“大于using声明”。

更有意思的是result的值所指的对象在DbFactory处置后的可用性如何。这是特定于实现的,基本上......我期望如果访问任何result属性需要进一步的数据库查询(例如,获取由外键引用的对象),那么它将失败,但是已获取的任何东西都应该没问题。

至于处置时间 - DbFactory将在using声明的末尾处置。这与垃圾收集完全分开,大概Repository对象仍然会提及它 - 但是在工厂处理后它可能没有用处。因此,如果您在using声明后致电repo.Get(...),您可能会看到一个异常,具体取决于代码实际在工厂中执行的操作,以及处置的工厂的行为方式。再次,处置不是垃圾回收。它只是调用Dispose方法 - CLR不以任何特殊方式关心这一点。

+0

编辑该问题。我很困惑,repo变量在using语句或DbContext在使用语句之后处理并且回购将等待gc之后是否持有对DbContext的处置? – Sreejith

+1

Dispose与GarbageCollector无关,因为Dispose方法不是析构函数,所以不会在Dispose方法时调用GC。 – Vir

+0

@jonskeet伟大的一点,我正在寻找处置的时机。 – Sreejith

3

DbFactory会被丢弃吗?

是的。

在using语句中使用的repo变量的作用域是什么?

repo范围是,它是包含在块的,所以对花括号(“{”,“}”),它的包在在这种情况下,它发生在与所述主体一致你的using声明,是的。

+0

所以'repo'变量将不会举行处置'DbFactory'正确的? – Sreejith

+0

@Rebornx它保存在同一个对象上,所以如果该对象被放置,并且存储库尝试使用某个在处理对象上不受支持的操作,那么它将不起作用。 – Servy

0

如果回购也是一次性的,你可能想出售它也为exampe:

using(DbFactory db = new DbFactory()) 
using(Repository repo = new Repository<someobject>(db)) 
{ 
    result = repo.Get(somecondition); 
} 
+0

我知道。但是,将仓库作为一次性使用是否是一种好的模式? – Sreejith

0

此:

Repository repo; 
ResultObject result; 
using(DbFactory db = new DbFactory()) 
{ 
    repo = new Repository<someobject>(db); 
    result = repo.Get(somecondition); 
} 

是相同的,因为这一个:

Repository repo; 
ResultObject result; 
{ 
    DbFactory db = new DbFactory() 
    repo = new Repository<someobject>(db); 
    result = repo.Get(somecondition); 
    db.Dispose(); 
} 

所以尽管db对象本身不会变幻(引用它将会保存在Repository实例中,它将处于Disposed/Closed状态。寻找可能会破坏你的代码的DbFactory的实现。

你没有提供完整的代码,它应该做的,但我认为你应该往这个方向:

  1. 在Repository对象实现IDisposable和里面配置DbFactory还有:

    public class Repository : IDisposable 
    { 
        private _dbFactory; 
    
        public Repository(DbFactory dbFactory) 
        { 
         _dbFactory = dbFactory; 
        } 
    
        public void Dispose() 
        { 
         _dbFactory.Dispose(); 
        } 
    } 
    
  2. 现在使用它像这样:

    ResultObject result; 
    using (Repository repo = new Repository(new DbFactory()) 
    { 
        result = repo.Get(somecondition); 
    } 
    

或者用使用嵌套:

using (DbFactory db = new DbFactory()) 
{ 
    using(Repository repo = new Repository(db)) 
    { 
     result = repo.Get(somecondition); 
    } 
}