Entity Framework ObjectContext для повторного использования

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

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

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

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

6 ответов

Решение

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

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

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

Я думаю, что наиболее распространенный способ - использовать его по запросу. Создайте его в начале, делайте то, что вам нужно (в большинстве случаев это операции, требующие общего 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;
    }
}

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

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

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

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

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

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

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

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);
        }
    }
Другие вопросы по тегам