2014-11-05 21 views
12

Tôi đang sử dụng Entity Framework 7 trên kênh xây dựng hàng đêm (hiện tại tôi đang sử dụng phiên bản EntityFramework.7.0.0-beta2-11524) và tôi đang cố gắng ghi lại các truy vấn mà EF tạo ra chỉ vì tò mò.Cách đăng nhập truy vấn bằng Entity Framework 7?

Tôi đang viết một chương trình điều khiển đơn giản, tôi đã thử sử dụng same logging technic mà EF6 sử dụng, nhưng DbContext.Database.Log không khả dụng trên Khung thực thể 7. Có cách nào để ghi nhật ký hoặc chỉ xem qua SQL được tạo bởi EF7 không?

Trả lời

8

Đối với những người sử dụng EF7 không có điều nào ở trên làm việc cho tôi. Nhưng đây là cách tôi làm cho nó hoạt động. (từ nhận xét của @avi cherry)

Trong số Startup.cs bạn có thể có phương thức Cấu hình với nhiều cấu hình trong đó. Nó sẽ trông giống như dưới đây (ngoài công cụ của bạn).

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

     //your other stuff 

    } 
+1

Tôi tự hỏi nếu có một cách để đăng nhập chỉ là các truy vấn EF mà không cần mọi thứ khác. –

+1

@MahmoudAli Tài liệu EF Core cho biết cách lọc trên một số danh mục nhật ký nhất định: https://docs.microsoft.com/en-us/ef/core/miscellaneous/logging –

3

Nếu bạn đang sử dụng MS SQL Server, một trong những cách tôi đã sử dụng trong quá khứ là để tận dụng các SQL Server Profiler và nắm bắt tất cả tương tác với SQL Server, này nắm bắt được SQL chính xác trình và có thể được cắt n dán vào SQL Server Management Studio để xem xét/phân tích thêm. Tôi biết điều này không trực tiếp trả lời câu hỏi của bạn trên Khung thực thể, nhưng tôi đã tìm thấy cách tiếp cận chung này rất hữu ích cho bất kỳ ngôn ngữ/công cụ nào.

Một mẹo nằm trong Thuộc tính theo dõi khi thiết lập một dấu vết mới, tôi thấy hữu ích khi điều chỉnh lựa chọn sự kiện mặc định trong tab Lựa chọn sự kiện. Chủ yếu là tôi tắt Đăng nhập kiểm tra/Đăng xuất trừ khi theo dõi cụ thể vấn đề như vậy.

+1

Câu trả lời rất thiết thực trong trường hợp bạn gặp sự cố NGAY BÂY GIỜ và không có thời gian để xây dựng và triển khai :) Ngoài ra bạn có thể sao chép-dán truy vấn từ SQL Profiler vào SQL Management Studio để chẩn đoán thêm. –

7

Bạn có thể đăng nhập vào giao diện điều khiển sử dụng mã này, tôi chắc chắn nó sẽ được bọc trong một api đơn giản sau:

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()); 
    } 
} 

Và DbLoggerProvider được thực hiện ở đây: https://github.com/ErikEJ/EntityFramework7.SqlServerCompact/tree/master/src/Provider40/Extensions/Logging

+2

Có vẻ như đội EF chỉ thay đổi điều này một lần nữa: https://github.com/aspnet/EntityFramework/commit/dec9dc11abd462f6a8767b92111114a1fb295f6f –

+0

Có ai tìm cách đăng nhập vào bàn điều khiển với các bit EF7 hiện tại không? –

+0

Bạn thêm địa chỉ này ở đâu? Dường như không hoạt động nữa. –

3

Tôi nghĩ rằng tôi figured điều này. Với các bit EF7 hiện tại, ILoggerFactory được đăng ký với thùng chứa phụ thuộc mà EF đang sử dụng. Bạn có thể lấy một tham chiếu đến vùng chứa, là một IServiceProvider, thông qua thuộc tính ScopedServiceProvider của DbContext khi nó được truyền tới IDbContextServices. Từ đó, bạn có thể lấy ILoggerFactory và cấu hình nó bằng phương thức mở rộng AddToConsole từ gói 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); 
} 

Dưới đây là một ý chính tôi đã tạo cho đoạn này: https://gist.github.com/tonysneed/4cac4f4dae2b22e45ec4

+0

Rất tốt và cảm ơn Gist! –

+1

Bạn thực sự có thể thêm một tham số ILoggerFactory vào phương thức "Configure" của bạn trong Startup.cs và gọi .AddConsole() vào nó ngay tại đó. –

+0

Trong khi có quá tải cấu hình chấp nhận tham số ILoggerFactory, Startup.cs chỉ áp dụng cho các ứng dụng web, chứ không áp dụng cho các ứng dụng giao diện điều khiển. Tuy nhiên, các ứng dụng web sẽ được hưởng lợi từ việc ghi nhật ký SQL vào cửa sổ Debug Output. –

4

Với phiên bản mới nhất của EF7-beta8, câu trả lời của Anthony cần một chút tinh chỉnh. Đây là những gì tôi đã làm để làm cho nó hoạt động.

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

này làm việc cho tôi với 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); 
    } 
} 
5

tôi vật lộn với tất cả các câu trả lời ở trên là các bit EF liên tục thay đổi, vì vậy mã sẽ không biên dịch. Tính đến hôm nay (19Feb2016) với EF7.0.0-rc1 kết (Prerelease) và SQLite, đây là những gì làm việc cho tôi:

Từ các tài liệu 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)); 
      } 
     } 
    } 
} 

Sử dụng một số ý tưởng trên và EF7 Documents:

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 chỉ ra nếu bạn thêm "bằng cách sử dụng Microsoft.Extensions.DependencyInjection", các tài liệu EF7 là chính xác. Cảm ơn!

Và cuối cùng, trong phương pháp App.OnStartup tôi:

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

Mã này sẽ tạo ra một tập tin đăng nhập và thông tin đăng nhập cũng ra đến cửa sổ trực quan ra Studio. Tôi hy vọng điều này sẽ giúp - Tôi chắc chắn trong một vài tuần, các bit sẽ thay đổi một lần nữa.

+1

Tài liệu thực sự đúng nhưng bạn cần 'sử dụng Microsoft. Tiện ích mở rộng.DependencyInjection; '. Tôi chạy vào cùng một điều. – jnm2

+0

Aha! Đã cập nhật bài đăng của tôi. Cảm ơn! – RandyB

+1

vẫn hoạt động với EF7.0.0-rc2-16649 – MadDeveloper

1

Để thay thế cho câu trả lời ở trên, tôi thấy this answer đến nay là giải pháp dễ nhất cho tôi để suy luận về:

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 
} 
Các vấn đề liên quan