Как регистрировать запросы с помощью 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);
}
}
Ответ 8
С ASP.NET Core 2.0 вы автоматически регистрируете SQL-журнал. Не нужно ничего делать.
Ответ 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