我想知道如何在LinqToSql中跟踪生成的SQL,如DataContext。
我还在Jaroslaw Kowalski的博客上阅读了有关EFProviderWrapper解决方案的文章,但它基于ObjectContext,不适用于DbContext。
任何人都知道如何在DbContext中执行此操作?
谢谢。
答案 0 :(得分:16)
使用DbContext
和DbSet<T>
的最简单方法就是在您构建的ToString()
上使用IQueryable
。例如:
var query = context.Blogs.Include(b => b.Posts)
.Where(b => b.Title == "AnyTitle");
string sql = query.ToString();
sql
包含SQL命令,该命令将在执行查询时发布给数据库。
答案 1 :(得分:1)
MVC-Mini-Profiler是一个功能强大的工具,不仅可以跟踪生成的sql,还可以分析工具。
Using mvc-mini-profiler database profiling with Entity Framework Code First
答案 2 :(得分:0)
我使用SQL Server探查器工具来确切地查看已创建的SQL。还有http://efprof.com/,但价格相当高。
答案 3 :(得分:0)
您可以使用ObjectQuery.ToTraceString方法查看存储命令(例如SQL语句)。 MSDN上的How To将向您展示如何使用它。
请注意,在许多情况下,您可以将IQueryable(Linq扩展方法的返回类型,例如IQueryable.Where)转换为ObjectQuery,以便您可以访问ToTraceString方法。
答案 4 :(得分:0)
我在这里找到了ObjectContext的EFTracingProvider扩展:
http://efwrappers.codeplex.com/
但是示例是针对ObjectContext而不是DbContext,以使其与DbContext一起使用 在构造函数中执行以下操作:
Public Sub New()
MyBase.New(EFTracingProviderUtils.CreateTracedEntityConnection("MyDbConnection"), True)
Dim context As ObjectContext = CType(Me, IObjectContextAdapter).ObjectContext
context.EnableTracing()
End Sub
哦,记得设置配置:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.diagnostics>
<sources>
<source name="EntityFramework.MyDbConnection" switchValue="All" />
</sources>
</system.diagnostics>
然后将所有SQL跟踪到即时窗口。
答案 5 :(得分:0)
对于任何不想引入第三方库的人,只是在寻找包含参数的SQL(并且不会被所有反射所扰乱),这个扩展方法从中获取InternalQuery对象和ObjectQuery对象。 DbQuery并在将Parameters返回到字符串后返回ToTraceString。如果失败,则从IQueryable返回无参数ToString:
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();
}
}
答案 6 :(得分:0)
执行代码,然后运行此查询以查看最后执行的SQL。
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
答案 7 :(得分:0)
这比使用值替换参数的解决方案(通过@kmk)略有改进。此解决方案声明并分配参数:
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();
}
}