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); var sqlBuilder = new StringBuilder(innerSelect.Length * ); 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. EF6.0 下sql语句自动生成的参数类型decimal(18,2)修改

    很多时候我们需要对插入到数据库的数据的精度做一个控制,例如sql server下保留6位小数使用numeric(10,6) .而到c#里对应的数据类型就是decimal ,但是使用EF6.0的crea ...

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

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

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

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

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

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

  9. 在EntityFramework6中执行SQL语句

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

随机推荐

  1. 项目Beta冲刺Day2

    项目进展 李明皇 今天解决的进度 优化了信息详情页的布局:日期显示,添加举报按钮等 优化了程序的数据传递逻辑 明天安排 程序运行逻辑的完善 林翔 今天解决的进度 实现微信端消息发布的插入数据库 明天安 ...

  2. Python之进程

    进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在当代 ...

  3. Python基础-TypeError:takes 2 positional arguments but 3 were given

    Error: 今天写一段简单类定义python代码所遇到报错问题:TypeError: drive() takes 2 positional arguments but 3 were given 代码 ...

  4. WPF优化体验&lt;一&gt;(转)

    最近将一个开发和维护了五年的一个Winform项目进行重构,考虑到最近很流行将用户体验挂在嘴上,于是采用了WPF技术,希望能在外观和体验上有一个全新的效果. 以前使用Winform的时候内存控制得不错 ...

  5. ovs 下流表port 1进入,port 1出去

    问题:ovs流量从in_port=1进入,然后从output:1出去,就是说,流量从哪个端口进来,然后从哪个端口出去 流表: ovs-ofctl add-flow br-int in_port=10, ...

  6. 对某道ctf的一点点记录

    题目:http://ctf5.shiyanbar.com/web/pcat/index.php 是一道注入的题,主要利用了offset 和 group by with rollup的知识 1.offs ...

  7. Flume1.5.0入门:安装、部署、及flume的案例

    转自:http://www.aboutyun.com/thread-8917-1-1.html 问题导读1.什么是flume2.flume的官方网站在哪里?3.flume有哪些术语?4.如何配置flu ...

  8. 51nod 算法马拉松4 B递归(YY)

    递归   基准时间限制:1 秒 空间限制:131072 KB 分值: 80 函数f(n,m) { 若n=1或m=1返回a[n][m]; 返回f(n-1,m)异或f(n,m-1); } 读入2<= ...

  9. c++ 程序设计question 001:我们的开发工具是什么?

    我们使用的开发工具是dev cpp (c plus plus),这是一个集成开发环境,我们称之为IDE(integrated development environment)

  10. PyInstaller 库

    将.py 源代码转换成无需源代码的可执行文件 首先,PyInstaller是第三方库,需要下载额外安装(安装第三方库需要使用pip工具) 步骤: 1.用管理员运行cmd命令行 "pip in ...