Это может быть связанная, но другая проблема, но так как именно пост Андерса привел меня к решению, я решил опубликовать и это решение здесь.
Проблема:
Если MiniProfiler инициализируется до выполнения наших стратегий инициализации базы данных Entity Framework, инициализация завершается ошибкой с отсутствующей таблицей миграции.
Если стратегии инициализации базы данных Entity Framework выполняются первыми,доступ к сущностям завершается неудачно с исключением типа приведения типа, так как MiniProfiler DbConnection пытаются принудительно принудительно ввести в переменную SqlConnection (во внутреннем универсальном).
Причина:
Когда MiniProfiler инициализируется, он использует отражение для извлечения коллекции поставщиков баз данных из частного статического поля в System.Data.Common.DbProviderFactories.Затем он переписывает этот список с поставщиками прокладок MiniProfiler для замены собственных поставщиков.Это позволяет MiniProfiler перехватывать любые вызовы базы данных в режиме без вывода сообщений.
При инициализации Entity Framework он начинает компилировать модели данных и создавать кэшированные инициализированные базы данных, хранящиеся в System.Data.Entity.Internal.LazyInternalContext внутри некоторого частного статического объекта.поля.После того, как они созданы, запросы к DbContext используют кэшированные модели и базы данных, которые внутренне типизированы для использования поставщиков, которые существовали во время инициализации.
Когда запускается стратегия инициализации базы данных Entity Framework, ей требуется доступ к голой, родной Sql-провайдер, а не Shim MiniProfiler, для правильной генерации SQL для создания таблиц.Но как только эти обращения к собственному провайдеру сделаны, нативный провайдер кэшируется в LazyInternalContext, и мы больше не можем вставлять прокладки MiniProfiler без сбоев во время выполнения.
Мое решение:
Доступ к частным коллекциям внутри System.Data.Entity.Internal.LazyInternalContext и очистка кэшированных скомпилированных моделей и инициализированных баз данных.
Если я выполню эту чистку между операцией стратегий инициализации базы данных EF и инициализациейMiniProfiler, затем можно вставить прокладки MiniProfiler, не вызывая при этом последующих сбоев во время выполнения.
Код: Этот код помог мне:
Type type = typeof(DbContext).Assembly.GetType("System.Data.Entity.Internal.LazyInternalContext");
object concurrentDictionary = (type.GetField("InitializedDatabases", BindingFlags.NonPublic | BindingFlags.Static)).GetValue(null);
var initializedDatabaseCache = (IDictionary)concurrentDictionary;
if (initializedDatabaseCache != null) initializedDatabaseCache.Clear();
object concurrentDictionary2 = (type.GetField("CachedModels", BindingFlags.NonPublic | BindingFlags.Static)).GetValue(null);
var modelsCache = (IDictionary)concurrentDictionary2;
if (modelsCache != null) modelsCache.Clear();
Предупреждение:
Похоже, что имена внутренних полей в LazyInternalContext изменяются между версиями EF, поэтому вам может потребоваться изменить этот код для работы с точной версией EF, которую вы включили в свой проект..