2011-12-18 2 views
1

Это действие, которое у меня есть в контроллере. Считается, что плохая практика заключается в создании и удалении подключения к базе данных (например, PhotoGalleryContext - который является соединением с базой данных MySql) внутри этого контроллера, а не абстракции, если это действие выполняется на уровне доступа к данным в модели. cs класс?MVC3 Data Context Best Practice

// GET: /Admin/GetPhoto/id 
    public ActionResult GetPhoto(int id) 
    { 
     PhotoGalleryContext db = new PhotoGalleryContext(); 

     Models.PhotoGallery.Photo photo = new Models.PhotoGallery.Photo(); 
     photo = db.Photos.Where(p => p.PhotoId == id).Single(); 

     string filePath = photo.FileLocation; 

     db.Dispose();  

     byte[] byteArray; 
     try 
     { 
      byteArray = System.IO.File.ReadAllBytes(filePath); 
      return File(byteArray, "image/jpg"); 
     } 
     catch (Exception) 
     { 
      //throw; 
     } 
     return null; 
    } 
+0

Где вы располагаете db (PhotoGalleryContext)? Это не в этом примере? – DaveShaw

+0

Ошибка копирования патчей, * editted *, чтобы показать dispose –

ответ

1

согласен с Давидом, в том, что это зависит от размера вашего приложения.

Однако я бы предложил использовать зависимую инъекцию для управления соединением для вас.

Используя что-то вроде StructureMap, вы могли бы иметь что-то вроде этого:

For<PhotoGalleryContext>() 
    .HybridHttpOrThreadLocalScoped 
    .Use<PhotoGalleryContext>(); 

что переводится:

Когда что-то просит PhotoGalleryContext, придать ему новый PhotoGalleryContext что HTTP-область (созданная при начале запроса, расположена в конце).

Таким образом, StructureMap автоматически откроет/закроет соединение для вас.

Тогда ваш контроллер может выглядеть следующим образом:

private readonly PhotoGalleryContext _db; 
public AdminController(PhotoGalleryContext db) 
{ 
    _db = db; 
} 

И в своих методах действий, _db будет готов пойти на вас.

Несколько строк кода, чтобы сэкономить много повторяющихся с использованием утверждений в вашем приложении.

+1

Это элегантное решение, спасибо вам большое. –

+0

Если я верну модель, которая по-прежнему использует неглубокую копию контекста базы данных, это предотвратит отказ от вызова? –

+0

@TravisJ - нет, потому что рендеринг View по-прежнему является частью текущего HTTP-запроса, * однако *, это плохая практика. Ваш взгляд не должен знать/заботиться о каком-либо соединении с БД. Почему модель использует мелкую копию ctx? – RPM1984

2

Возможно, вы рассмотрели размер своей заявки, решив это. Я бы сказал, отделяя модель является наилучшей практикой, но для небольших приложений, может быть, вы просто должны обернуть PhotoGalleryContext в использовании блока:

using(PhotoGalleryContext db = new PhotoGalleryContext()) 
{ 

    Models.PhotoGallery.Photo photo = new Models.PhotoGallery.Photo(); 
    photo = db.Photos.Where(p => p.PhotoId == id).Single(); 

    string filePath = photo.FileLocation; 
    byte[] byteArray; 
    try 
    { 
     byteArray = System.IO.File.ReadAllBytes(filePath); 
     return File(byteArray, "image/jpg"); 
    } 
    catch (Exception) 
    { 
     //throw; 
    } 
    return null; 
} 
+1

Если бы я мог отделить это от модели, я бы все равно просто создавал экземпляр класса PhotoGalleryManager каждый раз внутри такого контроллера, а затем удалял его в конце? Если мой Менеджер содержит много разных операций, то будет ли медленнее загружать весь класс менеджера для чего-то легкого? –

+0

Использует() лучше вызова .dispose()? –

+1

с использованием() вызовов Dispose() в концевой фигурной скобе imo делает код более понятным с первого взгляда (пока вы вставляете формат своего кода). – danludwig