Entity Framework 6.X实现记录执行的SQL功能

Entity Framework在使用时,很多时间操纵的是Model,并没有写sql语句,有时候为了调试或优化等,又需要追踪Entity framework自动生成的sql(最好还能记录起来,方便出错时排查)

方式一:

通过System.Data.Entity.DataBase.Log属性指定一个无返回值的委托,来实现记录日志的功能

public partial class EFContext<T> : DbContext where T : class
    {
        public EFContext(): base("name=MyConnectionString")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            Database.SetInitializer<EFContext<T>> (null);

            Database.Log = log => File.AppendAllText("ef.log",string.Format("{0}{1}{2}", DateTime.Now, Environment.NewLine, log));

            modelBuilder.Configurations.Add(new MemberMap());
            modelBuilder.Configurations.Add(new RoleMap());
            base.OnModelCreating(modelBuilder);
        }

        public DbSet<T> Table { get; set; }

        public IQueryable<T> GetList(Expression<Func<T,bool>> where)
        {
            return this.Table.Where(where);
        }
    }

其中:Database.Log = log => File.AppendAllText("ef.log",string.Format("{0}{1}{2}", DateTime.Now, Environment.NewLine, log));  设置写入日志

控制台代码:

EFContext<Member> efMemberContext = new EFContext<Member>();
var memberSet = efMemberContext.Set<Member>().Include("Role");

var memberList = memberSet.OrderBy(m => new { m.RoleId, m.Name });
foreach (Member item in memberList)
{
    Console.WriteLine("{0},Role:{1}",item.Name,item.Role.Name);
}

运行程序后,打开ef.log文件,发现记录了日志

方式二:自定义一个类,继承于DbCommandInterceptor,重写下面几个方法

public class EFDbCommandInterceptor : DbCommandInterceptor
    {
        /// <summary>
        /// 计时器
        /// </summary>
        public volatile Stopwatch watch = new Stopwatch();

        public override void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
        {
            base.NonQueryExecuting(command, interceptionContext);
            watch.Restart();
        }

        public override void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
        {
            watch.Stop();
            if (interceptionContext.Exception != null)
            {
                WriteLog(string.Format("Exception:{1} \r\n --> Error executing command: {0}", command.CommandText, interceptionContext.Exception.ToString()));
            }
            else
            {
                WriteLog(string.Format("\r\n执行时间:{0} 毫秒\r\n-->ScalarExecuted.Command:{1}\r\n", watch.ElapsedMilliseconds, command.CommandText));
            }
            base.NonQueryExecuted(command, interceptionContext);
        }

        public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
        {
            base.ScalarExecuting(command, interceptionContext);
            watch.Restart();
        }

        public override void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
        {
            watch.Stop();
            if (interceptionContext.Exception != null)
            {
                WriteLog(string.Format("Exception:{1} \r\n --> Error executing command: {0}", command.CommandText, interceptionContext.Exception.ToString()));
            }
            else
            {
                WriteLog(string.Format("\r\n执行时间:{0} 毫秒\r\n-->ScalarExecuted.Command:{1}\r\n", watch.ElapsedMilliseconds, command.CommandText));
            }
            base.ScalarExecuted(command, interceptionContext);
        }

        public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
        {
            base.ReaderExecuting(command, interceptionContext);
            watch.Restart();
        }

        public override void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
        {
            watch.Stop();
            if (interceptionContext.Exception != null)
            {
                WriteLog(string.Format("Exception:{1} \r\n --> Error executing command: {0}", command.CommandText, interceptionContext.Exception.ToString()));
            }
            else
            {
                WriteLog(string.Format("\r\n执行时间:{0} 毫秒\r\n-->ScalarExecuted.Command:{1}\r\n", watch.ElapsedMilliseconds, command.CommandText));
            }
            base.ReaderExecuted(command, interceptionContext);
        }
        /// <summary>
        /// 记录日志
        /// </summary>
        /// <param name="msg">消息</param>
        private void WriteLog(string msg)
        {
            //指定true表示追加
            using (TextWriter writer = new StreamWriter("Db.log",true))
            {
                writer.WriteLine(msg);
            }
        }
    }

public partial class EFContext<T> : DbContext where T : class
    {
        public EFContext(): base("name=MyConnectionString")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            Database.SetInitializer<EFContext<T>> (null);

            //Database.Log = log => File.AppendAllText("ef.log",string.Format("{0}{1}{2}", DateTime.Now, Environment.NewLine, log));

            DbInterception.Add(new EFDbCommandInterceptor());

            modelBuilder.Configurations.Add(new MemberMap());
            modelBuilder.Configurations.Add(new RoleMap());
            base.OnModelCreating(modelBuilder);
        }

        public DbSet<T> Table { get; set; }

        public IQueryable<T> GetList(Expression<Func<T,bool>> where)
        {
            return this.Table.Where(where);
        }
    }

