Зачем нужно реализовывать шаблон Dispose в UnitOfWork EF?

Учебник Microsoft http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application советует реализовать шаблон удаления, например:

private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    context.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

Почему я должен это делать, почему я не могу просто избавиться от контекста и достаточно, что произойдет, если я буду использовать только:

context.Dispose()

Какие цели реализации шаблона утилизации Microsoft?


person testCoder    schedule 07.10.2012    source источник
comment
msdn.microsoft.com/en-us/library /b1yfkh5e(v=vs.100).aspx   -  person Pawel    schedule 08.10.2012


Ответы (2)


Вы можете просто использовать ...

    public void Dispose() // IDisposable implementation
    {
        context.Dispose();
    }

... без виртуальной Dispose перегрузки и без частного disposed флага, потому что

  • сам контекст проверяет, был ли уже вызван Dispose, поэтому при втором вызове ничего не происходит и исключение не генерируется
  • класс контекста имеет свой собственный финализатор, который гарантирует, что соединение с базой данных будет освобождено при сборке мусора, если вы не вызывали Dispose явно

Последний пункт, кстати, не означает, что вам вообще не нужно вызывать context.Dispose(), потому что момент времени, когда сборщик мусора завершит контекст, является неопределенным, и он может быть позже, чем момент, когда вы создали новый экземпляр контекста и использовать его, возможно, с теми же объектами, что может вызвать некоторые проблемы. Итак: всегда удаляйте контекст явно или блоком using.

Я также сомневаюсь, что GC.SuppressFinalize(this); имеет здесь какой-либо эффект, потому что у вас нет финализатора ни в вашем классе, ни в базовом классе, поэтому нечего подавлять.

На мой взгляд, шаблон в вашем примере - это фрагмент (в котором отсутствует реализация финализатора / деструктора), и это может быть полезно, если вам приходится иметь дело со своими собственными неуправляемыми ресурсами в вашем классе. Но для вашего класса UnitOfWork это не обязательно. Неуправляемый ресурс (соединение с базой данных) управляется контекстом, и вам нужно только делегировать ему работу, вызвав context.Dispose().

person Slauma    schedule 08.10.2012

Клиентский код должен взаимодействовать только с репозиторием. Репозиторий скрывает детали реализации (такие как использование DBContext, EF и любой другой бэкэнд, который вы используете) от вызывающего кода, что является одной из основных целей шаблона репозитория.

Вот почему вызывающий код репозитория не может и не должен вызывать context.dispose. Он не должен даже знать о контексте. Он знает только о репозитории и вызывает его метод Dispose (явно или предпочтительно с помощью using ключевого слова).

person kabaros    schedule 07.10.2012