Почему Entity Framework + перечисление провайдера MySQL возвращает частичные результаты без исключений - PullRequest
4 голосов
/ 06 мая 2010

Я пытаюсь разобраться в ситуации, в которой я использую Entity Framework на .net 3.5 sp1 + MySQL 6.1.2.0 в качестве провайдера. Он включает следующий код:

Response.Write("Products: " + plist.Count() + "<br />");
var total = 0;
foreach (var p in plist)
{
//... some actions
    total++;
//... other actions
}
Response.Write("Total Products Checked: " + total + "<br />");

Как правило, общее количество продуктов меняется при каждом запуске, и оно не совпадает с полным итогом в plist. Он варьируется в широких пределах, от ~ 1/5 до половины.

В foreach нет никакого кода потока управления, т. Е. Без перерыва, продолжения, попытки / перехвата, условий, связанных с total ++, всего, что может повлиять на счет. В качестве подтверждения в цикле фиксируются другие итоги, относящиеся к действиям, которые соответствуют нижнему и более высокому суммарным прогонам.

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

Тело foreach может иметь некоторые отличия во времени, так как действия включают доступ к файлам и сети, Мой лучший способ на тот момент - когда код .net выходит за определенные пределы, возникает некоторый тип время ожидания в базовом фреймворке / провайдере, и вместо того, чтобы вызвать исключение, он молча сообщает, что больше нет элементов для перечисления .

Может ли кто-нибудь пролить свет на вышеприведенный сценарий и / или подтвердить, имеет ли провайдер Entity Framework / MySQL поставщик вышеуказанного поведения?


Обновление 1: Я не могу воспроизвести поведение с помощью Thread.Sleep в простом foreach в тестовом проекте, не уверен, где еще искать это странное поведение: (.


Обновление 2: в приведенном выше примере .Count () всегда возвращает одинаковое + правильное количество предметов. Использование ToList или ToArray, как предлагается, позволяет обойти проблему как положено (нет операторов управления потоком в теле foreach), и оба значения совпадают + не меняются при каждом запуске.

Что меня интересует, так это то, что вызывает такое поведение в каркасе сущностей + mysql. Действительно предпочел бы не менять код во всех проектах, в которых для создания .ToArray используется Entity Framework + MySQL перед перечислением результатов, потому что я не знаю, когда он проглотит некоторые результаты. Или, если я сделаю это, хотя бы узнайте, что / почему это произошло.

Ответы [ 4 ]

2 голосов
/ 10 мая 2010

Если проблема связана с провайдером или чем-то еще, то вы можете решить / идентифицировать это, реализовав перечисляемое значение перед тем, как выполнить итерацию:

var realisedList = plist.ToArray();
foreach(var p in realisedList)
{
  //as per your example
}

Если после этого проблема все еще сохраняется, то

a) Одно из действий в перечислителе вызывает исключение, которое где-то проглатывается

б) Базовые данные действительно каждый раз разные.

ОБНОВЛЕНИЕ: (согласно вашему комментарию)

[удалено - несколько перечислений согласно вашему комментарию]

В конце дня - я бы поместил вызов ToArray (), чтобы исправить проблему в этом случае (если для получения итога требуется метод Count (), просто измените его на .Length на массиве, который построен).

Возможно, MySql уничтожает соединение во время перечисления и не выдает ошибку EF при вызове следующего MoveNext (). EF тогда просто покорно отвечает, говоря, что перечисление просто закончено. Если это так, пока такая ошибка в поставщике не будет исправлена, ToArray () - это путь вперед.

1 голос
/ 13 мая 2010

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

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

Чтобы проверить это, вы можете попробовать:

  • Упорядочивание данных и проверка, является ли число, возвращаемое для каждого оператора, одинаковым каждый раз.
  • Выберите только столбец id и посмотрите, исчезнет ли проблема
  • Удалите все строки из таблицы, добавьте их по нескольку за раз, чтобы увидеть, не является ли конкретная строка причиной проблемы

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

0 голосов
/ 24 мая 2010

Проблема, причина и обходной путь описаны именно в этой ошибке mysql .

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

На данный момент проблема присутствует в последней версии поставщика MySql и в нормальных условиях будет влиять только на сценарии, в которых строки читаются с подключением, поддерживаемым в течение длительного времени (которое может включать или не включать медленный запрос) , Это замечательно, потому что это не влияет на все предыдущие проекты, где я использовал MySql / применение обходного пути к источникам, а также означает, что он не потерпит молчания.

Ps. пара ошибок, которые кажутся связанными с MySQL: 1 , 2

0 голосов
/ 12 мая 2010

Я считаю, что это связано с тем, как EF обрабатывает ленивую загрузку. Возможно, вам придется использовать Load() или Include(), а также проверить использование свойства IsLoaded в цикле обработки. Проверьте эти две ссылки для получения дополнительной информации:
http://www.singingeels.com/Articles/Entity_Framework_and_Lazy_Loading.aspx
http://blogs.msdn.com/jkowalski/archive/2008/05/12/transparent-lazy-loading-for-entity-framework-part-1.aspx

Я прошу прощения, я не знаю больше об EF, чтобы быть более конкретным. Надеемся, что ссылки предоставят достаточно информации, чтобы вы могли начать, а другие могут ответить на любые ваши вопросы.

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