Entity framework ObjectContext share-плюсы и минусы
в моем проекте я использую entity framework 4.0 в качестве ORM для сохранения данных в SQL Server.
мой проект представляет собой ленту из приложения с видом сетки и дерева навигации в основной форме с панелью ленты поверх него. Мое приложение в основном действует CRUD UI с очень маленькой бизнес-логикой.
будучи впервые с EF, я разработал этот проект, создав и удерживая экземпляр objectContext в оркеструющей форме (основная форма или та, которая отображается как application to user) в качестве переменной-члена и привязал запрос к представлению сетки.
для различных событий, таких как щелчки кнопки панели ленты, щелчки строки сетки и т. д., Я открываю другую форму windows. В этой форме окна я создаю другой контекст объекта и сохраняю его в переменной-члене этого класса формы.
Я прочитал несколько блогов и вопросов, таких как:
- как решить на всю жизнь для вашего objectcontext
- Entity Framework и ObjectContext N-уровневая архитектура etc.
один набор авторов предлагает поделиться контекстом объекта, в то время как другие предлагают кратковременный и не общий.
Я достиг этого состояния замешательства, потому что теперь я нахожусь в состоянии, когда изменения, внесенные мной в objectContext в одной из дочерних форм, не отражают родительскую форму, которая его показала. Я попытался обновить, но все равно ничего полезного. Просто для эксперимент, я разделил objectContext, который я впервые создал в самом родительском классе с помощью инъекции конструктора, и моя проблема отражения изменений решена.
Это огромная работа для меня, чтобы преобразовать все мои дочерние формы для обмена objectContext. Но я готов, если это того стоит. Я не уверен, каковы будут скрытые проблемы, связанные с его разделением?
Я могу выбрать статический экземпляр objectContext, поскольку я не использую это для интернета и не планирую многопоточные сценарии. Если потребуется, я могу стать одиночкой.
Мои Вопросы:
- поделиться или не поделиться ObjectContext для моей ситуации?
- если не делиться, как я могу решить свою нынешнюю проблему обновления одного objectContext с изменениями, внесенными в другой?
- если поделиться-что было бы лучше? Статика, синглтон или что-то еще?
детали проекта и окружающей среды как ниже:
- приложения WinForms
- C#
- VS 2012
- EF 4.0, модель, созданная с первым подходом к данным.
Я публикую это после поиска и чтения многих вопросов и сообщений в блоге. Чем больше я читаю, тем более запутанным становится :) пожалуйста, потерпите со мной, если я оставляю кого-то предполагать что-то ответить. Я постараюсь обновить вопрос, если такие разъяснения будут заданы через комментарии.
1 ответов
Вопросы
поделиться или не поделиться ObjectContext для моей ситуации?
Не делитесь своим контекстом. Контекст EntityFramework должен следовать шаблону UnitOfWork. Ваш контекст объекта должен быть как можно более коротким, без ненужного создания / уничтожения слишком много контекстов. Это обычно переводится на отдельные "операции" в вашем приложении как единицы работы. Для веб-приложения / api это может быть per HttpWebRequest
, или вы можете сделать это в логических данных операция (для каждого из ваших реализованных фрагментов "бизнес-логики").
например:
-
LoadBusinssObjects()
создаст контекст, загрузит ваш список данных плюс любые связанные данные, которые вы хотите, а затем избавиться от контекста. -
CreateBusinessObject()
создаст контекст, создаст экземпляр некоторой сущности, заполнит его данными, присоединит его к сбору в контексте, сохранит изменения и затем удалит контекст. -
UpdateBusinessObject()
читал какой-то объект из контекста обновите его, сохраните изменения и удалите контекст. -
DeleteBusinessObject()
найдет бизнес-объект в контексте, удалит его из коллекции в контексте, сохранит изменения и удалит контекст.
если не делиться, как я могу решить свою нынешнюю проблему обновления одного objectContext с изменениями, внесенными в другой? Это работа для паб/суб архитектуры. Это может быть так же просто, как несколько статических событий обработчики ваших объектов для каждой операции, реализованной выше. Затем в коде для каждой бизнес-операции, выполнении соответствующих мероприятий.
если поделиться-что было бы лучше? Статика, синглтон или что-то еще? Это неверно. Контекст EF будет продолжать расти в объеме памяти, поскольку диспетчер состояний контекста непрерывно собирает кэшированные объекты (как прикрепленные, так и не прикрепленные) для взаимодействие вы сделайте в своем приложении. Контекст не предназначен для такой работы.
в дополнение к использованию ресурсов контекст EF не является потокобезопасным. Например, что, если вы хотите разрешить одной из форм редактора сохранять некоторые изменения одновременно с загрузкой новых данных в список дерева? С одним статическим экземпляром вам лучше убедиться, что все это работает в потоке пользовательского интерфейса или синхронизировано с семафором (yuck и yuck-bad практики.)
пример
вот пример использования C# и кода первого подхода в соответствии с вашим сообщением. Обратите внимание, что я не рассматриваю такие вещи, как параллелизм данных или поток, чтобы сохранить пример коротким. Также в реальном приложении эта концепция реализована с дженериками и отражением, так что все наши модели имеют базовые события для создания, обновления, удаления.
public class MyCodeFirstEntityChangedArgs : EventArgs
{
/// <summary>
/// The primary key of the entity being changed.
/// </summary>
public int Id {get;set;}
/// <summary>
/// You probably want to make this an ENUM for Added/Modified/Removed
/// </summary>
public string ChangeReason {get;set;}
}
public class MyCodeFirstEntity
{
public int Id {get;set;}
public string SomeProperty {get;set;}
/// <summary>
/// Occurs when an instance of this entity model has been changed.
/// </summary>
public static event EventHandler<MyCodeFirstEntityChangedArgs> EntityChanged;
}
public class MyBusinessLogic
{
public static void UpdateMyCodeFirstEntity(int entityId, MyCodeFirstEntity newEntityData)
{
using(var context = new MyEFContext())
{
// Find the existing record in the database
var existingRecord = context.MyCodeFirstEntityDbSet.Find(entityId);
// Copy over some changes (in real life we have a
// generic reflection based object copying method)
existingRecord.Name = newEntityData.Name;
// Save our changes via EF
context.SaveChanges();
// Fire our event handler so that other UI components
// subscribed to this event know to refresh/update their views.
// ----
// NOTE: If SaveChanges() threw an exception, you won't get here.
MyCodeFirstEntity.EntityChanged(null, new MyCodeFirstEntityChangedArgs()
{
Id = existingRecord.Id,
ChangeReason = "Updated"
});
}
}
}
теперь вы можете прикрепить обработчики событий к вашей модели из любого места (его статический eventhandler) вот так:
MyCodeFirstEntity.EntityChanged += new EventHandler<MyCodeFirstEntityChangedArgs>(MyCodeFirstEntity_LocalEventHandler);
а затем иметь обработчик в каждом представлении, который будет обновлять локальные представления пользовательского интерфейса при каждом запуске этого события:
static void MyCodeFirstEntity_LocalEventHandler(object sender, MyCodeFirstEntityChangedArgs e)
{
// Something somewhere changed a record! I better refresh some local UI view.
}
теперь каждый компонент пользовательского интерфейса вы можете подписаться на то, какие события важны для него. Если у вас есть список дерева, а затем некоторая форма редактора, список дерева подпишется на любые изменения для добавления/обновления/удаления узла (или простым способом - просто обновите весь список дерева).
Обновления Между Приложения
если вы хотите пойти дальше и даже связать отдельные экземпляры вашего приложения в подключенной среде, вы можете реализовать систему pub / sub eventing по сети, используя что-то вроде WebSync-реализация comet для стека технологий Microsoft. WebSync имеет все материалы, встроенные для разделения событий на логические "каналы" для каждой сущности/события, на которые вы хотите подписаться или опубликовать. И да, я работаю в софтверной компании, которая производит WebSync-они платят за мое время, когда я пишу это. :-)
но если вы не хотите платить за коммерческую реализацию, Вы можете написать свой собственный клиент/сервер сокета TCP, который распространяет уведомления о вышеуказанных событиях при изменении сущности. Затем, когда подписавшееся приложение получает уведомление по сети, оно может запускать свои локальные обработчики событий таким же образом, что приведет к обновлению локальных представлений. Вы не можете сделать это с плохо сконструированным статическим экземпляром вашего контекст данных (вы будете обязаны иметь только один экземпляр вашего приложения). С хорошей настройкой на раннем этапе вы можете легко прикрепить распределенную систему pub-sub позже, которая работает в нескольких экземплярах собственных приложений и веб-приложений одновременно! Это становится очень мощным.