2010-12-23 3 views
5

У меня есть служба Windows, которая содержит наблюдателя файлов, который вызывает события при поступлении файла. Когда возникает событие, я буду использовать Ninject для создания объектов бизнес-уровня, внутри которых есть ссылка на контекст платформы Entity Framework, который также вводится через Ninject. В моих веб-приложениях я всегда использовал InRequestScope для контекста, таким образом, в рамках одного запроса все объекты бизнес-уровня работают с одним и тем же контекстом Entity Framework. В моем текущем сценарии службы Windows было бы достаточно переключить привязку контекста Entity Framework к привязке InThreadScope?Ninject InThreadScope Binding

В теории, когда обработчик событий в сервисе запускает его, выполняется в каком-то потоке, тогда, если другой файл поступает одновременно, он будет выполняться под другим потоком. Поэтому оба события не будут разделять контекст Entity Framework, по сути, как два разных HTTP-запроса в Интернете.

Единственное, что меня беспокоит разрушение этих нитей области видимости объектов, когда вы смотрите на вики Ninject:

.InThreadScope() - Один экземпляр типа будет создан для каждого потока.
.InRequestScope() - Один экземпляр типа будет создан для каждого веб-запроса и будет уничтожен при завершении запроса.

Исходя из этого, я понимаю, что объекты InRequestScope будут уничтожены (сборщик мусора собрал?), Когда (или в какой-то момент после) запрос завершается. Это ничего не говорит о том, как уничтожаются объекты InThreadScope. Чтобы вернуться к моему примеру, когда метод обработчика событий наблюдателя файла завершен, поток уходит (обратно в пул потоков?), Что происходит с объектами InThreadScope-d, которые были введены?

EDIT: Одно теперь ясно, что при использовании InThreadScope() не будет разрушать ваш объект, когда обработчик для выходов FileWatcher. Я смог воспроизвести это, отбросив много файлов в папке, и в итоге у меня есть тот же самый идентификатор потока, который привел к тому же точному контексту Entity Framework, что и раньше, поэтому его явно недостаточно для моих приложений. В этом случае файл, который пришел через 5 минут, может использовать устаревший контекст, который был ранее назначен тому же потоку.

ответ

4

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

Обычно я создаю ObjectContext с той же областью, в которой я создаю транзакцию базы данных (я часто даже переношу ObjectContext в транзакцию базы данных и распоряжаюсь им сразу после друг друга). Один (веб-запрос) мог бы иметь несколько транзакций базы данных, но обычно имеет одну «бизнес-транзакцию», которая выполняет бизнес-логику. Другие транзакции могут быть начаты для вещей как ведение журнала (до, после, а иногда и во время бизнес-транзакции). При повторном использовании ObjectContext для полного запроса вы можете столкнуться с беспорядком, потому что при сбое бизнес-транзакции ObjectContext может находиться в недопустимом состоянии, что может повлиять на операции (например, протоколирование), которые повторно используют тот же самый ObjectContext.

С вашей службой Windows я считаю, что каждое событие, вызванное наблюдателем файла, может инициировать новую бизнес-транзакцию. В этом случае я создам новый ObjectContext за каждое событие.

Короче говоря, я бы не вводил ObjectContext, у которого есть жизнь, которая управляется вашей картой IoC. Я бы ввел завод, который позволяет вашему коду создать новый ObjectContext и утилизировать его.Я просто ответил на другой вопрос об этом несколько наших назад. Посмотрите на решение, которое я предлагаю в that answer.

Удачи.

+0

Что касается HTTP-запроса, то, поскольку EF реализует шаблоны типа UnitOfWork, мой вызов SaveChanges в основном выполняет фиксацию транзакции на уровне бизнеса, как вы описали. Я вижу ваше предлагаемое решение, но я считаю, что для моей службы Windows также потребуется ссылка на мой уровень доступа к данным. Одно из преимуществ использования Ninject для предоставления мне объектов моего бизнес-уровня - это также забота о впрыске вниз, поэтому я запрашиваю объект бизнес-уровня, но он действительно вводит 3 уровня ProductManager-hasa-ProductRepository-hasa-EFContext. – e36M3

+0

@ e36M3: Ваш аргумент не изменился, вы можете использовать фабрику. Вам не нужна зависимость от вашей технологии доступа к данным, если вы этого не хотите. Взгляните на эту статью, чтобы узнать, как абстрагировать поставщика LINQ: http://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=84. – Steven

Смежные вопросы