Miniprofiler 1.9.1 throws Невозможно определить имя поставщика для соединения типа 'System.Data.SqlClient.SqlConnection' с EF Code First - PullRequest
3 голосов
/ 06 сентября 2011

Я знаю, что, вероятно, я немного толще, однако ......

Создано новое тестовое приложение MVC3, сначала использующее код EF.

Контекст:

    public class EmployeeContext : DbContext
    {
        public DbSet<Employee> Employees { get; set; }
    }

Контроллер:

    public ActionResult Index()
    {
        List<Employee> employees;
        using (var ctx = new EmployeeContext())
        {
            employees = ctx.Employees.ToList();
        }
        return View(employees);
    }

    [HttpPost]
    public ActionResult Create(Employee employee)
    {
        using (var ctx = new EmployeeContext())
        {
            ctx.Employees.Add(employee);
            ctx.SaveChanges();
        }

        return RedirectToAction("Index");
    }

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

Теперь для минипрофиля.

Добавлен miniprofiler.EF1.9.1 из nuget.

Я думаю мне просто нужно добавить следующую строку в метод application.start global.asax:

    MiniProfilerEF.Initialize();

Когда я запускаю с использованием этого, Я получаю «Невозможно определить имя поставщика для подключения типа« System.Data.SqlClient.SqlConnection »."исключение.

Мне не нужно ничего добавлять в файл web.config, верно?

Ответы [ 3 ]

1 голос
/ 13 октября 2011

Нет, ты не толстый :-). Кажется, есть проблема с EF и MiniProfiler.EF 1.9.1. См. этот вопрос . По всей видимости, в версии 2.0 появится обходной путь.

0 голосов
/ 18 апреля 2013

Проблема:

Если 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, которую вы включили в свой проект..

0 голосов
/ 14 декабря 2011

Существует открытая в настоящее время нерешенная проблема, отслеживающая это:

http://code.google.com/p/mvc-mini-profiler/issues/detail?id=112&q=Unable%20to%20determine%20the%20provider%20name

...