1、关于EF6的记录Sql语句,一个老生长谈的问题。 他生成的sql语句实在是烂,大家都这样说

2、EF6 更新删除不方便,没有批量操作。所以,有人出了EF6.Extend  大家用起来也很爽

基于以上两点,我也尝试着使用 EF6.Extend 。本以为可以很好的,很美好。没有想到我遇到了一个大问题。

我需要 通过程序记录 EF执行的Sql语句,当然也包括 EF6.Extend 执行的Sql语句。(不是通过SqlProfiler)

在网上查找,发现 了一篇文章,我就这样抄下来了。(太匆忙解决问题,忘记了哪一篇)

继承了 System.Data.Entity.Infrastructure.Interception.DbCommandInterceptor  ,实现相关方法。  然后在Main方法(程序入口)进行添加  DbInterception.Add(new EFIntercepterLogging());

 using System;
 using System.Collections.Generic;
 using System.Data.Entity.Infrastructure.Interception;
 using System.Diagnostics;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;

 namespace EF_Sqlite
 {
     class EFIntercepterLogging : DbCommandInterceptor
     {
         private readonly Stopwatch _stopwatch = new Stopwatch();
         public override void ScalarExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
         {
             base.ScalarExecuting(command, interceptionContext);
             _stopwatch.Restart();
         }
         public override void ScalarExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
         {
             _stopwatch.Stop();
             if (interceptionContext.Exception != null)
             {
                 Trace.TraceError("Exception:{1} \r\n --> Error executing command: {0}", command.CommandText, interceptionContext.Exception.ToString());
             }
             else
             {
                 string txt=string.Format("\r\n执行时间:{0} 毫秒\r\n-->ScalarExecuted.Command:{1}\r\n", _stopwatch.ElapsedMilliseconds, command.CommandText);
                 Console.WriteLine(txt);
                 Trace.TraceInformation(txt);
             }
             base.ScalarExecuted(command, interceptionContext);
         }
         public override void NonQueryExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
         {
             base.NonQueryExecuting(command, interceptionContext);
             _stopwatch.Restart();
         }
         public override void NonQueryExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
         {

             _stopwatch.Stop();
             if (interceptionContext.Exception != null)
             {
                 Trace.TraceError("Exception:{1} \r\n --> Error executing command:\r\n {0}", command.CommandText, interceptionContext.Exception.ToString());
             }
             else
             {   

                 string txt = string.Format("\r\n执行时间:{0} 毫秒\r\n-->ScalarExecuted.Command:{1}\r\n", _stopwatch.ElapsedMilliseconds, command.CommandText);
                 Console.WriteLine(txt);
                 Trace.TraceInformation(txt);
             }
             base.NonQueryExecuted(command, interceptionContext);
         }
         public override void ReaderExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
         {
             base.ReaderExecuting(command, interceptionContext);
             _stopwatch.Restart();
         }
         public override void ReaderExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
         {
             _stopwatch.Stop();
             if (interceptionContext.Exception != null)
             {
                 Trace.TraceError("Exception:{1} \r\n --> Error executing command:\r\n {0}", command.CommandText, interceptionContext.Exception.ToString());
             }
             else
             {
                 string txt = string.Format("\r\n执行时间:{0} 毫秒\r\n-->ScalarExecuted.Command:{1}\r\n", _stopwatch.ElapsedMilliseconds, command.CommandText);
                 Console.WriteLine(txt);
                 Trace.TraceInformation(txt);
             }
             base.ReaderExecuted(command, interceptionContext);
         }

     }
 }

日志记录类完整代码

通过EF正常的操作是可以记录到SQL语句的,而通过EF.Extend执行的删除操作是无法获取sql的。我想,是不是我写错了,可网上根本没有关于EF.Extend 记录生成SQL的只言片语,可能大家都没有遇到这样的问题。

只能硬着头皮,翻源码。

经过翻看EF.Extend的源码,发现他是直接用Command执行的sql,再翻 EF的源码发现,EF是绕了很大一圈来执行的SQL

