Entity Framework 4.1 - EFTracingProvider

断了今生、忘了曾经 提交于 2019-11-28 04:26:02

Yes, you can. I'm using the community version with both database-first DbContexts and code-first DbContexts. This answer is based on a discussion thread on the project site.

For database-first/designer DbContexts (via ADO.NET DbContext Generator templates), you can simply add the following constructor:

public abstract class MyDbContext : DbContext
{
    protected MyDbContext(string nameOrConnectionString)
        : base(EFTracingProviderUtils.CreateTracedEntityConnection(nameOrConnectionString), true)
    {
        // enable sql tracing
        ((IObjectContextAdapter) this).ObjectContext.EnableTracing();
    }
}

For code first DbContexts its a bit more complicated since the EFTracingProvider wants a full entity connection string. You have to create an instance of EFTracingConnection manually. The following example will work for both database first and code first contexts.

public abstract class MyDbContext : DbContext
{
    protected MyDbContext(string nameOrConnectionString)
        : base(CreateTracingConnection(nameOrConnectionString), true)
    {
        // enable sql tracing
        ((IObjectContextAdapter) this).ObjectContext.EnableTracing();
    }

    private static DbConnection CreateTracingConnection(string nameOrConnectionString)
    {
        try
        {
            // this only supports entity connection strings http://msdn.microsoft.com/en-us/library/cc716756.aspx
            return EFTracingProviderUtils.CreateTracedEntityConnection(nameOrConnectionString);
        }
        catch (ArgumentException)
        {
            // an invalid entity connection string is assumed to be a normal connection string name or connection string (Code First)

            ConnectionStringSettings connectionStringSetting =
                ConfigurationManager.ConnectionStrings[nameOrConnectionString];
            string connectionString;
            string providerName;

            if (connectionStringSetting != null)
            {
                connectionString = connectionStringSetting.ConnectionString;
                providerName = connectionStringSetting.ProviderName;
            }
            else
            {
                providerName = "System.Data.SqlClient";
                connectionString = nameOrConnectionString;
            }

            return CreateTracingConnection(connectionString, providerName);
        }
    }

    private static EFTracingConnection CreateTracingConnection(string connectionString, string providerInvariantName)
    {
        // based on the example at http://jkowalski.com/2010/04/23/logging-sql-statements-in-entity-frameworkcode-first/
        string wrapperConnectionString =
            String.Format(@"wrappedProvider={0};{1}", providerInvariantName, connectionString);

        EFTracingConnection connection =
            new EFTracingConnection
                {
                    ConnectionString = wrapperConnectionString
                };

        return connection;
    }
}

Whilst the previous answers work, I've found them problematic, a much simpler solution is to use the Clutch.Diagnostics.EntityFramework package from NuGet that uses MiniProfiler behind the scenes. It is significantly simpler to get working than EFTracingProvider, and a much more flexible solution.

The project is on GitHub at https://github.com/Kukkimonsuta/Clutch

For EFTracingProvider like functionality install the NuGet package and then implement IDbTracingListener like this:

using System;
using System.Data.Common;
using System.Diagnostics;
using Clutch.Diagnostics.EntityFramework;

/// <summary>
/// 
/// </summary>
public class DbTracingListener : IDbTracingListener
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="connection"></param>
    /// <param name="command"></param>
    /// <param name="result"></param>
    /// <param name="duration"></param>
    public void CommandExecuted(DbConnection connection, DbCommand command, object result, TimeSpan duration)
    {
        Debug.WriteLine(command.CommandText);
        Debug.WriteLine(string.Format("Executed in: {0}", duration));
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="connection"></param>
    /// <param name="command"></param>
    public void CommandExecuting(DbConnection connection, DbCommand command)
    {

    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="connection"></param>
    /// <param name="command"></param>
    /// <param name="exception"></param>
    /// <param name="duration"></param>
    public void CommandFailed(DbConnection connection, DbCommand command, Exception exception, TimeSpan duration)
    {

    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="connection"></param>
    /// <param name="command"></param>
    /// <param name="result"></param>
    /// <param name="duration"></param>
    public void CommandFinished(DbConnection connection, DbCommand command, object result, TimeSpan duration)
    {

    }
}

If you are using DBContext and MVC Model First, meaning using EntityConnections then the following sample code should be all you need:

    public partial class BrickHouseFitnessContext : DbContext
{

    public BrickHouseFitnessContext(): base(EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(ConfigurationManager.ConnectionStrings["BrickHouseFitnessContext"].ConnectionString, "EFTracingProvider"), true)
    {
    }

Also:

In the Web.Config file add the following sections:

  <system.data>
<DbProviderFactories>
  <add name="EF Tracing Data Provider" invariant="EFTracingProvider" description="Tracing Provider Wrapper" type="EFTracingProvider.EFTracingProviderFactory, EFTracingProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b" />
  <add name="EF Generic Provider Wrapper" invariant="EFProviderWrapper" description="Generic Provider Wrapper" type="EFProviderWrapperToolkit.EFProviderWrapperFactory, EFProviderWrapperToolkit, Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b" />
</DbProviderFactories>

and:

    <add key="EFTracingProvider.logToConsole" value="true" />
<add key="EFTracingProvider.logToFile" value="C:\BrickHouseFitnessSqlLog.txt" />

There is no need to include the ExtendedEntities or the other ObjectContext derived class mentioned in the original article. Run that code and you should see your log file as specified, with all the SQL commands in it. I am bypassing database intialization when tracing is enabled,

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!