Почему MySQL вызывает исключение DataReader при использовании для EF - PullRequest
0 голосов
/ 11 мая 2018

Я пытался использовать MySQL с Entity Framework 6. У меня есть несколько проектов, которые успешно используют SQL Server Express без проблем. Новый проект основан на этих предыдущих проектах, и мне потребовались небольшие изменения, чтобы подключиться и заполнить базу данных EF. Проблема, с которой я сейчас сталкиваюсь, заключается в том, что простой запрос, который отлично работает на SQL Server, вызывает исключение при использовании MySQL.

Здесь задействованы две таблицы / сущности. Device - это представление физического устройства, которое собирает образцы данных. Monitor - это определение типа данных для выборки. Итак, для каждого устройства определены несколько мониторов. Как только я пытаюсь получить список мониторов для устройства, выдается следующее сообщение об ошибке:

MySql.Data.MySqlClient.MySqlException: There is already an open DataReader associated with this Connection which must be closed first.

Вот код:

using (var context = new ApplicationDbContext())
{
    foreach (var device in context.Devices)
    {
        var monitors = device.Monitors.Where(m => m.Enabled == true).ToList();

        if (monitors.Count > 0)
        {
            // Get sampled data from device
        }
    }
}

Я предполагаю, что это проблема с драйверами MySQL относительно их реализации EF. У кого-нибудь есть идеи, как это исправить или обойти это? Я делаю что-то действительно глупое и очевидное, чего просто не вижу? Я использую эти же шаблоны для доступа к связанным объектам все время в моих реализациях SQL Server. Итак, я обеспокоен тем, что это будет пробой для использования MySQL, по крайней мере с их встроенными драйверами.

Некоторая соответствующая информация:

.NET: 4.5.2

EF: 6

MySQL: 5,7

MySqlClient: 6.9.11.0

1 Ответ

0 голосов
/ 11 мая 2018

Это происходит потому, что context.Devices сохраняет MySqlDataReader открытым (для ленивой потоковой передачи результатов), но device.Monitors.Where(...) пытается выполнить второй запрос для того же соединения.

Я могу придумать два обходных пути:

1. Принудительная оценка первого запроса

Используйте .ToList(), чтобы принудительно внести все результаты в память:

foreach (var device in context.Devices.ToList())

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

2. Объедините оба запроса в один

foreach (var device in context.Devices.Where(d => d.Monitors.Any(m => m.Enabled)))
{
    // Get sampled data from device
}

Это должно привести к тому, что EF создаст один, более эффективный запрос, который извлекает только нужные вам объекты device и избегает ошибки «уже открыт DataReader».

...