Оболочка провайдера трассировки Entity Framework без конфигурационных файлов - PullRequest
4 голосов
/ 26 декабря 2011

Я хотел бы использовать первый подход Entity Framework Code с базой данных SQLCE4. Кажется, все действительно хорошо, но у меня проблема с отладкой SQL-запросов. Я обнаружил, что EFTracing из http://efwrappers.codeplex.com/ должен быть именно тем, что мне нужно, но я не знаю, как его использовать без файла app.config. Я не большой поклонник этой конфигурации. Я хочу использовать только код C # для настройки и запуска. Я думаю, что должно быть хорошо использовать код, подобный этому:

using (System.Data.Common.DbConnection c = 
    new EFTracingProvider.EFTracingConnection(
        new System.Data.SqlServerCe.SqlCeConnection(conn)))
{
    using (var context = new MyContext(c))
    {
        var a = from data in context.Projects select data;
    }
}

Но это не работает. Выдает исключение:

Невозможно определить имя провайдера для соединения типа EFTracingProvider.EFTracingConnection.

Есть ли простой способ, как правильно создать упакованное соединение только в коде?

Ответы [ 3 ]

6 голосов
/ 27 декабря 2011

Решением для моей проблемы является следующий объект DbContext.

public class MyContext : DbContext
{
  public MyContext()
    : base(CreateConnection("Data Source=file.sdf", 
                            "System.Data.SqlServerCe.4.0"), true)
  { }

  public DbSet<Project> Projects { get; set; }

  public static bool TraceEnabled = true;

  private static DbConnection CreateConnection(string connectionString, 
                                               string providerInvariantName)
  {
    DbConnection connection = null;
    if (TraceEnabled)
    {
      EFTracingProviderConfiguration.RegisterProvider();
      EFTracingProviderConfiguration.LogToConsole = true;
      string wrapperConnectionString = String.Format(@"wrappedProvider={0};{1}",
         providerInvariantName, connectionString);
      connection = new EFTracingConnection() 
      { 
        ConnectionString = wrapperConnectionString 
      };
    }
    else
    {
      DbProviderFactory factory = DbProviderFactories.GetFactory(providerInvariantName);
      connection = factory.CreateConnection();
      connection.ConnectionString = connectionString;
    }
    return connection;
  }
}

Так что теперь я могу использовать только контекст, и соединение создается автоматически для обернутого или развернутого SqlCe в зависимости от свойства TraceEnabled.

using (var context = new MyContext())
{
    var a = context.Projects.FirstOrDefault();
}
0 голосов
/ 26 декабря 2011

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

public partial class LoggedContext : MyContext
{
    public LoggedContext()
        : this("name=MyEntities")    // Adjust this to match your entities
    {
    }

    public LoggedContext(string connectionString)
        : base(EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(connectionString)
    {
    }

    private EFTracingConnection TracingConnection
    {
        get { return this.UnwrapConnection<EFTracingConnection>(); }
    }

    public event EventHandler<CommandExecutionEventArgs> CommandExecuting
    {
        add { this.TracingConnection.CommandExecuting += value; }
        remove { this.TracingConnection.CommandExecuting -= value; }
    }

    public event EventHandler<CommandExecutionEventArgs> CommandFinished
    {
        add { this.TracingConnection.CommandFinished += value; }
        remove { this.TracingConnection.CommandFinished -= value; }
    }

    public event EventHandler<CommandExecutionEventArgs> CommandFailed
    {
        add { this.TracingConnection.CommandFailed += value; }
        remove { this.TracingConnection.CommandFailed -= value; }
    }
}

У меня также есть статический класс, который определяет метод вывода трассировки и имеет статический метод для инициализации трассировки. Здесь:

public static class EFTracingExtensions
{
    private static ILogger _logger;

    public static void InitSqlTracing(ILogger logger)
    {
        _logger = logger;

        EFTracingProviderConfiguration.RegisterProvider();

        if (logger.IsLoggingEnabled())          // Don't add logging hooks if logging isn't enabled
        {
            EFTracingProviderConfiguration.LogAction = new Action<CommandExecutionEventArgs>(AppendSqlLog);
        }
    }

    private static void AppendSqlLog(CommandExecutionEventArgs e)
    {
        if (e.Status != CommandExecutionStatus.Executing)               // we only care about Finished and Failed
        {
            StringBuilder msg = new StringBuilder(e.ToTraceString().TrimEnd());
            msg.Append(Environment.NewLine);
            if (e.Result is SqlDataReader)
            {
                int rows = ((SqlDataReader)e.Result).HasRows ? ((SqlDataReader)e.Result).RecordsAffected : 0;
                msg.AppendFormat("*** {0} rows affected", rows);
            }
            else if (e.Result is int)
            {
                msg.AppendFormat("*** result: {0}", e.Result);
            }
            else
            {
                msg.AppendFormat("*** finished, result: {0}", e.Result);
            }

            msg.Append(Environment.NewLine);
            msg.AppendFormat(" [{0}] [{1}] in {2} seconds", e.Method, e.Status, e.Duration);
            _logger.Log(msg.ToString(), LoggerCategories.SQL);
        }
    }
}

ILogger - это интерфейс регистрации, который я использую. Вам необходимо заменить свой собственный интерфейс / методы.

Метод InitSqlTracing вызывается один раз при запуске моей программы, а затем класс LoggedContext используется для регистрации всего SQL, сгенерированного Entity Framework.

Собираем все вместе с вашим примером кода:

EFTracingExtensions.InitSqlTracing(logger);    // only call this once

using (var context = new LoggedContext())
{
    var a = from data in context.Projects select data;
}
0 голосов
/ 26 декабря 2011

Подлинный способ отследить запросы SQL - это вызвать метод ToString следующим образом:

var t = from c in _entities.CompanyDetail
        select c;

string test = t.ToString();

Я не знаю EFTracing, но вы можете попробовать MVCMiniProfiler . Несмотря на название MVCMiniProfiler также предоставляет профилирование SQL-запросов и работает без конфигурационного файла.

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