2017-01-25 5 views
1

Меня смущает следующий код и область применения оператора и его удаление объекта.Объем элементов внутри оператора using

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

В этом коде, что происходит после того, с помощью выполнения блока будет ли DbFactory получает утилизировать?
Какова будет область действия переменной repo, используемой внутри оператора using?
DbFactory Используется Repository и имеет переменную-член, которая будет содержать 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 по-прежнему будет ссылаться на него, но он, вероятно, будет бесполезен после того, как завод был удален. Поэтому, если вы вызываете repo.Get(...)после, заявление using, вы, вероятно, увидите исключение, в зависимости от того, что этот код действительно делает с фабрикой, и как ведет себя работающий завод. Опять же, Утилизация не сбор мусора. Это просто вызов метода Dispose - CLR не заботится об этом каким-либо особым образом.

+0

Отредактированный вопрос. Я смущен тем, что переменная repo хранит утилизацию DbContext после оператора using или DbContext, размещенного сразу после использования оператора, и репо будет ждать gc? – Sreejith

+1

Dispose не имеет ничего общего с GarbageCollector, поскольку метод Dispose не является деструктором, и поэтому GC не будет вызываться, только когда метод Dispose. – Vir

+0

@jonskeet Отличный момент, я ищу, что время удаления. – Sreejith

3

Будет ли утилизирован DbFactory?

Да.

Какова будет область переменной репо, используемая внутри оператора using?

Объем 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 не будет wanish (ссылка на него будет keept в экземпляре репозитория, она будет находиться в состоянии Disposed/Closed. Depe при реализации DbFactory, который, вероятно, сломает ваш код.

Вы не предоставили полный код и что он должен делать, но я думаю, что вы должны идти в этом направлении:

  1. Реализовать 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); 
    } 
}