2014-01-12 2 views
3

Мне интересно, каковы различия в производительности и общих рекомендациях при подключении к db с использованием классов контекста для веб-сайта. Что является лучшим способом пойти при рассмотрении этих двух различных подходов:Есть ли правильный способ использования класса контекста db?

public class Repository() 
{ 
    Private Context context; 

    public List<User> GetUsers() 
    { 
     return this.context.Users.ToList(); 
    } 

или

public class Repository() 
{   
    public List<User> GetUsers() 
    { 
     using (Context context = new context()) 
     { 
      return context.Users.ToList(); 
     } 
    } 
} 

И это имеет значение, если она возвращает результат как List или IEnumerable?

+0

Первая версия: где и когда вы создаете и удаляете контекст? –

+0

Здесь вы можете найти информацию: http://stackoverflow.com/questions/16058769/declaring-entity-framework-contexts-with-using Надеюсь, что эта помощь. – lmt1608

ответ

3

Хотя вы уже приняли (вполне приемлемый) ответ, который затрагивает вопросы, связанные с жизнью, я думаю, что самый важный аспект был снят только в ответ Криса. Важнейшей причиной, почему (IMHO) должен быть вариант 1, является композитоспособность.(Но важным предположением является то, что в варианте 1 репозиторий получает контекст в своем конструкторе, поэтому этот контекст может использоваться несколькими репозиториями в одном случае).

Предположим, вы хотите присоединиться к двум организациям в одном запросе:

from u in repo1.GetUsers() 
join r in repo2.GetRoles() on u.UserId equals r.UserId 
where u.UserId = ... 

С опцией 2 это будет выполнять отдельные запросы для пользователей и ролей, потому что два DbSet s из разных контекстов могут быть объединены только в памяти. В случае с вариантом 1 (и некоторыми изменениями) это сгенерирует один скомпилированный запрос с помощью соединения SQL.

Что вам нужно сделать, сделать дополнительно, это вернуть IQueryable в смену List, т.е. просто вернуть context.Users.

Кроме того, с вариантом 2, если вы вносите изменения в объекты из разных хранилищ, для их совершения в одной транзакции гораздо сложнее. (Вам нужно SaveChanges() вызовов в каждом контексте, завернутых в TransactionScope).

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

+0

Какой шаблон вы рассматриваете вариант № 1? Тот, который появляется первым? Или тот, который использует новый dbContext для каждого вызова метода? – Aheho

+0

Я фактически перепутал фрагменты кода. Хорошо, что вы заметили, потому что я также должен был упомянуть важное предположение - см. Мое редактирование. –

0

Используйте первую версию. Если вам нужно вызвать несколько методов в вашем репозитории, вы только инициализируете свой контекст один раз, а не инициализируете его снова и снова внутри каждого метода. Кроме того, с помощью поля подложки, вы даете себе возможность инъекции Усиливая зависимость, которая является мощной концепцией, чтобы ваше приложение развязано, flexbile, проверяемым и ремонтопригодна:

http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-dependency-injection

1

Определенно второго подхода ,
Построение DbContext почти не работает. Дорогая вещь - , создавая (не , устанавливая) соединение с Db, и это происходит только один раз из-за объединения пулов. С другой стороны, сохранение соединения в течение более длительного времени - это плохая идея (в том числе, она довольно ресурсоемкая) и может вызывать различные другие проблемы (например, разрыв соединения из-за сетевых ошибок).

5

Копирование из MSDN

Lifetime

Времени жизни контекста начинается, когда создается экземпляр, и заканчивается, когда экземпляр либо помещенный или сборщик мусора. Используйте, если хотите, чтобы все ресурсы, которые элементы управления контекстом должны быть расположены в конце блока. Когда вы используете использование, компилятор автоматически создает блок try/finally и вызовы удаляются в блоке finally.

using (var context = new ProductContext()) 
{  
    // Perform data access using the context 
} 

Вот некоторые общие рекомендации при принятии решения о жизни в контексте:

При работе с долгоиграющим контекстом необходимо учитывать следующее: Как загрузить больше объектов и их ссылки в память, память потребление контекста может быстро увеличиваться. Это может вызвать проблемы с производительностью. Не забудьте избавиться от контекста, когда он больше не требуется. Если исключение приводит к тому, что контекст находится в состоянии, не подлежащем восстановлению, все приложение может завершиться. Шансы столкнуться с проблемами, связанными с параллелизмом, возрастают по мере увеличения разрыва между временем, когда данные запрашиваются и обновляются. При работе с веб-приложениями используйте экземпляр контекста для каждого запроса. При работе с Windows Presentation Foundation (WPF) или Windows Forms используйте экземпляр контекста для каждой формы. Это позволяет использовать функции отслеживания изменений, предоставляемые контекстом.

Смежные вопросы