entity-framework - snippet - title tag




Wie kann ich das vom Entity Framework generierte SQL anzeigen? (11)

Anwendbar für EF 6.0 und höher: Für diejenigen von Ihnen, die mehr über die Protokollierungsfunktionalität erfahren und die bereits gegebenen Antworten ergänzen möchten.

Jeder von der EF an die Datenbank gesendete Befehl kann jetzt protokolliert werden. Verwenden Sie die DBContext.Database.Log property , um die generierten Abfragen von EF 6.x DBContext.Database.Log property

Was wird protokolliert?

 - SQL for all different kinds of commands. For example:
    - Queries, including normal LINQ queries, eSQL queries, and raw queries from methods such as SqlQuery.
    - Inserts, updates, and deletes generated as part of SaveChanges
    - Relationship loading queries such as those generated by lazy loading
 - Parameters
 - Whether or not the command is being executed asynchronously
 - A timestamp indicating when the command started executing
 - Whether or not the command completed successfully, failed by throwing an exception, or, for async, was canceled
 - Some indication of the result value
 - The approximate amount of time it took to execute the command. Note that this is the time from sending the command to getting the result object back. It does not include time to read the results.

Beispiel:

using (var context = new BlogContext()) 
{ 
    context.Database.Log = Console.Write; 

    var blog = context.Blogs.First(b => b.Title == "One Unicorn"); 

    blog.Posts.First().Title = "Green Eggs and Ham"; 

    blog.Posts.Add(new Post { Title = "I do not like them!" }); 

    context.SaveChangesAsync().Wait(); 
}

Ausgabe:

SELECT TOP (1)
    [Extent1].[Id] AS [Id],
    [Extent1].[Title] AS [Title]
    FROM [dbo].[Blogs] AS [Extent1]
    WHERE (N'One Unicorn' = [Extent1].[Title]) AND ([Extent1].[Title] IS NOT NULL)
-- Executing at 10/8/2013 10:55:41 AM -07:00
-- Completed in 4 ms with result: SqlDataReader

SELECT
    [Extent1].[Id] AS [Id],
    [Extent1].[Title] AS [Title],
    [Extent1].[BlogId] AS [BlogId]
    FROM [dbo].[Posts] AS [Extent1]
    WHERE [Extent1].[BlogId] = @EntityKeyValue1
-- EntityKeyValue1: '1' (Type = Int32)
-- Executing at 10/8/2013 10:55:41 AM -07:00
-- Completed in 2 ms with result: SqlDataReader

UPDATE [dbo].[Posts]
SET [Title] = @0
WHERE ([Id] = @1)
-- @0: 'Green Eggs and Ham' (Type = String, Size = -1)
-- @1: '1' (Type = Int32)
-- Executing asynchronously at 10/8/2013 10:55:41 AM -07:00
-- Completed in 12 ms with result: 1

INSERT [dbo].[Posts]([Title], [BlogId])
VALUES (@0, @1)
SELECT [Id]
FROM [dbo].[Posts]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()
-- @0: 'I do not like them!' (Type = String, Size = -1)
-- @1: '1' (Type = Int32)
-- Executing asynchronously at 10/8/2013 10:55:41 AM -07:00
-- Completed in 2 ms with result: SqlDataReader

So loggen Sie sich in eine externe Datei ein:

using (var context = new BlogContext()) 
{  
    using (var sqlLogFile = new StreamWriter("C:\\temp\\LogFile.txt"))
    {          
         context.Database.Log = sqlLogFile.Write;     
         var blog = context.Blogs.First(b => b.Title == "One Unicorn"); 
         blog.Posts.First().Title = "Green Eggs and Ham"; 
         context.SaveChanges();
   }
}

Weitere Informationen finden Sie hier: Protokollieren und Abfangen von Datenbankoperationen

Wie kann ich das vom Entitätsframework generierte SQL anzeigen?

(In meinem speziellen Fall verwende ich den mysql-Provider - wenn es darauf ankommt)


Beginnend mit EF6.1 können Sie Interceptors verwenden, um einen Datenbanklogger zu registrieren. Siehe Kapitel "Interceptors" und "Logging Database Operations" zu einer Datei here

<interceptors> 
  <interceptor type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework"> 
    <parameters> 
      <parameter value="C:\Temp\LogOutput.txt"/> 
      <parameter value="true" type="System.Boolean"/> 
    </parameters> 
  </interceptor> 
</interceptors>

Für diejenigen, die Entity Framework 6 und höher verwenden, müssen Sie, wenn Sie die Ausgabe-SQL in Visual Studio anzeigen möchten (wie ich), die neue Protokollierungs- / Überwachungsfunktionalität verwenden.

Durch das Hinzufügen der folgenden Zeile wird das generierte SQL (zusammen mit zusätzlichen ausführungsbezogenen Details) im Visual Studio-Ausgabebereich ausgegeben:

using (MyDatabaseEntities context = new MyDatabaseEntities())
{
    context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
    // query the database using EF here.
}

Weitere Informationen zum Anmelden bei EF6 in dieser raffinierten Blogserie: http://blog.oneunicorn.com/2013/05/08/ef6-sql-logging-part-1-simple-logging/

Hinweis: Stellen Sie sicher, dass Sie Ihr Projekt im DEBUG-Modus ausführen.