找到EF的这里,我明白了

 public virtual int NonQuery(DbCommand command, DbCommandInterceptionContext interceptionContext)
 {
 Check.NotNull(command, "command");
 Check.NotNull(interceptionContext, "interceptionContext");

 return _internalDispatcher.Dispatch(
 command,
 (t, c) => t.ExecuteNonQuery(),
 new DbCommandInterceptionContext<int>(interceptionContext),
 (i, t, c) => i.NonQueryExecuting(t, c),
 (i, t, c) => i.NonQueryExecuted(t, c));
 }

EF的执行代码

而,EF.Extend的代码是这样写的

 private int InternalDelete<TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery<TEntity> query)
             where TEntity : class
 #endif
         {
             DbConnection deleteConnection = null;
             DbTransaction deleteTransaction = null;
             DbCommand deleteCommand = null;
             bool ownConnection = false;
             bool ownTransaction = false;

             try
             {
                 // get store connection and transaction
                 var store = GetStore(objectContext);
                 deleteConnection = store.Item1;
                 deleteTransaction = store.Item2;

                 if (deleteConnection.State != ConnectionState.Open)
                 {
                     deleteConnection.Open();
                     ownConnection = true;
                 }

                 if (deleteTransaction == null)
                 {
                     deleteTransaction = deleteConnection.BeginTransaction();
                     ownTransaction = true;
                 }

                 deleteCommand = deleteConnection.CreateCommand();
                 deleteCommand.Transaction = deleteTransaction;
                 if (objectContext.CommandTimeout.HasValue)
                     deleteCommand.CommandTimeout = objectContext.CommandTimeout.Value;

                 var innerSelect = GetSelectSql(query, entityMap, deleteCommand);

                 );

                 sqlBuilder.Append("DELETE ");
                 sqlBuilder.Append(entityMap.TableName);
                 sqlBuilder.AppendLine();

                 sqlBuilder.AppendFormat("FROM {0} AS j0 INNER JOIN (", entityMap.TableName);
                 sqlBuilder.AppendLine();
                 sqlBuilder.AppendLine(innerSelect);
                 sqlBuilder.Append(") AS j1 ON (");

                 bool wroteKey = false;
                 foreach (var keyMap in entityMap.KeyMaps)
                 {
                     if (wroteKey)
                         sqlBuilder.Append(" AND ");

                     sqlBuilder.AppendFormat("j0.[{0}] = j1.[{0}]", keyMap.ColumnName);
                     wroteKey = true;
                 }
                 sqlBuilder.Append(")");

                 deleteCommand.CommandText = sqlBuilder.ToString();

 #if NET45
                 int result = async
                     ? await deleteCommand.ExecuteNonQueryAsync().ConfigureAwait(false)
                     : deleteCommand.ExecuteNonQuery();
 #else
                 int result = deleteCommand.ExecuteNonQuery();
 #endif
                 // only commit if created transaction
                 if (ownTransaction)
                     deleteTransaction.Commit();

                 return result;
             }
             finally
             {
                 if (deleteCommand != null)
                     deleteCommand.Dispose();

                 if (deleteTransaction != null && ownTransaction)
                     deleteTransaction.Dispose();

                 if (deleteConnection != null && ownConnection)
                     deleteConnection.Close();
             }
         }

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文件

