關於EF6的記錄Sql語句 與 EntityFramework.Extend 的詬病

一、關於EF6的記錄Sql語句,一個老生長談的問題。 他生成的sql語句實在是爛,你們都這樣說sql

二、EF6 更新刪除不方便,沒有批量操做。因此,有人出了EF6.Extend  你們用起來也很爽緩存

 

基於以上兩點,我也嘗試着使用 EF6.Extend 。本覺得能夠很好的,很美好。沒有想到我遇到了一個大問題。async

我須要 經過程序記錄 EF執行的Sql語句,固然也包括 EF6.Extend 執行的Sql語句。(不是經過SqlProfiler)ide

在網上查找,發現 了一篇文章,我就這樣抄下來了。(太匆忙解決問題,忘記了哪一篇)ui

繼承了 System.Data.Entity.Infrastructure.Interception.DbCommandInterceptor  ,實現相關方法。  而後在Main方法(程序入口)進行添加  DbInterception.Add(new EFIntercepterLogging());   spa

 

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Data.Entity.Infrastructure.Interception;
 4 using System.Diagnostics;
 5 using System.Linq;
 6 using System.Text;
 7 using System.Threading.Tasks;
 8 
 9 namespace EF_Sqlite
10 {
11     class EFIntercepterLogging : DbCommandInterceptor
12     {
13         private readonly Stopwatch _stopwatch = new Stopwatch();
14         public override void ScalarExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
15         {
16             base.ScalarExecuting(command, interceptionContext);
17             _stopwatch.Restart();
18         }
19         public override void ScalarExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
20         {
21             _stopwatch.Stop();
22             if (interceptionContext.Exception != null)
23             {
24                 Trace.TraceError("Exception:{1} \r\n --> Error executing command: {0}", command.CommandText, interceptionContext.Exception.ToString());
25             }
26             else
27             {
28                 string txt=string.Format("\r\n執行時間:{0} 毫秒\r\n-->ScalarExecuted.Command:{1}\r\n", _stopwatch.ElapsedMilliseconds, command.CommandText);
29                 Console.WriteLine(txt);
30                 Trace.TraceInformation(txt);
31             }
32             base.ScalarExecuted(command, interceptionContext);
33         }
34         public override void NonQueryExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
35         {
36             base.NonQueryExecuting(command, interceptionContext);
37             _stopwatch.Restart();
38         }
39         public override void NonQueryExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
40         {
41             
42             _stopwatch.Stop();
43             if (interceptionContext.Exception != null)
44             {
45                 Trace.TraceError("Exception:{1} \r\n --> Error executing command:\r\n {0}", command.CommandText, interceptionContext.Exception.ToString());
46             }
47             else
48             {   
49                 
50                 string txt = string.Format("\r\n執行時間:{0} 毫秒\r\n-->ScalarExecuted.Command:{1}\r\n", _stopwatch.ElapsedMilliseconds, command.CommandText);
51                 Console.WriteLine(txt);
52                 Trace.TraceInformation(txt);
53             }
54             base.NonQueryExecuted(command, interceptionContext);
55         }
56         public override void ReaderExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
57         {
58             base.ReaderExecuting(command, interceptionContext);
59             _stopwatch.Restart();
60         }
61         public override void ReaderExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
62         {
63             _stopwatch.Stop();
64             if (interceptionContext.Exception != null)
65             {
66                 Trace.TraceError("Exception:{1} \r\n --> Error executing command:\r\n {0}", command.CommandText, interceptionContext.Exception.ToString());
67             }
68             else
69             {
70                 string txt = string.Format("\r\n執行時間:{0} 毫秒\r\n-->ScalarExecuted.Command:{1}\r\n", _stopwatch.ElapsedMilliseconds, command.CommandText);
71                 Console.WriteLine(txt);
72                 Trace.TraceInformation(txt);
73             }
74             base.ReaderExecuted(command, interceptionContext);
75         }
76 
77         
78     }
79 }
日誌記錄類完整代碼

 

經過EF正常的操做是能夠記錄到SQL語句的,而經過EF.Extend執行的刪除操做是沒法獲取sql的。我想,是否是我寫錯了,可網上根本沒有關於EF.Extend 記錄生成SQL的隻言片語,可能你們都沒有遇到這樣的問題。  pwa

只能硬着頭皮,翻源碼。日誌

