See http://www.codeproject.com/Articles/499902/Profiling-Entity-Framework-5-in-code . I implemented Mr. Cook's idea in an asp.net mpc application using First code, POCO DbContext, Entity Framework 5.
The context class for the application comes from DbContext:
public class MyDbContext : DbContext
The context constructor triggers the SavingChanges event (I only want to make an expensive reflection for debug collections):
public MyDbContext(): base("MyDbContext") { #if DEBUG ((IObjectContextAdapter)this).ObjectContext.SavingChanges += new EventHandler(objContext_SavingChanges); #endif }
The save change event writes the generated sql to the output window. The code I copied from Mr. Cook, converts DbParameter to SqlParamter, which I leave as is, because I click on Sql Server, but I assume that the conversion will fail if you click on some other database.
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()); }
Tom Regan Aug 19 '13 at 17:04 on 2013-08-19 17:04
source share