Entity framework 如何使用Entity Framework 7记录查询?

Entity framework 如何使用Entity Framework 7记录查询?,entity-framework,entity-framework-core,Entity Framework,Entity Framework Core,我在夜间构建频道上使用EntityFramework 7(现在我使用的是EntityFramework.7.0.0-beta2-11524版本),我正试图记录EF出于好奇而生成的查询 我正在编写一个简单的控制台程序,我尝试使用EF6使用的,但是在EntityFramework7上不能使用DbContext.Database.Log。是否有办法记录或查看EF7生成的SQL?如果您使用的是MS SQL Server,我过去使用的一种方法是使用SQL Server Profiler并捕获与SQL Se

我在夜间构建频道上使用EntityFramework 7(现在我使用的是EntityFramework.7.0.0-beta2-11524版本),我正试图记录EF出于好奇而生成的查询


我正在编写一个简单的控制台程序,我尝试使用EF6使用的,但是在EntityFramework7上不能使用
DbContext.Database.Log
。是否有办法记录或查看EF7生成的SQL?

如果您使用的是MS SQL Server,我过去使用的一种方法是使用SQL Server Profiler并捕获与SQL Server的所有交互,这将捕获提交的确切SQL,并可剪切粘贴到SQL Server Management Studio中以供进一步查看/分析。 我知道这并不能直接回答您关于实体框架的问题,但我发现这种通用方法对于任何语言/工具都非常有用


设置新跟踪时,跟踪属性中有一个提示,我发现在“事件选择”选项卡中调整事件的默认选择非常有用。大多数情况下,我会关闭审核登录/注销,除非专门跟踪此类问题。

您可以使用此代码登录到控制台,我相信稍后它将封装在一个更简单的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());
    }
}
使用系统;
使用Microsoft.Data.Entity.Infrastructure;
使用Microsoft.Data.Entity.Utilities;
使用Microsoft.Framework.Logging;
公共静态类SqlCeDbContextExtensions
{
公共静态void LogToConsole(此DbContext上下文)
{
var loggerFactory=((IAccessor)context.GetService();
AddProvider(新的DbLoggerProvider());
}
}

DbLoggerProvider在这里实现:

我想我已经解决了这个问题。使用当前的EF7位,iLogger工厂在EF使用的依赖项注入容器中注册。当容器强制转换为IDbContextServices时,您可以通过DbContext的ScopedServiceProvider属性获取对容器(IServiceProvider)的引用。从那里,您可以获取iLogger工厂,并使用Microsoft.Framework.Logging.Console NuGet包中的AddToConsole扩展方法对其进行配置

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);
}
publicstaticvoidlogtoconsole(此DbContext上下文)
{
//IServiceProvider表示已注册的DI容器
IServiceProvider contextServices=((IDbContextServices)上下文);
//从DI容器获取已注册的iLogger工厂
var loggerFactory=contextServices.GetRequiredService();
//添加带有控制台跟踪侦听器的日志提供程序
AddConsole(LogLevel.Verbose);
}

以下是我为这段代码创建的要点:

对于最新版本的EF7-beta8,Anthony的答案需要稍加修改。这是我为让它工作所做的

internal static class DbContextExtensions
{
    public static void LogToConsole(this DbContext context)
    {
        var loggerFactory = context.GetService<ILoggerFactory>();
        loggerFactory.AddConsole(LogLevel.Verbose);
    }
}
内部静态类DbContextensions
{
公共静态void LogToConsole(此DbContext上下文)
{
var loggerFactory=context.GetService();
AddConsole(LogLevel.Verbose);
}
}

对于那些使用EF7的人来说,以上这些都不适合我。但我就是这样让它工作的。(摘自@avi cherry的评论)

Startup.cs中,您可能有一个配置方法,其中包含一系列配置。它应该如下所示(除了你的东西)


这在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);
    }
}
“EntityFramework.MicrosoftSqlServer”:“7.0.0-rc2-16485”,
“Microsoft.Extensions.Logging.Console”:“1.0.0-rc2-15888”,
公共静态类DbContextensions
{
公共静态void LogToConsole(此DbContext上下文)
{
var contextServices=((IInfrastructure)context).Instance;
var loggerFactory=contextServices.GetRequiredService();
AddConsole(LogLevel.Verbose);
}
}

由于EF位不断变化,所以代码无法编译,我很难找到上述所有答案。截至今天(2016年2月19日),EF7.0.0-rc1-final(预发行版)和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));
            }
        }
    }
}

此代码将创建一个日志文件,并将日志信息输出到VisualStudio输出窗口。我希望这能有所帮助——我相信几周后,bits将再次改变。

作为上述答案的替代方案,我找到了迄今为止最简单的解决方案:

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
}

使用ASP.NET Core 2.0。无需执行任何额外操作。

对于那些只希望记录SQL查询的人(使用Entity Framework Core with.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");

参考资料:

看起来EF团队又改变了这一点:有人找到了使用当前EF7位登录控制台的方法吗?您在哪里添加了这个?似乎不再有效。实际上,您可以在Startup.cs中向“Configure”方法添加一个ILogger工厂参数,并在那里调用.AddConsole()。虽然存在接受ILogger工厂参数的配置重载,但Startup.cs仅适用于web应用程序,而不适用于控制台应用程序。:)但是,web应用程序将受益于将SQL记录到“调试输出”窗口。我想知道是否有办法只记录EF查询而不记录其他内容。@MahmoudAli EF Core文档说明了如何对某些日志类别进行筛选:文档实际上是正确的,但您需要使用Microsoft.Extensions.DependencyInjection。我遇到了同样的事情。啊哈!更新了我的帖子。谢谢谢谢你的更新!我需要看看RC2 bits中有什么新功能。GetInfrastructure()现在位于命名空间Microsoft.EntityFrameworkCore.Infrastructure中的EF Core.yack中。这是一种方式,太多的代码只获取输出的sql。如果您现在有问题并且没有时间构建和部署,这是一个非常实用的答案:)此外,您还可以将粘贴查询从sql Profiler复制到sql Management Studio中,以进一步诊断错误。
using (var db = new MyDbContext())
{
    db.LogToConsole();
}
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
}
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");