通過翻看EF.Extend的源碼,發現他是直接用Command執行的sql,再翻 EF的源碼發現,EF是繞了很大一圈來執行的SQL code

 找到EF的這裏,我明白了orm

 1 public virtual int NonQuery(DbCommand command, DbCommandInterceptionContext interceptionContext)
 2 {
 3 Check.NotNull(command, "command");
 4 Check.NotNull(interceptionContext, "interceptionContext");
 5 
 6 return _internalDispatcher.Dispatch(
 7 command,
 8 (t, c) => t.ExecuteNonQuery(),
 9 new DbCommandInterceptionContext<int>(interceptionContext),
10 (i, t, c) => i.NonQueryExecuting(t, c),
11 (i, t, c) => i.NonQueryExecuted(t, c));
12 }
EF的執行代碼

 

 而,EF.Extend的代碼是這樣寫的

 1 private int InternalDelete<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query)
 2             where TEntity : class
 3 #endif
 4         {
 5             DbConnection deleteConnection = null;
 6             DbTransaction deleteTransaction = null;
 7             DbCommand deleteCommand = null;
 8             bool ownConnection = false;
 9             bool ownTransaction = false;
10 
11             try
12             {
13                 // get store connection and transaction
14                 var store = GetStore(objectContext);
15                 deleteConnection = store.Item1;
16                 deleteTransaction = store.Item2;
17 
18                 if (deleteConnection.State != ConnectionState.Open)
19                 {
20                     deleteConnection.Open();
21                     ownConnection = true;
22                 }
23 
24                 if (deleteTransaction == null)
25                 {
26                     deleteTransaction = deleteConnection.BeginTransaction();
27                     ownTransaction = true;
28                 }
29 
30 
31                 deleteCommand = deleteConnection.CreateCommand();
32                 deleteCommand.Transaction = deleteTransaction;
33                 if (objectContext.CommandTimeout.HasValue)
34                     deleteCommand.CommandTimeout = objectContext.CommandTimeout.Value;
35 
36                 var innerSelect = GetSelectSql(query, entityMap, deleteCommand);
37 
38                 var sqlBuilder = new StringBuilder(innerSelect.Length * 2);
39 
40                 sqlBuilder.Append("DELETE ");
41                 sqlBuilder.Append(entityMap.TableName);
42                 sqlBuilder.AppendLine();
43 
44                 sqlBuilder.AppendFormat("FROM {0} AS j0 INNER JOIN (", entityMap.TableName);
45                 sqlBuilder.AppendLine();
46                 sqlBuilder.AppendLine(innerSelect);
47                 sqlBuilder.Append(") AS j1 ON (");
48 
49                 bool wroteKey = false;
50                 foreach (var keyMap in entityMap.KeyMaps)
51                 {
52                     if (wroteKey)
53                         sqlBuilder.Append(" AND ");
54 
55                     sqlBuilder.AppendFormat("j0.[{0}] = j1.[{0}]", keyMap.ColumnName);
56                     wroteKey = true;
57                 }
58                 sqlBuilder.Append(")");
59 
60                 deleteCommand.CommandText = sqlBuilder.ToString();
61 
62 #if NET45
63                 int result = async
64                     ? await deleteCommand.ExecuteNonQueryAsync().ConfigureAwait(false)
65                     : deleteCommand.ExecuteNonQuery();
66 #else
67                 int result = deleteCommand.ExecuteNonQuery();
68 #endif
69                 // only commit if created transaction
70                 if (ownTransaction)
71                     deleteTransaction.Commit();
72 
73                 return result;
74             }
75             finally
76             {
77                 if (deleteCommand != null)
78                     deleteCommand.Dispose();
79 
80                 if (deleteTransaction != null && ownTransaction)
81                     deleteTransaction.Dispose();
82 
83                 if (deleteConnection != null && ownConnection)
84                     deleteConnection.Close();
85             }
86         }
EF.Extend的執行代碼

 

 通過分析,是這個道理,按照這個邏輯,EF.Extend沒有按照EF的邏輯寫,因此,他不能經過這種方式記錄Sql。

恍然大悟後,我這樣執行的Sql

System.Data.Common.DbConnection con = t.Database.Connection;
System.Data.Common.DbCommand command = con.CreateCommand();
con.Open();
command.CommandText = "delete from area where 1=2 and 4=9";
DbInterception.Dispatch.Command.NonQuery(command, new DbCommandInterceptionContext());
EF 自定義的SQL執行

 就這樣,我 經過統一的方式,獲取到了我本身執行的Sql語句,和EF執行的Sql語句

 

原本是打算用EF.Extend的,看到這裏,我決定不用了,有點殺雞用牛刀。(其實,EF.Extend 不只擴展了修改和刪除的方法,還擴展了 EF沒有的二級緩存,等等。若是隻是用到修改刪除的擴展方法,那能夠放棄Extend了。)

 

 

 

修改後的DLL文件

相關文章
相關標籤/搜索