2011-04-09 53 views
31

我想知道如何在LinqToSql中跟蹤生成的SQL,如DataContext。在EF 4.1 DbContext中如何跟蹤生成的SQL

我還在Jaroslaw Kowalski的博客上閱讀了有關EFProviderWrapper解決方案的文章,但它基於ObjectContext,不適用於DbContext。

任何人都知道如何在DbContext中做到這一點?

謝謝。

+2

這實際上是非常好的問題。 – 2011-04-09 17:39:26

+0

這是微軟希望你花費更多錢(Visual Studio Ultimate)的那些[功能](http://msdn.microsoft.com/en-us/magazine/ee336126.aspx)之一。有一些第三方庫可以讓它更容易。 – 2013-12-09 21:16:59

回答

0

我使用SQL Server分析器工具來確切地查看已創建的SQL。也有http://efprof.com/但它有相當高的價格。

+1

謝謝,我知道那個工具。我正在尋找一種DIY解決方案。 – Chance 2011-04-09 06:16:55

0

可以使用ObjectQuery.ToTraceString方法,以查看存儲命令(例如SQL語句)。 MSDN上的How To將向您展示如何使用它。

注意,在很多情況下,你就可以讓你有機會獲得ToTraceString方法施放一個IQueryable(從LINQ的擴展方法如IQueryable.Where返回類型)到的ObjectQuery。

+0

這不太方便。我推薦這個:http://stackoverflow.com/questions/6550046/using-mvc-mini-profiler-database-profiling-with-entity-framework-code-first/6743941#6743941 – Chance 2011-07-20 04:43:13

15

最簡單的方法與DbContextDbSet<T>只是使用ToString()IQueryable你已經建成。例如:

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

string sql = query.ToString(); 

sql包含當查詢被執行將被髮布到DB SQL命令。

+1

這隻有在你做了搜索(返回一個IQueryable)。如果您要添加,修改和刪除實體,您如何查看該SQL? – codemonkey 2011-08-12 19:08:30

+0

@codemonkey:True,僅適用於查詢。我不認爲有任何內置的方式來跟蹤DbContext的所有SQL語句。 – Slauma 2011-08-12 21:02:29

+0

我來這裏問@codemonkey的問題。我發現的一切都表明前者,後者還沒有運氣。 – Funka 2013-01-26 01:34:16

0

我發現這裏的ObjectContext此EFTracingProvider擴展:

http://efwrappers.codeplex.com/

但這個例子是ObjectContext中沒有的DbContext,讓它用的DbContext 工作做在構造函數如下:

​​3210

哦,並記住設置配置:

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

然後將所有SQL追蹤到即時窗口。

0

對於任何不想拉入第三方庫的人來說,只需查找包含參數的SQL(並且不會被所有反射所困擾),該擴展方法將從內部查詢對象和ObjectQuery對象DbQuery並在將參數實現回字符串後返回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(); 
     } 
    } 
+0

當有超過10個參數時,此解決方案存在問題。假設一個參數被稱爲p10。當您用它的值替換p1時,最終會導致無效的SQL。 – 2014-06-16 21:46:03

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 
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(); 
     } 
    } 
相關問題