복붙노트

[SQL] 어떻게 프로그램에 DbContext.SaveChanges ()에서 생성 된 SQL을 기록 할 수 있습니까? [복제]

SQL

어떻게 프로그램에 DbContext.SaveChanges ()에서 생성 된 SQL을 기록 할 수 있습니까? [복제]

이 스레드에 따르면, 우리는 생성 된 EF를 통해 SQL,하지만 DbContext.SaveChanges에 대해 ()를 로그인 할 수 있습니까? 여분의 프레임 워크없이이 일을 할 수있는 쉬운 방법이 있습니까?

해결법

  1. ==============================

    1.엔티티 프레임 워크 6.0에서 데이터베이스 클래스는 속성 액션 <문자열> 로그인이있다. 이렇게 설정 로깅만큼 간단합니다 :

    엔티티 프레임 워크 6.0에서 데이터베이스 클래스는 속성 액션 <문자열> 로그인이있다. 이렇게 설정 로깅만큼 간단합니다 :

    context.Database.Log = Console.WriteLine;
    

    고급 요구를 들어 당신은 인터셉터를 설정할 수 있습니다.

  2. ==============================

    2.http://www.codeproject.com/Articles/499902/Profiling-Entity-Framework-5-in-code를 참조하십시오. 나는 코드 첫째, POCO DbContext, 엔티티 프레임 워크 (5)을 사용하여 asp.net의 MVC 응용 프로그램에서 미스터 쿡의 아이디어를 구현했습니다.

    http://www.codeproject.com/Articles/499902/Profiling-Entity-Framework-5-in-code를 참조하십시오. 나는 코드 첫째, POCO DbContext, 엔티티 프레임 워크 (5)을 사용하여 asp.net의 MVC 응용 프로그램에서 미스터 쿡의 아이디어를 구현했습니다.

    DbContext에서 응용 프로그램 도출에 대한 컨텍스트 클래스 :

    public class MyDbContext : DbContext
    

    문맥의 생성자는 SavingChanges 이벤트를 (난 단지 디버그 빌드를 위해 고가의 반사를 수행 할) 사귀는 :

    public MyDbContext(): base("MyDbContext")
    {
    #if DEBUG
        ((IObjectContextAdapter)this).ObjectContext.SavingChanges += new EventHandler(objContext_SavingChanges);
    #endif
    }
    

    구원의 변경 이벤트는 출력 창에 생성 된 SQL을 기록합니다. 미스터 쿡에서 복사 한 코드 내가는 SQL 서버를 치는거야 때문에있는 그대로 내가 떠나 SqlParamter,에있는 DbParameter 변환,하지만 난 당신이 데이터베이스의 다른 종류를 타격하는 경우 그 변환이 실패 있으리라 믿고있어.

    public void objContext_SavingChanges(object sender, EventArgs e)
        {
            var commandText = new StringBuilder();
    
            var conn = sender.GetType()
                 .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                 .Where(p => p.Name == "Connection")
                 .Select(p => p.GetValue(sender, null))
                 .SingleOrDefault();
            var entityConn = (EntityConnection)conn;
    
            var objStateManager = (ObjectStateManager)sender.GetType()
                  .GetProperty("ObjectStateManager", BindingFlags.Instance | BindingFlags.Public)
                  .GetValue(sender, null);
    
            var workspace = entityConn.GetMetadataWorkspace();
    
            var translatorT =
                sender.GetType().Assembly.GetType("System.Data.Mapping.Update.Internal.UpdateTranslator");
    
            var translator = Activator.CreateInstance(translatorT, BindingFlags.Instance |
                BindingFlags.NonPublic, null, new object[] {objStateManager,workspace,
                entityConn,entityConn.ConnectionTimeout }, CultureInfo.InvariantCulture);
    
            var produceCommands = translator.GetType().GetMethod(
                "ProduceCommands", BindingFlags.NonPublic | BindingFlags.Instance);
    
            var commands = (IEnumerable<object>)produceCommands.Invoke(translator, null);
    
            foreach (var cmd in commands)
            {
                var identifierValues = new Dictionary<int, object>();
                var dcmd =
                    (DbCommand)cmd.GetType()
                       .GetMethod("CreateCommand", BindingFlags.Instance | BindingFlags.NonPublic)
                       .Invoke(cmd, new[] { translator, identifierValues });
    
                foreach (DbParameter param in dcmd.Parameters)
                {
                    var sqlParam = (SqlParameter)param;
    
                    commandText.AppendLine(String.Format("declare {0} {1} {2}",
                                                            sqlParam.ParameterName,
                                                            sqlParam.SqlDbType.ToString().ToLower(),
                                                            sqlParam.Size > 0 ? "(" + sqlParam.Size + ")" : ""));
    
                    commandText.AppendLine(String.Format("set {0} = '{1}'", sqlParam.ParameterName, sqlParam.SqlValue));
                }
    
                commandText.AppendLine();
                commandText.AppendLine(dcmd.CommandText);
                commandText.AppendLine("go");
                commandText.AppendLine();
            }
    
            System.Diagnostics.Debug.Write(commandText.ToString());
        }
    
  3. ==============================

    3.단기 기록을 위해, 난 그냥 DbContext의 생성자에 넣어 :

    단기 기록을 위해, 난 그냥 DbContext의 생성자에 넣어 :

    Database.Log = x => Debug.WriteLine(x);
    

    꽤 빨리 / SQL의 삭제 기록을 추가 할 수 있습니다. 긴 사용 기간의 경우와 검사에 싸여 수 있습니다

    #IFDEF DEBUG // or something similar
    
  4. ==============================

    4.당신이 EF6를 사용하여 생성 된 실제 SQL을 캡처하려면 인터셉터를 사용하여 (아마 나중에 다시 재생), 다음을 수행 할 수 있습니다.

    당신이 EF6를 사용하여 생성 된 실제 SQL을 캡처하려면 인터셉터를 사용하여 (아마 나중에 다시 재생), 다음을 수행 할 수 있습니다.

    당신의 인터셉터를 만들기

    public class InsertUpdateInterceptor : IDbCommandInterceptor
    {
        public virtual void NonQueryExecuting(
            DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
        {
            logCommand(command);
        }
    
        public virtual void ReaderExecuting(
            DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
        {
            // this will capture all SELECT queries if you care about them..
            // however it also captures INSERT statements as well 
            logCommand(command);
        }
    
        public virtual void ScalarExecuting(
         DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
        {
            logCommand(command);
        }
    
    
        private void logCommand(DbCommand dbCommand)
        {
            StringBuilder commandText = new StringBuilder();
    
            commandText.AppendLine("-- New statement generated: " + System.DateTime.Now.ToString());
            commandText.AppendLine();
    
            // as the command has a bunch of parameters, we need to declare
            // those parameters here so the SQL will execute properly
    
            foreach (DbParameter param in dbCommand.Parameters)
            {
                var sqlParam = (SqlParameter)param;
    
                commandText.AppendLine(String.Format("DECLARE {0} {1} {2}",
                                                        sqlParam.ParameterName,
                                                        sqlParam.SqlDbType.ToString().ToLower(),
                                                        getSqlDataTypeSize(sqlParam));
    
                var escapedValue = sqlParam.SqlValue.replace("'", "''");
                commandText.AppendLine(String.Format("SET {0} = '{1}'", sqlParam.ParameterName, escapedValue ));
                commandText.AppendLine();
            }
    
            commandText.AppendLine(dbCommand.CommandText);
            commandText.AppendLine("GO");
            commandText.AppendLine();
            commandText.AppendLine();
    
            System.IO.File.AppendAllText("outputfile.sql", commandText.ToString());
        }
    
        private string getSqlDataTypeSize(SqlParameter param)
        {
            if (param.Size == 0)
            {
                return "";
            }
    
            if (param.Size == -1)
            {
                return "(MAX)";
            }
    
            return "(" + param.Size + ")";
        }
    
    
        // To implement the IDbCommandInterceptor interface you need to also implement these methods like so
    
        public void NonQueryExecuted(
            DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
        {
        }
    
        public void ReaderExecuted(
            DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
        {
        }
    
        public void ScalarExecuted(
            DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
        {
        }
    }
    

    그리고 당신은 또한 당신의 인터셉터를 등록해야합니다. 당신은 ASP.NET 응용 프로그램의 메이크업 내에서이 일을하는 경우 반드시 당신은 단지 한 번 그것을 할 그렇지 않으면 동일한 요청을 여러 번 차단 될 겁니다.

    예를 DAO

    public class MyDataDAO
    {
        private static bool isDbInterceptionInitialised = false;
    
        public MyDataDAO()
        {
            if (!isDbInterceptionInitialised)
            {
                DbInterception.Add(new InsertUpdateInterceptor());
                isDbInterceptionInitialised = true;
            }
        }
    
        public void Insert(string dataToInsert)
        {
            using (myentities context = new myentities())
            {
                MyData myData = new MyData();
                myData.data = dataToInsert;
    
                // this will trigger the interceptor
                context.SaveChanges();
            }
        }
    }
    
  5. ==============================

    5.이 같은 일을하지만, 당신이 당신의 컨텍스트를 사용할 때마다 그것을 출력 창에서 SQL 쿼리를 작성합니다. 차이점은이 릴리스에서 컴파일되지 않는다는 것입니다.

    이 같은 일을하지만, 당신이 당신의 컨텍스트를 사용할 때마다 그것을 출력 창에서 SQL 쿼리를 작성합니다. 차이점은이 릴리스에서 컴파일되지 않는다는 것입니다.

    public MyEntitities()
        : base()
    {
        Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
    }
    

    이 StackOverflow의 추적 및 디버그 사이의 차이를 설명합니다.

  6. ==============================

    6.톰 레이건의 코드는 EF6 업데이트.

    톰 레이건의 코드는 EF6 업데이트.

        public void objContext_SavingChanges(object sender, EventArgs e)
        {
            var commandText = new StringBuilder();
    
            var conn = sender.GetType()
                 .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                 .Where(p => p.Name == "Connection")
                 .Select(p => p.GetValue(sender, null))
                 .SingleOrDefault();
            var entityConn = (EntityConnection)conn;
    
            var objStateManager = (System.Data.Entity.Core.Objects.ObjectStateManager)sender.GetType()
                  .GetProperty("ObjectStateManager", BindingFlags.Instance | BindingFlags.Public)
                  .GetValue(sender, null);
    
            var workspace = entityConn.GetMetadataWorkspace();
    
            var translatorT =
                sender.GetType().Assembly.GetType("System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator");
    
            var entityAdapterT =
                sender.GetType().Assembly.GetType("System.Data.Entity.Core.EntityClient.Internal.EntityAdapter");
            var entityAdapter = Activator.CreateInstance(entityAdapterT, BindingFlags.Instance |
                BindingFlags.NonPublic | BindingFlags.Public, null, new object[] { sender }, System.Globalization.CultureInfo.InvariantCulture);
    
            entityAdapterT.GetProperty("Connection").SetValue(entityAdapter, entityConn);
    
            var translator = Activator.CreateInstance(translatorT, BindingFlags.Instance |
                BindingFlags.NonPublic | BindingFlags.Public, null, new object[] { entityAdapter }, System.Globalization.CultureInfo.InvariantCulture);
    
            var produceCommands = translator.GetType().GetMethod(
                "ProduceCommands", BindingFlags.NonPublic | BindingFlags.Instance);
    
            var commands = (IEnumerable<object>)produceCommands.Invoke(translator, null);
    
            foreach (var cmd in commands)
            {
                var identifierValues = new Dictionary<int, object>();
                var dcmd =
                    (System.Data.Common.DbCommand)cmd.GetType()
                       .GetMethod("CreateCommand", BindingFlags.Instance | BindingFlags.NonPublic)
                       .Invoke(cmd, new[] { identifierValues });
    
                foreach (System.Data.Common.DbParameter param in dcmd.Parameters)
                {
                    var sqlParam = (SqlParameter)param;
    
                    commandText.AppendLine(String.Format("declare {0} {1} {2}",
                                                            sqlParam.ParameterName,
                                                            sqlParam.SqlDbType.ToString().ToLower(),
                                                            sqlParam.Size > 0 ? "(" + sqlParam.Size + ")" : ""));
    
                    commandText.AppendLine(String.Format("set {0} = '{1}'", sqlParam.ParameterName, sqlParam.SqlValue));
                }
    
                commandText.AppendLine();
                commandText.AppendLine(dcmd.CommandText);
                commandText.AppendLine("go");
                commandText.AppendLine();
            }
    
            System.Diagnostics.Debug.Write(commandText.ToString());
        }
    
  7. ==============================

    7.당신은 SQL Server 프로파일 러를 사용하여 연결중인 데이터베이스 서버에 대해 실행할 수 있습니다.

    당신은 SQL Server 프로파일 러를 사용하여 연결중인 데이터베이스 서버에 대해 실행할 수 있습니다.

  8. ==============================

    8.이것은 EFTracingProvider, 도움이 될 것입니다

    이것은 EFTracingProvider, 도움이 될 것입니다

    http://code.msdn.microsoft.com/EFProviderWrappers

  9. from https://stackoverflow.com/questions/16880687/how-can-i-log-the-generated-sql-from-dbcontext-savechanges-in-my-program by cc-by-sa and MIT license