821 Stimmen

Wie kann ich das vom Entity Framework generierte SQL anzeigen?

Wie kann ich das vom Entity Framework generierte SQL anzeigen?

(In meinem speziellen Fall verwende ich den mysql-Anbieter - falls das eine Rolle spielt)

14voto

Rosdi Kasim Punkte 22151

Ich tue Integrationstest, und brauchte dies, um die generierte SQL-Anweisung in Entity Framework Core 2.1 zu debuggen, so dass ich verwenden DebugLoggerProvider o ConsoleLoggerProvider etwa so:

[Fact]
public async Task MyAwesomeTest
    {
        //setup log to debug sql queries
        var loggerFactory = new LoggerFactory();
        loggerFactory.AddProvider(new DebugLoggerProvider());
        loggerFactory.AddProvider(new ConsoleLoggerProvider(new ConsoleLoggerSettings()));

        var builder = new DbContextOptionsBuilder<DbContext>();
        builder
            .UseSqlServer("my connection string") //"Server=.;Initial Catalog=TestDb;Integrated Security=True"
            .UseLoggerFactory(loggerFactory);

        var dbContext = new DbContext(builder.Options);

        ........

Hier ist eine Beispielausgabe der Visual Studio-Konsole:

Sample SQL statement output

11voto

andrew pate Punkte 3251

SQL Management Studio => Werkzeuge => SQL Server Profiler

Datei => Neuer Trace...

Verwenden Sie die Vorlage => Blank

Ereignisauswahl => T-SQL

Linksseitige Prüfung auf: SP.StmtComplete

Spaltenfilter können verwendet werden, um einen bestimmten Anwendungsnamen oder Datenbanknamen auszuwählen.

Starten Sie dieses Profil und lösen Sie dann die Abfrage aus.

Klicken Sie hier für Informationen zur Quelle

8voto

Jeremy Morren Punkte 478

Es gibt hier zwar gute Antworten, aber keine hat mein Problem vollständig gelöst (ich wollte die gesamte SQL-Anweisung erhalten), einschließlich Parameter aus dem DbContext von einem beliebigen IQueryable. Der folgende Code tut genau das. Es ist eine Kombination von Codeschnipseln von Google. Ich habe es nur mit EF6+ getestet. .

Nebenbei bemerkt hat mich diese Aufgabe viel länger beschäftigt, als ich dachte. Abstraktion in Entity Framework ist ein bisschen viel, IMHO.

Zuerst die Verwendung. Sie benötigen einen expliziten Verweis auf 'System.Data.Entity.dll'.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Data.Common;
using System.Data.Entity.Core.Objects;
using System.Data.Entity;
using System.Data;
using System.Data.Entity.Infrastructure;
using System.Reflection;

Die folgende Klasse wandelt eine IQueryable in eine DataTable um. Ändern Sie sie je nach Bedarf:

public class EntityFrameworkCommand
{
    DbContext Context;

    string SQL;

    ObjectParameter[] Parameters;

    public EntityFrameworkCommand Initialize<T>(DbContext context, IQueryable<T> query)
    {
        Context = context;
        var dbQuery = query as DbQuery<T>;
        // get the IInternalQuery internal variable from the DbQuery object
        var iqProp = dbQuery.GetType().GetProperty("InternalQuery", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
        var iq = iqProp.GetValue(dbQuery, null);
        // get the ObjectQuery internal variable from the IInternalQuery object
        var oqProp = iq.GetType().GetProperty("ObjectQuery", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
        var objectQuery = oqProp.GetValue(iq, null) as ObjectQuery<T>;
        SQL = objectQuery.ToTraceString();
        Parameters = objectQuery.Parameters.ToArray();
        return this;
    }

    public DataTable GetData()
    {
        DataTable dt = new DataTable();
        var connection = Context.Database.Connection;
        var state = connection.State;
        if (!(state == ConnectionState.Open))
            connection.Open();
        using (var cmd = connection.CreateCommand())
        {
            cmd.CommandText = SQL;
            foreach (var p in Parameters)
            {
                var param = cmd.CreateParameter();
                param.Name = "@" + p.Name;
                param.Value = p.Value;
                cmd.Parameters.Add(param);
            }
            using (var da = DbProviderFactories.GetFactory(connection).CreateDataAdapter())
            {
                da.SelectCommand = cmd;
                da.Fill(dt);
            }
        }
        if (!(state == ConnectionState.Open))
            connection.Close();
        return dt;
    }
}

Rufen Sie sie einfach wie folgt auf:

var context = new MyContext();
var data = ....//Query, return type can be anonymous
    .AsQueryable();
var dt = new EntityFrameworkCommand()
    .Initialize(context, data)
    .GetData();

7voto

Christian Findlay Punkte 5653

Protokollierung mit Entity Framework Core 3.x verwenden

Entity Framework Core gibt SQL über das Logging-System aus. Es gibt nur ein paar kleine Tricks. Sie müssen eine ILoggerFactory und Sie müssen einen Filter angeben. Hier ist ein Beispiel aus dieser Artikel

Erstellen Sie die Fabrik:

var loggerFactory = LoggerFactory.Create(builder =>
{
    builder
    .AddConsole((options) => { })
    .AddFilter((category, level) =>
        category == DbLoggerCategory.Database.Command.Name
        && level == LogLevel.Information);
});

Sag dem DbContext um die Fabrik in der OnConfiguring Methode:

optionsBuilder.UseLoggerFactory(_loggerFactory);

Von hier aus können Sie die Log-Methode nutzen, um Details über das ausgeführte SQL zu extrahieren. In diesem Artikel finden Sie eine ausführliche Diskussion.

public class EntityFrameworkSqlLogger : ILogger
{
    #region Fields
    Action<EntityFrameworkSqlLogMessage> _logMessage;
    #endregion
    #region Constructor
    public EntityFrameworkSqlLogger(Action<EntityFrameworkSqlLogMessage> logMessage)
    {
        _logMessage = logMessage;
    }
    #endregion
    #region Implementation
    public IDisposable BeginScope<TState>(TState state)
    {
        return default;
    }
    public bool IsEnabled(LogLevel logLevel)
    {
        return true;
    }
    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        if (eventId.Id != 20101)
        {
            //Filter messages that aren't relevant.
            //There may be other types of messages that are relevant for other database platforms...
            return;
        }
        if (state is IReadOnlyList<KeyValuePair<string, object>> keyValuePairList)
        {
            var entityFrameworkSqlLogMessage = new EntityFrameworkSqlLogMessage
            (
                eventId,
                (string)keyValuePairList.FirstOrDefault(k => k.Key == "commandText").Value,
                (string)keyValuePairList.FirstOrDefault(k => k.Key == "parameters").Value,
                (CommandType)keyValuePairList.FirstOrDefault(k => k.Key == "commandType").Value,
                (int)keyValuePairList.FirstOrDefault(k => k.Key == "commandTimeout").Value,
                (string)keyValuePairList.FirstOrDefault(k => k.Key == "elapsed").Value
            );
            _logMessage(entityFrameworkSqlLogMessage);
        }
    }
    #endregion
}

6voto

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

Gibt die Sql-Abfrage zurück. Arbeiten mit datacontext von EntityFramework 6

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X