Подтвердить что ты не робот

Потоковая защита Entity Framework 6

Простое тестирование EF6 и его функции Async. Мальчик был удивлен, когда понял, что они не потокобезопасны. Я предположил, что в этом смысл.

В течение многих лет у меня были собственные методы расширения Task, но то, что я ожидал от EF, заключалось в том, чтобы сделать их потокобезопасными.

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

Насколько я могу судить. Единственными двумя совместно используемыми (между объектами) изменяемыми ресурсами в dbContext являются отслеживание соединения и изменений (кэширование). Если бы мы могли добавить блокировку к функциям, тогда у нас был бы потокобезопасный контекст.

Мы могли бы сделать это в два этапа. Если бы мы могли реализовать поставщика, который заблокировал одну централизованную функцию, используемую для запроса базы данных. Тогда любые не отслеживаемые запросы - либо путем возврата объектов без сущностей (анонимных), либо путем вызова AsNoTracking() - будут потокобезопасными и будут безопасны для вызова с помощью функций Async, даже если другой поток может запрашивать ленивый загруженный объект.

Наша масштабируемость будет не хуже, чем сейчас, мы должны использовать один контекст для каждого потока, и даже функции Async находятся вне таблицы, если вы попытаетесь пропустить хотя бы один из них, чтобы ввести немного parallelism или (например, wpf), которые могут запускаться после того, как ожидаемая функция вернется с заданием.

Итак, мой вопрос. Кто-нибудь реализовал такой провайдер. Или кто-нибудь захочет работать со мной на нем?

4b9b3361

Ответ 1

Я думаю, что вы столкнулись с архитектурной проблемой. То, что вы описываете, - это приложение, в котором пользовательский интерфейс напрямую использует объекты EF, и он нарушает парадигму "разделение проблем".

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

Объекты DbContext, и все операции, связанные с EF CRUD, имеют очень ограниченное время жизни. Каждая операция CRUD создает экземпляр собственного DbContext и возвращает объекты модели в кеш, затем контексты собирают мусор. Мои приложения используют кеши в качестве уровня абстракции, а кеши используют EF в качестве уровня абстракции DB.

Например, изучение вложенных свойств объектов выполняется путем реализации пользовательских методов на уровне модели, который принимает объект Id как параметр и возвращает список связанных объектов в кеш. Пользовательский интерфейс запрашивает кэш, затем Cache запрашивает EF, а затем один раз доступный, вызов, сделанный в кеш, возвращает объекты в пользовательский интерфейс. Просто как это.

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

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

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