Für mich, EF6 und Visual Studio 2015 benutzend, habe ich query im unmittelbaren Fenster eingegeben und es gab mir die generierte SQL-Anweisung


In meinem Fall für EF 6+, anstatt dies im Direktfenster zu verwenden, um den Abfrage-String zu finden:

var sql = ((System.Data.Entity.Core.Objects.ObjectQuery)query).ToTraceString();

Am Ende musste ich das verwenden, um den generierten SQL-Befehl zu erhalten:

var sql = ((System.Data.Entity.Infrastructure.DbQuery<<>f__AnonymousType3<string,string,string,short,string>>)query).ToString();

Natürlich ist Ihre anonyme Signatur möglicherweise anders.

HTH.


Meine Antwort adressiert EF Core . Ich verweise auf dieses Github-Problem und die Dokumentation zur Konfiguration von DbContext :

Einfach

OnConfiguring Sie die OnConfiguring Methode Ihrer DbContext Klasse ( YourCustomDbContext ) wie hier gezeigt , um einen ConsoleLoggerProvider zu verwenden. Ihre Abfragen sollten sich an der Konsole anmelden:

public class YourCustomDbContext : DbContext
{
    #region DefineLoggerFactory
    public static readonly LoggerFactory MyLoggerFactory
        = new LoggerFactory(new[] {new ConsoleLoggerProvider((_, __) => true, true)});
    #endregion


    #region RegisterLoggerFactory
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
            .UseLoggerFactory(MyLoggerFactory) // Warning: Do not create a new ILoggerFactory instance each time
            //.UseSqlServer("...");
    #endregion
}

Komplex

Dieser komplexe Fall vermeidet das Überschreiben der DbContext OnConfiguring Methode. , was in den Dokumenten nicht empfohlen wird: "Dieser Ansatz eignet sich nicht zum Testen, es sei denn, die Tests zielen auf die vollständige Datenbank ab."

Dieser komplexe Fall verwendet:

  • Die IServiceCollection in der Startup Klasse ConfigureServices Methode (statt die OnConfiguring Methode zu überschreiben; der Vorteil ist eine lockere Verbindung zwischen dem DbContext und dem ILoggerProvider Sie verwenden möchten)
  • Eine Implementierung von ILoggerProvider (anstatt die ConsoleLoggerProvider gezeigte ConsoleLoggerProvider Implementierung zu verwenden; Vorteil ist, dass unsere Implementierung zeigt, wie wir uns bei File anmelden würden (ich sehe keinen File Logging-Provider, der mit EF Core ausgeliefert wird ))

So was:

public class Startup

    public void ConfigureServices(IServiceCollection services)
    {
        ...
        var lf = new LoggerFactory();
        lf.AddProvider(new MyLoggerProvider());

        services.AddDbContext<YOUR_DB_CONTEXT>(optionsBuilder => optionsBuilder
                .UseSqlServer(connection_string)
                //Using the LoggerFactory 
                .UseLoggerFactory(lf));
        ...
    }
}

Hier ist die Implementierung eines MyLoggerProvider (und dessen MyLogger der seine Logs an eine Datei MyLogger die Sie konfigurieren können; Ihre EF Core-Abfragen erscheinen in der Datei.)

public class MyLoggerProvider : ILoggerProvider
{
    public ILogger CreateLogger(string categoryName)
    {
        return new MyLogger();
    }

    public void Dispose()
    { }

    private class MyLogger : ILogger
    {
        public bool IsEnabled(LogLevel logLevel)
        {
            return true;
        }

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            File.AppendAllText(@"C:\temp\log.txt", formatter(state, exception));
            Console.WriteLine(formatter(state, exception));
        }

        public IDisposable BeginScope<TState>(TState state)
        {
            return null;
        }
    } 
}

Nun, ich benutze Express Profiler für diesen Zweck im Moment, der Nachteil ist, dass es nur für MS SQL Server funktioniert. Sie finden dieses Tool hier: https://expressprofiler.codeplex.com/


Sie können Folgendes tun:

IQueryable query = from x in appEntities
             where x.id = 32
             select x;

var sql = ((System.Data.Objects.ObjectQuery)query).ToTraceString();

oder in EF6:

var sql = ((System.Data.Entity.Core.Objects.ObjectQuery)query)
            .ToTraceString();

Dadurch erhalten Sie die SQL, die generiert wurde.


Um die Abfrage immer griffbereit zu haben, ohne den Code zu ändern, fügen Sie dies Ihrem DbContext hinzu und überprüfen Sie es im Ausgabefenster von Visual Studio.

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.Log = (query)=> Debug.Write(query);
    }

Ähnlich wie @Matt Nibecker Antwort, aber damit müssen Sie es nicht in Ihrem aktuellen Code hinzufügen, jedes Mal, wenn Sie die Abfrage benötigen.


Wenn Sie Parameterwerte (nicht nur @p_linq_0 sondern auch deren Werte) haben möchten, können Sie IDbCommandInterceptor und der ReaderExecuted Methode eine Protokollierung ReaderExecuted .


IQueryable query = from x in appEntities
                   where x.id = 32
                   select x;
var queryString = query.ToString();

Gibt die SQL-Abfrage zurück. Arbeiten mit Datenkontext von EntityFramework 6







ado.net