如何正确分析实体框架?

时间:2011-07-07 15:36:30

标签: c# .net entity-framework entity-framework-4

为了从EF 4.1获得单个回调,我可以编写的最少量代码是什么,提供以下内容:

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

目前我们使用的是一个似乎在泄露性能的令人讨厌的黑客,我很好奇我们如何能够在对应用程序产生最小影响的情况下实现此回调。


我们可以通过Mini Profilerhacking around中进行连接 - 最后我们更改了Database.DefaultConnectionFactory但是默认工厂的工作意味着您无法同时运行两个分析工厂。所以我们采取了更激进的路线。


常用的技术非常简单,您实施:DbProviderFactoryIDbConnectionFactoryDbProviderServicesDbConnectionDbCommandDbDataReader这样他们就可以拦截电话和个人资料。

到目前为止,很容易......但是当你试图连接它时它会变得混乱:

   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)

FransAyende都记录了这一点。

如何以健壮和优雅的方式连接我的剖析工厂和家庭? 有没有其他方法来获得我的回调?

4 个答案:

答案 0 :(得分:10)

最简单的方法是使用Entity Framework tracing wrappers并挂钩EFTracingConnection的{​​{1}}。它没有给你开始时间,但它确实给你持续时间(从CommandFinished减去,可能足够接近)。

我将代码影响称为“中等”,因为您必须更改对现有上下文类的引用。不过,这很简单。

如果您只想跟踪并且不需要实际的回调,则NuGet包有一个simple default tracing system

编辑(添加了堆栈跟踪): EF跟踪包装器不会为您提供堆栈跟踪。您可以获得源代码并添加它而不会有太大的困难,但我认为这会影响性能。

答案 1 :(得分:7)

虽然它是商业产品,但我强烈建议您查看EF Prof。这个工具是由Ayende(Oren Eini拼写?)开发的,他还在其他产品中创建了NH Prof,优步教授(NH + EF教授)和RavenDB。

购买了他的NH教授,在调整NH时它是非常宝贵的,我希望EF教授分别同样有价值。

答案 2 :(得分:0)

首先:如果您正在寻找自定义实现,您可以直接在EF中触发自己的事件而忘记它。 ADO.NET团队不知何故忘记实现任何扩展点,他们甚至忘记实现任何日志记录(除了将ObjectQuery / DbQuery转换为SQL,但它不处理延迟加载或数据修改)。

我相信与EF一起使用的每个跟踪实现都是通过创建自定义DbProviderFactory来完成的,该自定义Connection包装真实工厂并包装真实CommandObjectContext等。这在提到的跟踪中非常清楚地描述包装

有商业工具已经做了你想做的事情

  • 提到EF教授是一个很好的工具,但每个座位花费​​300美元。
  • 替代方案是Huagati Query Profiler。特别是this screen shot看起来像你在找什么。价格低得多(每个座位40美元),它支持Linq-to-sql,Entity Framework和LLBLGen。

这两个工具都有免费试用版,因此您可以下载并试用它们。

顺便说一下。如果您拥有VS 2010 Ultimate,也许您可​​以从Intelli Trace中获取大量信息。您可以在MSDN Magazine中了解所有当前可用的替代方案。

我认为有一个很大的问号 - 您使用的是DbContext还是ObjectContext(您提到过EFv4.1)?为ObjectContext API创建了提到的工具和跟踪包装器,因此我不确定它们如何与DbContext API一起使用。您仍然可以从DbContext获得EntityConnection,但如果该工具需要{{1}}而不是常见连接,那么这将是一个问题。

答案 3 :(得分:0)

我可以推荐Entity Framework Profiler,每月订阅最适合您需要,每月最低费用为16美元。我们在DbContext上遇到了一些性能问题,它提供了很好的视觉信息来解决这些问题。您可以将EF Profiler与持续集成服务器集成,并不断提高性能。

http://efprof.com/