[SQL] 어떻게 프로그램에 DbContext.SaveChanges ()에서 생성 된 SQL을 기록 할 수 있습니까? [복제]
SQL어떻게 프로그램에 DbContext.SaveChanges ()에서 생성 된 SQL을 기록 할 수 있습니까? [복제]
이 스레드에 따르면, 우리는 생성 된 EF를 통해 SQL,하지만 DbContext.SaveChanges에 대해 ()를 로그인 할 수 있습니까? 여분의 프레임 워크없이이 일을 할 수있는 쉬운 방법이 있습니까?
해결법
-
==============================
1.엔티티 프레임 워크 6.0에서 데이터베이스 클래스는 속성 액션 <문자열> 로그인이있다. 이렇게 설정 로깅만큼 간단합니다 :
엔티티 프레임 워크 6.0에서 데이터베이스 클래스는 속성 액션 <문자열> 로그인이있다. 이렇게 설정 로깅만큼 간단합니다 :
context.Database.Log = Console.WriteLine;
고급 요구를 들어 당신은 인터셉터를 설정할 수 있습니다.
-
==============================
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.단기 기록을 위해, 난 그냥 DbContext의 생성자에 넣어 :
단기 기록을 위해, 난 그냥 DbContext의 생성자에 넣어 :
Database.Log = x => Debug.WriteLine(x);
꽤 빨리 / SQL의 삭제 기록을 추가 할 수 있습니다. 긴 사용 기간의 경우와 검사에 싸여 수 있습니다
#IFDEF DEBUG // or something similar
-
==============================
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.이 같은 일을하지만, 당신이 당신의 컨텍스트를 사용할 때마다 그것을 출력 창에서 SQL 쿼리를 작성합니다. 차이점은이 릴리스에서 컴파일되지 않는다는 것입니다.
이 같은 일을하지만, 당신이 당신의 컨텍스트를 사용할 때마다 그것을 출력 창에서 SQL 쿼리를 작성합니다. 차이점은이 릴리스에서 컴파일되지 않는다는 것입니다.
public MyEntitities() : base() { Database.Log = s => System.Diagnostics.Trace.WriteLine(s); }
이 StackOverflow의 추적 및 디버그 사이의 차이를 설명합니다.
-
==============================
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.당신은 SQL Server 프로파일 러를 사용하여 연결중인 데이터베이스 서버에 대해 실행할 수 있습니다.
당신은 SQL Server 프로파일 러를 사용하여 연결중인 데이터베이스 서버에 대해 실행할 수 있습니다.
-
==============================
8.이것은 EFTracingProvider, 도움이 될 것입니다
이것은 EFTracingProvider, 도움이 될 것입니다
http://code.msdn.microsoft.com/EFProviderWrappers
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
'SQL' 카테고리의 다른 글
[SQL] 어떻게 PostgreSQL의에서 함수 내부에서 SELECT의 결과를 반환하는? (0) | 2020.04.01 |
---|---|
[SQL] SQL 서버 : 사용하여 테이블의 기본 키를 얻기 SQL 쿼리 [중복] (0) | 2020.04.01 |
[SQL] SQL Server의 선두에 제로 패딩으로 숫자 서식 (0) | 2020.04.01 |
[SQL] SQL 쿼리는 SQL 서버에서 날짜를 삽입 (0) | 2020.04.01 |
[SQL] 필드가 null는 MySQL의에있는 경우 0을 반환 (0) | 2020.04.01 |