关于EF6的记录Sql语句 与 EntityFramework.Extend 的诟病的更多相关文章

  1. ORACLE百万记录SQL语句优化技巧

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  2. MySQL 5.6 记录 SQL 语句与慢查询

    环境: MySQL 如果需要记录 MySQL 的查询语句,需要在配置文件(Linux 下为 my.cnf,Windows 下为 my.ini)中添加配置: general_log = ON gener ...

  3. Ora中select某时间段记录sql语句

    要查找某时间段的记录,例如查找2013-11-1到2013-11-30的记录. ' group by user_name, user_id 注意:SQL语句中含有sum累加函数,末尾要加group b ...

  4. EF6中执行Sql语句

    EF中提供了两个方法,一个是执行查询的Sql语句SqlQuery,另外一个是执行非查询的语句ExecuteSqlCommand.SqlQuery有两种形式的,一种是泛型的,一种是非泛型的.比如我们要在 ...

  5. 用mybatis时log4j总是不记录sql语句

    log4j:WARN No appenders could be found for logger (org.apache.ibatis.logging.LogFactory).log4j:WARN ...

  6. 记录sql语句的执行记录,用于分析

    SET STATISTICS PROFILE ONSET STATISTICS IO ONSET STATISTICS TIME ONGO --这之间是要执行的脚本select * from [Use ...

  7. [转]在EntityFramework6中执行SQL语句

    本文转自:http://www.cnblogs.com/wujingtao/p/5412329.html 在上一节中我介绍了如何使用EF6对数据库实现CRDU以及事务,我们没有写一句SQL就完成了所有 ...

  8. 在EntityFramework6中执行SQL语句

    在EntityFramework6中执行SQL语句 在上一节中我介绍了如何使用EF6对数据库实现CRDU以及事务,我们没有写一句SQL就完成了所有操作.这一节我来介绍一下如何使用在EF6中执行SQL语 ...

  9. 在EntityFramework6中执行SQL语句【转】

    在上一节中我介绍了如何使用EF6对数据库实现CRDU以及事务,我们没有写一句SQL就完成了所有操作.这一节我来介绍一下如何使用在EF6中执行SQL语句. 你可能要问,我用EF不就为了避免写SQL吗?如 ...

随机推荐

  1. AngularJS快速入门指南16:Bootstrap

    thead>tr>th, table.reference>tbody>tr>th, table.reference>tfoot>tr>th, table ...

  2. DB2LOOK命令提取数据库对象信息

    提取复制数据库的DDL语句:db2look -d BCDLJS -e -o db2look.sql -a -a:导出所有用户的DDL-o: 定向结果到文件-d: 数据库名-e: 抽取复制数据库所需的 ...

  3. python继承

    Python继承 继承实例: 父类和子类的关系: 继承树: 没有父类就继承object类,不要忘记调用super().__init__来初始化父类 代码: class Person(object): ...

  4. 消息队列与RabbitMQ

    1 什么是消息队列 消息指进程或应用间通信的数据:队列是保存数据的结构:消息队列是指进程或应用间通信时,保存消息的容器.消息队列独特的机制和结构保证了消息发送者和接收者之间良好的异步通信. 2 为什么 ...

  5. win10 64位安装mysql

    原文地址:http://blog.csdn.net/kingyumao/article/details/51925795

  6. setInterval和setTimeout的使用区别

    setTimeout和setInterval的使用 这两个方法都可以用来实现在一个固定时间段之后去执行JavaScript.不过两者各有各的应用场景. 方 法 实际上,setTimeout和setIn ...

  7. 基于visual Studio2013解决C语言竞赛题之0405阶乘求和

      题目 解决代码及点评 这道题和上一道题类似,第n个累加项 = n-1累加项的n倍 由于有这个规律,我们可以用一个for循环实现 但是例子代码并没有这么做,大家可以回去修改下代码,使得代码更 ...

  8. webservice的调用方法

    一.WebService在cs后台程序中的调用 A.通过命名空间和类名直接调用 示例: WebService ws = new WebService(); string s = ws.HelloWor ...

  9. Swift语言中与C/C++和Java不同的语法(五)

    这一节将会提到Swift中其他的关于函数的应用,这些内容包括有: 默认参数值和可变参数值.常量参数.返回函数类型和函数嵌套: 一.默认参数值和可变参数值 对默认参数值是指在函数的声明中就已经定义了参数 ...

  10. Android动态换肤(二、apk免安装插件方式)

    在上一篇文章Android动态换肤(一.应用内置多套皮肤)中,我们了解到,动态换肤无非就是调用view的setBackgroundResource(R.drawable.id)等方法设置控件的背景或者 ...