Entity Framework: Как я могу использовать более одного контекста и оставаться синхронизированным? - PullRequest
2 голосов
/ 20 июля 2010

Я новичок в EntityFramework.

Мое приложение имеет пул экземпляров объектов контекста (каждый контекст имеет 1 соединение с БД).

Проблема в том, что когда я обновляю объект (и вызываю SaveChanges), данные обновляются в БД и в контексте обновления, но когда я выбираю другой экземпляр, он получает старые данные выбранного объекта.

Пример:

Давайте представим таблицу с именем tbl.

Таблица имеет 2 столбца: идентификатор и данные.

1 строка: id = 1, data = 2.

EFContext context1 = new EFContext();      
EFContext context2 = new EFContext();      
var obj1 = context1.tbl.Where(a => a.id == 1);      
var obj2 = context2.tbl.Where(a => a.id == 1);      
obj2.data = 10;      
context2.SaveChanges(); 
var obj3 = context1.tbl.Where(a => a.id == 1); 

После выполнения этих строк obj3.data содержит 2 вместо 10.

Как я могу решить эту проблему?

Я не хочу создавать экземпляр контекста каждый раз, когда хочу получить доступ к БД.

Обновление недостаточно, мне придется делать это перед каждым запросом (мое приложение является многопоточным), и это занимает много времени.

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

Спасибо!

Ответы [ 4 ]

5 голосов
/ 20 июля 2010

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

Вам следует рассмотреть возможность применения более подходящего шаблона проектирования к вашей проблеме, взгляните на шаблон Репозиторий и Единица работы

3 голосов
/ 20 июля 2010

Вы не должны хранить ссылку на контексты объекта в течение длительного периода времени.

http://blogs.microsoft.co.il/blogs/gilf/archive/2010/02/07/entity-framework-context-lifetime-best-practices.aspx

http://blogs.msdn.com/b/alexj/archive/2009/05/07/tip-18-how-to-decide-on-a-lifetime-for-your-objectcontext.aspx

Этот второй также указывает:

Безопасность потока: Если вы пытаетесь повторно использовать ObjectContext, вы должны знать, что он не является потокобезопасным, то есть похож на стандартные классы коллекций .NET. Если вы обращаетесь к нему из многих потоков (например, веб-запросов), вам необходимо убедиться, что вы синхронизируете доступ вручную.

Итак, в основном вам придется блокировать весь контекст. Вместо этого вы можете просто использовать экземпляр для каждого потока (созданного в соответствии с описанными рекомендациями) и позволить базе данных решать проблемы параллелизма. Еще лучше использовать транзакции .

Хотя соблазнительно пытаться держать контекст открытым в течение длительного периода времени, чтобы сэкономить на создании / удалении и т. Д. - на практике вы должны открывать и закрывать контекст так, как и когда вам это нужно.

Это облегчается с EF из-за того, что вы можете взять объект из контекста и позже присоединить его к другому - что трудно, если не невозможно сделать с Linq to SQL.

В общем, не делайте этого:)

0 голосов
/ 20 января 2015

как сказал @Андрас Золтан: Вы не должны хранить ссылку на контексты объекта в течение длительного периода времени.

EFContext context1 = new EFContext();      
EFContext context2 = new EFContext();      
var obj1 = context1.tbl.Where(a => a.id == 1);      
var obj2 = context2.tbl.Where(a => a.id == 1);      
obj2.data = 10;      
context2.SaveChanges(); 
EFContext context3 = new EFContext();   //new context
var obj3 = context3.tbl.Where(a => a.id == 1); 
0 голосов
/ 23 июля 2010

Обратите внимание, что соединения БД могут оставаться открытыми в течение нескольких периодов времени OC, даже если ваш провайдер не будет их объединять.Пара вещей, которые вы можете настроить после профилирования:

  1. Явное открытие Context.Connection при создании экземпляра OC.Запрещает контексту запрашивать новое соединение для каждого запроса.

  2. Предоставить существующий EntityConnection для конструктора OC.Затем он будет использовать существующее соединение в течение нескольких времен жизни OC.

  3. Прекомпилировать запросы EF;они кэшируются в OC.Прекомпиляция позволяет кешу охватывать несколько экземпляров OC.

Опять же, конструктор OC стоит не дорогоВы должны первый профиль и найти медленную часть.Исправьте это, не OC;это не сломано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...