其中DbInterception.Add(new EFDbCommandInterceptor());  设置日志记录

还是刚才的控制台代码,运行程序,打开Db.log

另外还有其它方法获取Entity Framework 执行的sql代码,比如SQL Server Profiler工具,不过这个不属于通过Entity Framework代码去配置,所以在此就不再赘述

时间: 2024-12-17 02:58:25

Entity Framework 6.X实现记录执行的SQL功能的相关文章

Entity Framework 删除一条记录包括所有子记录

Entity Framework 要删除一条记录,当其含有子记录时会报错: 操作失败: 无法更改关系,因为一个或多个外键属性不可以为 null.对关系作出更改后,会将相关的外键属性设置为 null 值.如果外键不支持 null 值,则必须定义新的关系,必须向外键属性分配另一个非 null 值,或必须删除无关的对象. 解决办法: 先删除子记录,再删除父记录.子记录必须是从数据库查出来的. //查询子记录 var contas = ConsignLighteringContaRepository.E

[转]Entity FrameWork利用Database.SqlQuery&lt;T&gt;执行存储过程并返回参数

本文转自:http://www.cnblogs.com/xchit/p/3334782.html 目前,EF对存储过程的支持并不完善.存在以下问题:        EF不支持存储过程返回多表联合查询的结果集.        EF仅支持返回返回某个表的全部字段,以便转换成对应的实体.无法支持返回部分字段的情况.        虽然可以正常导入返回标量值的存储过程,但是却没有为我们自动生成相应的实体.cs代码,我们还是无法在代码中直接调用或使用标量存储过程        EF不能直接支持存储过程中O

Entity FrameWork利用Database.SqlQuery&lt;T&gt;执行存储过程并返回参数

2013-09-23 14:26 by xchit, 5084 阅读, 3 评论, 收藏, 编辑 目前,EF对存储过程的支持并不完善.存在以下问题: EF不支持存储过程返回多表联合查询的结果集. EF仅支持返回返回某个表的全部字段,以便转换成对应的实体.无法支持返回部分字段的情况. 虽然可以正常导入返回标量值的存储过程,但是却没有为我们自动生成相应的实体.cs代码,我们还是无法在代码中直接调用或使用标量存储过程 EF不能直接支持存储过程中Output类型的参数. 其他一些问题. 今天我们利用EF

转:Entity FrameWork利用Database.SqlQuery&lt;T&gt;执行存储过程并返回参数

public IEnumerable<Statistic> GetStatistics(IEnumerable<Guid> itemIds) { var ctx = new DBContext(); return ctx.Database.SqlQuery<Statistic>("[dbo].[ItemStatisticsSelect] @Items, @IsPostModeration", new SqlParameter("Items&

Entity FrameWork 5 增删改查 &amp; 直接调用sql语句 ?

#region 1.0 新增 -void Add() /// <summary> /// 1.0 新增 /// </summary> static void Add() { //1.1创建实体对象 User uObj = new User() { uName = "刘德华", uLoginName = "aaa", uPwd = "asdfasdfasdfsadf", uIsDel = false, uAddtime =

Entity Framework 利用 Database.SqlQuery&lt;T&gt; 执行存储过程,并返回Output参数值

做个记录: var pCount = this._dataProvider.GetParameter(); pCount.ParameterName = "totalCount"; pCount.Direction = ParameterDirection.Output; pCount.DbType = DbType.Int32; var list = this._dbContext.SqlQuery<User>("exec P_GetList @totalCou

Entity FrameWork 5 增删改查 &amp; 直接调用sql语句

class="brush:csharp;gutter:true;"> #region 1.0 新增 -void Add() /// <summary> /// 1.0 新增 /// </summary> static void Add() { //1.1创建实体对象 User uObj = new User() { uName = "刘德华", uLoginName = "aaa", uPwd = "asd

Entity Framework 6处理User Defined Function(UDF SQL Server)

随着EF5的发布,新增了对数据库(SQL Server) UDF的支持,具体可以看以下的连接:https://msdn.microsoft.com/en-us/data/hh859577.aspx,新发布的EF6也继承了这个特性.问题是这个UDF貌似只是针对TVF-Table Value Function,在尝试导入一个SCALAR Function的时候,很可惜,该function不能被导入. 原因就是在EF6的版本里还没有对Scalar Function做支持...... 但是也有相应的wo

Entity Framework——记录执行的命令信息

有两种方法可以记录执行的SQl语句: 使用DbContext.Database.Log属性 实现IDbCommandInterceptor接口 一 使用DbContext.Database.Log属性 下面截图显示了Database属性和Log属性,可以看出这个属性是一个委托,类型为Action<string> 对Log属性的解释为: Set this property to log the SQL generated by the System.Data.Entity.DbContext t