Многочисленные AJAX-запросы MVC с Entity Framework вызывают ошибку - PullRequest
2 голосов
/ 09 марта 2012

У меня есть две jqGrids, которые загружают данные через вызов ajax POST на мой контроллер, и каждый раз, когда я запускаю приложение, только один из двух POST выполняется успешно. Обычно, если я нажимаю кнопку обновления в браузере, обе сетки будут загружаться правильно. Но последовательно 1 из 2 терпит неудачу при первой загрузке каждого представления (у меня есть два представления / страницы, у каждого из которых есть 2 jqGrids, "стиль панели инструментов"). В журналах log4net два запроса имеют разные потоки, и один всегда терпит неудачу, в то время как другой успешно, но тот, который успешно выполняется, является случайным (вероятно, первым пришел, первым обслужен) ... Иногда я получаю нулевую ссылку на ошибку, когда он пытается перебрать результирующий перечислимый список элементов, в других случаях я получаю «Соединение не было закрыто. Текущее состояние соединения подключается».

У меня есть некоторые подозрения, что может быть причиной этого: отложенная загрузка EF / прокси-серверы включены, неправильная конфигурация windsor, ошибка автоматического обработчика, которая не генерируется или не отображается в трассировке стека. Но так как у меня действительно нет никакой подсказки, ниже моя установка на случай, если она поможет расшифровать это.

Постоянство [LifestyleSingleton] - содержит текстовый текст EF4 (сначала код) и ссылку на EF4.3. Есть фабрика для создания контекста, называемая GetContext (), и эта фабрика реализует IDisposable.
Репо [LifestylePerWebRequest] - Содержит репозитории, реализующие шаблон репозитория и спецификации (http://huyrua.wordpress.com/2010/07/13/entity-framework-4-poco-repository-and-specification-pattern/).
Услуги [LifestylePerWebRequest] - вызывает репо и применяет шинную логику, то есть возвращает объекты PagedList для подкачки пользовательского интерфейса.
Контроллеры [LifestyleTransient] - контроллеры mvc, для автоматического отображения типов моделей используется автоматический преобразователь.
MVC UI - Я реализую Lib.Web.MVC, который создает строго типизированную оболочку для jqGrid. И отсюда я использую контейнер Виндзор, чтобы сделать DI.

ОБНОВЛЕНИЕ: Я изменил все компоненты для регистрации в LifestylePerThread, и все ошибки, похоже, были устранены с помощью этого. Тем не менее, я не понимаю, почему .. Я новичок в DI, так что я уверен, что что-то упустил. Может кто-нибудь объяснить, почему это решило проблему? И что это изменение сделает с масштабируемостью ...? Я решил, что хочу, чтобы фабрика контекста вместе с самим контекстом была зарегистрирована как синглтон, но это, очевидно, было неправильно.

Ответы [ 3 ]

3 голосов
/ 09 марта 2012

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

Я решил это, добавив MultipleActiveResultSets=True в строку подключения.

Цитирование Microsoft "Несколько активных наборов результатов (MARS) - это ... В двух словах, это возможность иметь более одного ожидающего запроса при заданном соединении с SQL Server. В большинстве случаев это прямо переводится иметь более одного набора результатов по умолчанию (курсор пожарного шланга) в ожидании, в то время как другие операции могут выполняться в одном сеансе. "

Узнайте больше о MARS на http://msdn.microsoft.com/en-us/library/ms345109%28v=sql.90%29.aspx

Что касается «образа жизни» вашего хранилища, я предлагаю создавать новый экземпляр хранилища каждый раз, когда его запрашивают. У меня были проблемы с каждым запросом.

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

2 голосов
/ 15 марта 2012

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

.... когда я использовал этот репозиторий впакетный процесс, при котором несколько потоков обращаются к хранилищу вместе с простым хранилищем объектного контекста, я получил исключения, поскольку объектный контекст не может быть общим (EF сам по себе не является потокобезопасным из-за этого).Следовательно, с небольшой модификацией SimpleObjectContextStorage это, кажется, теперь работает также: я просто сделал переменную хранения threadstatic и вместо этого использовала свойство в других методах (_storage дублируется для каждого потока, но заполняется только для первого потока черезвызов статического конструктора) [ThreadStatic] частный статический словарь _storage;

частный статический словарь для хранения {get {return _storage ??(_storage = новый словарь ());}} note: ThreadStatic ожидает, что соответствующая переменная также будет статической, но, поскольку вы, как правило, определяете только одно хранилище для приложения через вызов ObjectContextManager.Init, это не должно иметь влияния.

1 голос
/ 09 марта 2012

Как это терпит неудачу? т.е. вы получаете исключение обратно? Используете ли вы что-то вроде firebug, чтобы увидеть, что возвращается?

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

РЕДАКТИРОВАТЬ: Как правило, если что-то приводит к тому, что ваши репозитории создаются, а константы данных остаются нераспределенными между запросами, то это очень и очень плохо. Я видел много IOC-контейнеров, которые позволяют слишком легко это делать либо с помощью конфигурации, либо путем привязки к чему-то, что должно быть в запросе.

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

Сценарий, с которым я столкнулся здесь

PS: если вы делаете 2 отдельных поста через ajax, вам не нужно несколько активных наборов результатов, и это признак того, что ваш репозиторий и / или текстовый контекста являются громкими вне рамок запроса. Вам нужно только несколько активных наборов результатов, если вы хотите создать 2 экземпляра одного и того же текста данных в одной и той же области запроса.

Если это один пост / запрос, то приведенный выше ответ, вероятно, правильный.

...