Подтвердить что ты не робот

Как правильно профилировать Entity Framework?

Каков минимальный объем кода, который я могу написать, чтобы получить один обратный вызов из EF 4.1, который обеспечивает следующее:

  • OnSQLExecuted(DbCommand cmd, DateTime start, double durationMS, string stacktrace)

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


Мы можем подключить это в Mini Profiler от взломать - в основном мы изменили Database.DefaultConnectionFactory, однако сбрасывание по умолчанию factory означает, что у вас не может быть двух профилирующих заводов, идущих одновременно. Таким образом, мы пошли более агрессивным путем.


Используемая техника довольно проста, вы реализуете: DbProviderFactory, IDbConnectionFactory, DbProviderServices, DbConnection, DbCommand и DbDataReader таким образом, чтобы они перехватывали вызовы и профиль.

До сих пор, просто... однако это становится беспорядочным, когда вы пытаетесь подключить это:

   try
    {
        // ensure all the factories are loaded 
        DbProviderFactories.GetFactory("...");
    }
    catch (ArgumentException)
    {
    }

    Type type = typeof(DbProviderFactories);

    DataTable table;
    // SUPER UGLY - Can this be done in another way? 
    object setOrTable = (type.GetField("_configTable", BindingFlags.NonPublic | BindingFlags.Static) ??
                    type.GetField("_providerTable", BindingFlags.NonPublic | BindingFlags.Static)).GetValue(null);
    if (setOrTable is DataSet)
    {
        table = ((DataSet)setOrTable).Tables["DbProviderFactories"];
    }

    table = (DataTable)setOrTable;

    foreach (DataRow row in table.Rows.Cast<DataRow>().ToList())
    {
        DbProviderFactory factory;
        try
        {
            factory = DbProviderFactories.GetFactory(row);
        }
        catch (Exception)
        {
            continue;
        }

        var profType = typeof(MvcMiniProfiler.Data.EFProfiledDbProviderFactory<>).MakeGenericType(factory.GetType());


        DataRow profiled = table.NewRow();
        profiled["Name"] = row["Name"];
        profiled["Description"] = row["Description"];
        profiled["InvariantName"] = row["InvariantName"];
        profiled["AssemblyQualifiedName"] = profType.AssemblyQualifiedName;
        table.Rows.Remove(row);
        table.Rows.Add(profiled);

    }

Для последней версии EF необходимы некоторые рефлексивные взломы и полная бомба.

FileLoadException: The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)

Это было документировано как Frans и Ayende.

Как подключить мои профилирующие фабрики и семью прочным и элегантным способом?
Есть ли другой способ получить мой обратный вызов?

4b9b3361

Ответ 1

Самый простой способ - использовать Обертки трассировки Entity Framework и подключиться к EFTracingConnection CommandFinished. Это не дает вам время начала, но оно дает вам продолжительность (которая вычитается из Now, вероятно, достаточно близка).

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

Если вы просто хотите отслеживать и не нуждаетесь в фактическом обратном вызове, пакет NuGet имеет простую систему отслеживания по умолчанию.

Изменить (добавлена ​​трассировка стека): Обертки трассировки EF не дают вам трассировки стека. Вы можете получить источник и добавить его без особых трудностей, но я думаю, что это повлияет на производительность.

Ответ 2

В то время как это коммерческий продукт, я также настоятельно рекомендую посмотреть EF Prof. Этот инструмент был разработан Айенде (Oren Eini spelling?), Который также сделал NH Prof, Uber Prof (NH + EF Prof) и RavenDB среди других продуктов.

Купив его NH Prof, при настройке NH это было бесценно, и я ожидал бы, что EF Prof будет таким же ценным, соответственно.

Ответ 3

Во-первых: Если вы ищете пользовательскую реализацию, в которой вы можете инициировать собственное событие непосредственно в EF, забудьте об этом. Команда ADO.NET каким-то образом забыла внедрить любые точки расширения и даже забыла реализовать любое ведение журнала (за исключением преобразования ObjectQuery/DbQuery в SQL, но оно не обрабатывает ленивую загрузку или модификации данных).

Я считаю, что каждая реализация трассировки, используемая с EF, выполняется путем создания пользовательского DbProviderFactory, который обертывает реальный factory и обертывает реальные Connection, Command и т.д. Это очень четко описано в упомянутых обертки трассировки.

Есть коммерческие инструменты, которые уже делают то, что вы хотите

  • Упомянутый EF Prof - отличный инструмент, но он стоит 300 долларов за место.
  • Альтернатива Профайлер запросов Huagati. Особенно этот скриншот выглядит так, как вы ищите. Цена намного ниже ($ 40 за место), и она поддерживает Linq-to-sql, Entity Framework и LLBLGen.

Оба инструмента имеют бесплатную пробную версию, поэтому вы можете их скачать и попробовать.

Btw. возможно, вы можете получить много информации, которую ищете от Intelli Trace, если у вас есть VS 2010 Ultimate. Вы можете прочитать обо всех доступных в настоящее время альтернативах в MSDN Magazine.

Я думаю, что есть один большой вопросительный знак - вы используете DbContext или ObjectContext (вы упомянули EFv4.1)? Упомянутые инструменты и трассировочные обертки были созданы для ObjectContext API, поэтому я не уверен, как они работают с DbContext API. Вы все равно можете получить ObjectContext от DbContext, но если инструмент ожидает EntityConnection вместо обычного соединения, это будет проблемой.

Ответ 4

Я могу порекомендовать Entity Framework Profiler и ежемесячную подписку, подходящую для вас, с минимальными затратами $16 US в месяц. У нас были проблемы с производительностью с DbContext, и это обеспечило хорошую визуальную информацию, чтобы исправить это. вы можете интегрировать профилировщик EF с сервером непрерывной интеграции и улучшать свою производительность.

http://efprof.com/