Entity Framework ObjectContext повторное использование

Сейчас я изучаю EF и задаю вопрос относительно ObjectContext:

Должен ли я создавать экземпляр ObjectContext для каждого запроса (функции) при доступе к базе данных?

Или лучше создать его один раз (singleton) и повторно использовать его?

До EF я использовал блок доступа к данным корпоративной библиотеки и создал экземпляр dataacess для функции DataAccess...

Ответы

Ответ 1

Определенно для каждого запроса. Это легкий объект, поэтому затраты на его сборку невелики каждый раз, когда вам это нужно.

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

И вот там проблема ремонтопригодности. Однажды вы попытаетесь отследить ошибку, но не можете определить, где были загружены данные, которые вызвали ее.

Ответ 2

Я думаю, что наиболее распространенный способ - использовать его для каждого запроса. Создайте его в начале, сделайте то, что вам нужно (большую часть времени это операция, которая требует общего ObjectContext), располагайте в конце. Большинство инфраструктур DI поддерживают этот сценарий, но вы также можете использовать HttpModule для создания контекста и размещения его в HttpContext.Current.Items. Это простой пример:

public class MyEntitiesHttpModule : IHttpModule
{
    public void Init(HttpApplication application)
    {
        application.BeginRequest += ApplicationBeginRequest;
        application.EndRequest += ApplicationEndRequest;
    }

    private void ApplicationEndRequest(object sender, EventArgs e)
    {
        if (HttpContext.Current.Items[@"MyEntities"] != null)
            ((MyEntities)HttpContext.Current.Items[@"MyEntities"]).Dispose();
    }

    private static void ApplicationBeginRequest(Object source, EventArgs e)
    {
        var context = new MyEntities();
        HttpContext.Current.Items[@"MyEntities"] = context;
    }
}

Ответ 3

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

Я бы добавил его как частный член

Ответ 4

Как говорит Люк, этот вопрос был задан много раз на SO.

Для веб-приложения для каждого цикла запросов лучше всего работать. Синглтон определенно плохая идея.

По запросу хорошо работает, потому что на одной веб-странице есть Пользователь, возможно, некоторые Проекты, принадлежащие этому пользователю, возможно, некоторые Сообщения для этого пользователя. Вам нужен тот же ObjectContext, чтобы вы могли использовать User.Messages для их получения, возможно, отмечали некоторые сообщения как прочитанные, возможно, добавляли проект, а затем либо фиксировали, либо оставляли весь граф объекта по завершении цикла страницы.

Ответ 5

Поздний пост здесь на 7 месяцев. В настоящее время я занимаюсь этим вопросом в своем приложении, и я склоняюсь к решению @LukLed, создавая Singleton ObjectContext на протяжении всего моего HttpRequest. Для моей архитектуры у меня есть несколько элементов управления, которые занимаются созданием страницы, и все эти элементы управления имеют свои собственные проблемы с данными, которые выводят данные только для чтения из уровня EF. Кажется расточительным для каждого из них создавать и использовать свои собственные объекты ObjectContext. Кроме того, существует несколько ситуаций, когда один элемент управления может извлекать данные в контекст, который может быть повторно использован другими элементами управления. Например, на моей главной странице мой заголовок в верхней части страницы содержит информацию о пользователе, которая может быть повторно использована другими элементами управления на странице.

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

Ответ 6

public class DBModel {

        private const string _PREFIX = "ObjectContext";

        // DBModel.GetInstance<EntityObject>();
        public static ObjectContext GetInstance<T>() {
            var key = CreateKey<T>();
            HttpContext.Current.Items[key] = HttpContext.Current.Items[key] ?? Activator.CreateInstance<T>();
            return HttpContext.Current.Items[key] as ObjectContext;
        }

        private static string CreateKey<T>() {
            return string.Format("{0}_{1}", _PREFIX, typeof(T).Name);
        }
    }