Обеспечение IDisposable вызова на объектах, созданных в контроллере и переданных для просмотра - PullRequest
3 голосов
/ 03 сентября 2010

Я всегда знал, что все хорошие программисты вызывают Dispose для любого объекта, который реализует IDisposable, в данном случае класс ObjectContext в EF.

Я новичок в asp.net mvc, так что это может быть вопрос noob, но здесь идет ...

    public ActionResult Index()
    {
        using (var db = new MyObjectContext())
        {
            return View(db.People);
        }
    }

Если я запускаю этот код, я получаю ошибку (ObjectDisposedException), потому чтоObjectContext был удален до того, как представление выполнит действие с данными.Есть ли здесь другой подход?Как я могу гарантировать, что мои объекты будут уничтожены как можно скорее?

Ответы [ 2 ]

9 голосов
/ 03 сентября 2010

Переопределите метод Controller.Dispose () и избавьтесь от вашего объекта там:

private IDisposable _objectToDispose;

public ActionResult Index() {
  var db = new MyObjectContext();
  _objectToDispose = db;
  return View(db.People);  
}

protected override void Dispose(bool disposing) {
  if (disposing && _objectToDispose != null) {
    _objectToDispose.Dispose();
  }
  base.Dispose(disposing);
}

Среда MVC автоматически вызовет Controller.Dispose () в конце запроса.

3 голосов
/ 04 сентября 2010

Я бы порекомендовал вам использовать ViewModels и передавать только виды моделей в представления.Таким образом, вам не нужно беспокоиться об утилизации.Также абстрагируйте и разделите ваш доступ к данным в репозитории:

public interface IPersonRepository
{
    IEnumerable<Person> GetPeople();
}

public class PersonRepositorySql : IPersonRepository, IDisposable
{
    private MyObjectContext _db = new MyObjectContext();

    public IEnumerable<Person> GetPeople()
    {
        return _db.People;
    }

    public void Dispose()
    {
        _db.Dispose();       
    }
}

public class HomeController : Controller
{
    private readonly IPersonRepository _repository;

    public HomeController(IPersonRepository repository) 
    {
        _repository = repository;
    }

    public ActionResult Index()
    {
        IEnumerable<Person> people = _repository.GetPeople();

        // Using AutoMapper here but could be anything:
        IEnumerable<PersonViewModel> peopleViewModel = Mapper
            .Map<Person, PersonViewModel>(people);

        return View(peopleViewModel);
    }
}

Теперь утилизация репозитория является задачей его создателя, который, если вы следуете передовым методам, является структурой внедрения зависимости.Чтобы создать экземпляр вашего контроллера, вам нужно передать экземпляр репозитория в конструктор, и большинство хороших DI-фреймворков будут автоматически располагать объекты, которые реализуют IDisposable.

...