Как регистрировать запросы с помощью Entity Framework 7?

Я использую Entity Framework 7 на ночном канале сборки (сейчас я использую версию EntityFramework.7.0.0-beta2-11524), и я пытаюсь записать запросы, которые генерирует EF только из любопытства.

Я пишу простую консольную программу, я пробовал использовать ту же технику ведения журнала, которую использует EF6, но DbContext.Database.Log недоступен в Entity Framework 7. Is есть способ зарегистрировать или просто заглянуть в SQL, сгенерированный EF7?

Ответ 1

Для тех, кто использует EF7, ни один из вышеперечисленных не работал у меня. Но так я и работал. (от @avi cherry comment)

В Startup.cs у вас есть метод Configure с кучей конфигураций. Он должен выглядеть следующим образом (в дополнение к вашим материалам).

    public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
    {
        //this is the magic line
        loggerFactory.AddDebug(LogLevel.Debug); // formerly LogLevel.Verbose

        //your other stuff

    }

Ответ 2

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

using System;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Utilities;
using Microsoft.Framework.Logging;

public static class SqlCeDbContextExtensions
{
    public static void LogToConsole(this DbContext context)
    {
        var loggerFactory = ((IAccessor<IServiceProvider>)context).GetService<ILoggerFactory>();
        loggerFactory.AddProvider(new DbLoggerProvider());
    }
}

И DbLoggerProvider реализован здесь: https://github.com/ErikEJ/EntityFramework7.SqlServerCompact/tree/master/src/Provider40/Extensions/Logging

Ответ 3

Я боролся со всеми вышеперечисленными ответами, поскольку биты EF продолжали меняться, поэтому код не компилировался. На сегодняшний день (19Feb2016) с EF7.0.0-rc1-final (Prerelease) и SQLite, вот что работает для меня:

Из документации EF7:

using System;
using System.IO;
using Microsoft.Extensions.Logging;

namespace EFLogging
{
    public class EFLoggerProvider : ILoggerProvider
    {
        public ILogger CreateLogger(string categoryName)
        {
            return new EFLogger();
        }

        public void Dispose()
        {
            // N/A
        }

        private class EFLogger : ILogger
        {
            public IDisposable BeginScopeImpl(object state)
            {
                return null;
            }

            public bool IsEnabled(LogLevel logLevel)
            {
                return true;
            }

            public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
            {
                File.AppendAllText(@".\EF.LOG", formatter(state, exception));
                Console.WriteLine(formatter(state, exception));
            }
        }
    }
}

Используя некоторые идеи выше и документы EF7:

using System;
using Microsoft.Data.Entity;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Extensions.DependencyInjection;  // Add this to EF7 docs code
using Microsoft.Extensions.Logging;

namespace DataAccessLayer
{
    public static class DbContextExtensions
    {
        public static void LogToConsole(this DbContext context)
        {
            var serviceProvider = context.GetInfrastructure<IServiceProvider>();
            var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
            loggerFactory.AddProvider(new EFLoggerProvider(logLevel));
        }
    }
}

EDIT: @jnm2 указал, если вы добавите "using Microsoft.Extensions.DependencyInjection", документы EF7 будут правильными. Спасибо!

И, наконец, в моем методе App.OnStartup:

using (var db = new MyDbContext())
{
    db.LogToConsole();
}

Этот код создаст файл журнала, а также выводит информацию о регистрации в окно вывода Visual Studio. Надеюсь, что это поможет - я уверен, что через несколько недель бит снова изменится.

Ответ 4

Если вы используете MS SQL Server, один из способов, который я использовал в прошлом, - использовать Profiler SQL Server и захватить все взаимодействие с SQL Server, это фиксирует точный SQL-запрос и может быть вырезано n вставлено в SQL Server Management Studio для дальнейшего анализа/анализа. Я знаю, что это напрямую не отвечает на ваш вопрос в Entity Framework, но я нашел этот общий подход очень полезным для любого языка/инструментов.

Один совет в свойствах трассировки при настройке новой трассировки, я нашел полезным настроить выбор событий по умолчанию на вкладке "Выбор событий". В основном я отключу вход/выход из системы аудита, если специально не отслеживать такую ​​проблему.

Ответ 5

С последней версией EF7-beta8, ответ Энтони нуждается в небольшой настройке. Вот что я сделал, чтобы заставить его работать.

internal static class DbContextExtensions
{
    public static void LogToConsole(this DbContext context)
    {
        var loggerFactory = context.GetService<ILoggerFactory>();
        loggerFactory.AddConsole(LogLevel.Verbose);
    }
}

Ответ 6

Думаю, я понял это. С текущими битами EF7 ILoggerFactory регистрируется в контейнере инъекции зависимостей, который использует EF. Вы можете получить ссылку на контейнер, который является IServiceProvider, через свойство ScopedServiceProvider DbContext, когда оно передается в IDbContextServices. Оттуда вы можете получить ILoggerFactory и настроить его с помощью метода расширения AddToConsole из пакета Microsoft.Framework.Logging.Console NuGet.

public static void LogToConsole(this DbContext context)
{
    // IServiceProvider represents registered DI container
    IServiceProvider contextServices = ((IDbContextServices)context).ScopedServiceProvider;

    // Get the registered ILoggerFactory from the DI container
    var loggerFactory = contextServices.GetRequiredService<ILoggerFactory>();

    // Add a logging provider with a console trace listener
    loggerFactory.AddConsole(LogLevel.Verbose);
}

Вот суть, которую я создал для этого фрагмента: https://gist.github.com/tonysneed/4cac4f4dae2b22e45ec4

Ответ 7

Это работало для меня с EF7 rc2-16485:

"EntityFramework.MicrosoftSqlServer": "7.0.0-rc2-16485",
"Microsoft.Extensions.Logging.Console": "1.0.0-rc2-15888",

public static class DbContextExtensions
{
    public static void LogToConsole(this DbContext context)
    {
        var contextServices = ((IInfrastructure<IServiceProvider>) context).Instance;
        var loggerFactory = contextServices.GetRequiredService<ILoggerFactory>();
        loggerFactory.AddConsole(LogLevel.Verbose);
    }
}

Ответ 9

В качестве альтернативы вышеприведенным ответам я нашел этот ответ самым простым решением для меня:

private readonly ILoggerFactory loggerFactory;

// Using dependency injection
public FooContext(ILoggerFactory loggerFactor) {
    this.loggerFactory = loggerFactory;
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
    optionsBuilder.UseLoggerFactory(loggerFactory);    // Register logger in context
}

Ответ 10

Для тех, кто просто хочет, чтобы запросы SQL регистрировались (используя Entity Framework Core с .NET Core 2.0 или выше), используйте следующий код в своем классе DbContext:

public static readonly LoggerFactory MyLoggerFactory
    = new LoggerFactory(new[]
    {
        new ConsoleLoggerProvider((category, level)
            => category == DbLoggerCategory.Database.Command.Name
               && level == LogLevel.Information, true)
    });

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseLoggerFactory(MyLoggerFactory) // Warning: Do not create a new ILoggerFactory instance each time
        .UseSqlServer(
            @"Server=(localdb)\mssqllocaldb;Database=EFLogging;Trusted_Connection=True;ConnectRetryCount=0");

Ссылка: https://docs.microsoft.com/en-us/ef/core/miscellaneous/logging