16

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

我正在编写一个简单的控制台程序,我尝试使用与 EF6相同的日志记录技术,但DbContext.Database.Log在 Entity Framework 7 上不可用。有没有办法记录或只是查看 EF7 生成的 SQL?

4

10 回答 10

8

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

在您的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

    }
于 2015-11-19T11:24:13.710 回答
7

您可以使用此代码登录到控制台,我相信它稍后会被包装在一个更简单的 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

于 2014-11-05T01:10:49.753 回答
5

由于 EF 位不断变化,我在上述所有答案中都遇到了困难,因此代码无法编译。截至今天(2016 年 2 月 19 日),使用 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));
        }
    }
}

编辑:@jnm2 指出如果您添加“使用 Microsoft.Extensions.DependencyInjection”,EF7 文档是正确的。谢谢!

最后,在我的 App.OnStartup 方法中:

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

此代码将创建一个日志文件并将日志信息输出到 Visual Studio 输出窗口。我希望这会有所帮助——我敢肯定,几周后,这些位会再次发生变化。

于 2016-02-19T23:56:32.747 回答
4

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

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

于 2014-11-05T00:47:23.510 回答
4

使用最新版本的 EF7-beta8,Anthony 的回答需要稍作调整。这是我为使其正常工作所做的工作。

internal static class DbContextExtensions
{
    public static void LogToConsole(this DbContext context)
    {
        var loggerFactory = context.GetService<ILoggerFactory>();
        loggerFactory.AddConsole(LogLevel.Verbose);
    }
}
于 2015-11-09T21:26:52.433 回答
3

我想我想通了。使用当前的 EF7 位,ILoggerFactory 注册到 EF 正在使用的依赖注入容器。在将容器强制转换为 IDbContextServices 时,您可以通过 DbContext 的 ScopedServiceProvider 属性获取对容器的引用,该容器是 IServiceProvider。从那里,您可以获取 ILoggerFactory 并使用 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);
}

这是我为此片段创建的要点:https ://gist.github.com/tonysneed/4cac4f4dae2b22e45ec4

于 2014-12-26T15:03:01.530 回答
2

这对我来说适用于 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);
    }
}
于 2015-12-11T15:14:21.667 回答
2

使用 ASP.NET Core 2.0 ,您可以自动获得 SQL 日志记录。无需做任何额外的事情。

于 2017-08-31T17:04:13.167 回答
2

作为上述答案的替代方案,我发现这个答案是迄今为止我推理的最简单的解决方案:

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
}
于 2017-01-29T04:24:42.620 回答
0

对于那些只想记录 SQL 查询的人(使用 .NET Core 2.0 或更高版本的 Entity Framework Core),请在 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

于 2019-04-21T11:22:32.650 回答