【问题标题】:How to log queries using Entity Framework 7?如何使用 Entity Framework 7 记录查询?
【发布时间】:2015-01-01 02:12:57
【问题描述】:

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

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

【问题讨论】:

    标签: entity-framework entity-framework-core


    【解决方案1】:

    对于那些使用 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
    
        }
    

    【讨论】:

    【解决方案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 位不断变化,我对上述所有答案都感到困惑,因此代码无法编译。从今天(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 输出窗口。我希望这会有所帮助——我敢肯定,几周后,这些位会再次发生变化。

    【讨论】:

    • 文档实际上是正确的,但您需要using Microsoft.Extensions.DependencyInjection;。我遇到了同样的事情。
    • 啊哈!更新了我的帖子。谢谢!
    • 感谢您的更新!我需要看看 RC2 位中有什么新功能。
    • GetInfrastructure() 现在位于 EF Core 的命名空间 Microsoft.EntityFrameworkCore.Infrastructure 中。
    • 呸。这是太多的代码只是得到输出的sql。
    【解决方案4】:

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

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

    【讨论】:

    • 非常实用的答案,以防您现在遇到问题而没有时间构建和部署:) 您还可以将 SQL Profiler 中的查询复制粘贴到 SQL Management Studio 中,以进一步诊断问题所在。
    【解决方案5】:

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

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

    【讨论】:

      【解决方案6】:

      我想我想通了。使用当前的 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);
      }
      

      这是我为这个 sn-p 创建的要点:https://gist.github.com/tonysneed/4cac4f4dae2b22e45ec4

      【讨论】:

      • 您实际上可以在 Startup.cs 中的“Configure”方法中添加一个 ILoggerFactory 参数,然后在那里调用 .AddConsole()。
      • 虽然存在接受 ILoggerFactory 参数的重载配置,但 Startup.cs 仅适用于 Web 应用程序,而不适用于控制台应用程序。 :) 但是,Web 应用程序会受益于将 SQL 记录到“调试输出”窗口。
      【解决方案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】:

        作为上述答案的替代方案,我发现this answer 是迄今为止我最容易推理的解决方案:

        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
        }
        

        【讨论】:

          【解决方案9】:

          使用 ASP.NET Core 2.0 you get SQL logging automatically。不需要做任何额外的事情。

          【讨论】:

            【解决方案10】:

            对于那些只想记录 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-08-22
              • 1970-01-01
              • 1970-01-01
              • 2014-11-11
              • 2018-03-21
              • 2016-08-12
              • 1970-01-01
              相关资源
              最近更新 更多