sqlquery query non mvc framework example consulta sql logging entity-framework-4 entity-framework-4.1 tracing

sql - non - execute query entity



En EF 4.1 DbContext, cómo rastrear SQL generado (8)

Ejecute su código y luego ejecute esta consulta para ver el último SQL ejecutado.

SELECT deqs.last_execution_time AS [Time], dest.TEXT AS [Query] FROM sys.dm_exec_query_stats AS deqs CROSS APPLY sys.dm_exec_sql_text(deqs.sql_handle) AS dest ORDER BY deqs.last_execution_time DESC

Me pregunto cómo rastrear SQL generado como DataContext en LinqToSql.

También leo artículos sobre la solución de EFProviderWrapper en el blog de Jaroslaw Kowalski, pero está basado en ObjectContext, no funciona para DbContext.

¿Alguien sabe cómo hacer esto en DbContext?

Gracias.



Encontré esta extensión EFTracingProvider para ObjectContext aquí:

http://efwrappers.codeplex.com/

Pero el ejemplo es para ObjectContext no DbContext, para que funcione con DbContext haga lo siguiente en el constructor:

Public Sub New() MyBase.New(EFTracingProviderUtils.CreateTracedEntityConnection("MyDbConnection"), True) Dim context As ObjectContext = CType(Me, IObjectContextAdapter).ObjectContext context.EnableTracing() End Sub

Ah, y recuerda establecer la configuración:

<?xml version="1.0" encoding="utf-8"?> <configuration> <system.diagnostics> <sources> <source name="EntityFramework.MyDbConnection" switchValue="All" /> </sources> </system.diagnostics>

Que luego rastrea todo el SQL a la ventana inmediata.


Esta es una ligera mejora con respecto a la solución (por @kmk) que reemplaza los parámetros con valores. Esta solución declara y asigna los parámetros en su lugar:

public static string ToSqlString<TEntity>(this IQueryable<TEntity> queryable) where TEntity : class { StringBuilder parametersBuilder = new StringBuilder(); try { var dbQuery = queryable as DbQuery<TEntity>; // 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 oq = oqProp.GetValue(iq, null); var objectQuery = oq as ObjectQuery<TEntity>; var sqlString = objectQuery.ToTraceString(); foreach (var objectParam in objectQuery.Parameters) { SqlMetaData metadata = SqlMetaData.InferFromValue(objectParam.Value, objectParam.Name); string sqlType = metadata.TypeName + (metadata.SqlDbType == SqlDbType.NVarChar ? "(" + metadata.MaxLength + ")" : String.Empty); parametersBuilder.AppendFormat("declare @{0} {1} = ''{2}''", objectParam.Name, sqlType, objectParam.Value); parametersBuilder.AppendLine(); } parametersBuilder.AppendLine(); return parametersBuilder.ToString() + sqlString; } catch (Exception) { //squash it and just return ToString return queryable.ToString(); } }


Para cualquier persona que no desee obtener en una biblioteca de terceros, y simplemente está buscando el SQL que contiene los parámetros (y no está molesto por todo el reflejo), este método de extensión toma el objeto InternalQuery y el objeto ObjectQuery del DbQuery y regresa ToTraceString luego de realizar nuevamente los Parámetros en la cadena. Si falla, devuelve ToString sin parámetros de IQueryable:

public static string ToSqlString<TEntity>(this IQueryable<TEntity> queryable) where TEntity : class { try { var dbQuery = queryable as DbQuery<TEntity>; // 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); // get the ObjectQuery internal variable from the IInternalQuery object var oqProp = iq.GetType().GetProperty("ObjectQuery", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); var oq = oqProp.GetValue(iq); var objectQuery = oq as ObjectQuery<TEntity>; var sqlString = objectQuery.ToTraceString(); foreach (var objectParam in objectQuery.Parameters) { if (objectParam.ParameterType == typeof(string) || objectParam.ParameterType == typeof(DateTime) || objectParam.ParameterType == typeof(DateTime?)) { sqlString = sqlString.Replace(string.Format("@{0}", objectParam.Name), string.Format("''{0}''", objectParam.Value.ToString())); } else if (objectParam.ParameterType == typeof(bool) || objectParam.ParameterType == typeof(bool?)) { bool val; if (Boolean.TryParse(objectParam.Value.ToString(), out val)) { sqlString = sqlString.Replace(string.Format("@{0}", objectParam.Name), string.Format("{0}", val ? 1 : 0)); } } else { sqlString = sqlString.Replace(string.Format("@{0}", objectParam.Name), string.Format("{0}", objectParam.Value.ToString())); } } return sqlString; } catch (Exception) { //squash it and just return ToString return queryable.ToString(); } }


Puede usar el método ObjectQuery.ToTraceString para ver los comandos de la tienda (por ejemplo, sentencias de SQL). El Cómo en MSDN le mostrará cómo se puede usar.

Tenga en cuenta que, en muchos casos, podrá convertir un IQueryable (el tipo de devolución de los métodos de extensión de Linq como IQueryable.Where ) en un ObjectQuery para que tenga acceso al método ToTraceString.


Utilizo la herramienta de perfil SQL Server para ver exactamente qué SQL se ha creado. También hay http://efprof.com/ pero tiene un precio bastante alto.


La forma más fácil con DbContext y DbSet<T> es utilizar ToString() en IQueryable que ha creado. Por ejemplo:

var query = context.Blogs.Include(b => b.Posts) .Where(b => b.Title == "AnyTitle"); string sql = query.ToString();

sql contiene el comando SQL que se emitirá al DB cuando se ejecuta la consulta.