Forums Neueste Beiträge
 

Entity Framework - ToTraceString()

09/04/2009 - 16:58 von Roland Schumacher | Report spam
Hallo

Mit ToTraceString kann man auf einem IQueryable das generierte SQL Ausgeben
lassen.

[...]
var pruefung = m_context.PruefungCol.Where(i => (i.PruefungID == id));
//Generiertes SQL ausgeben.
Trace.WriteLine((pruefung as ObjectQuery<Pruefung>).ToTraceString());
[...]

Aber wie komme ich an die Insert oder Update Statements wenn ich so was
mache?
[...]
m_context.Attach(item);
m_context.SaveChanges();
[...]

Wie kann ich mir dieses SQL ausgeben?

Gruss
Roland Schumacher alias GENiALi
http://blog.geniali.ch/
http://jotd.geniali.ch/
 

Lesen sie die antworten

#1 Frank Dzaebel
13/04/2009 - 20:32 | Warnen spam
Hallo Roland,

Mit ToTraceString kann man auf einem IQueryable das generierte SQL
Ausgeben lassen.
Aber wie komme ich an die Insert oder Update Statements wenn ich so was
mache [...] context.SaveChanges();
Wie kann ich mir dieses SQL ausgeben?



Dafür gibt es momentan AFAIK keine öffentliche .NET - Methode.
Aber man kann (auf eigene Gefahr) mit privaten Typen und
Variablen zur Lösung kommen:

using System;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections.Generic;
using System.Collections;
using System.Data.EntityClient;
using System.Data.Objects;
using System.Data.Common;

namespace EntityTestTrace
{
public static class LinqErweiterungen
{
static Assembly efAssembly = typeof(EntityCommand).Assembly;

public static string ToTraceString(this IQueryable query)
{
MethodInfo method = query.GetType().
GetMethod("ToTraceString");

if (method != null)
return method.Invoke(query, null).ToString();
else return "";
}

public static string ToTraceString(this ObjectContext context)
{
string intern = "System.Data.Mapping.Update.Internal";

Type dynUpdate = efAssembly.GetType(
intern + ".DynamicUpdateCommand");
Type updTranslate = efAssembly.GetType(
intern + ".UpdateTranslator");
Type funcUpdate = efAssembly.GetType(
intern + ".FunctionUpdateCommand");

EntityConnection conn = context.Connection as EntityConnection;
object[] parameter = new object[]
{
context.ObjectStateManager,
conn.GetMetadataWorkspace(),
conn, context.CommandTimeout
};

BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
object updTranslator = Activator.CreateInstance(updTranslate,
flags, null, parameter, null);
MethodInfo prodCommands = updTranslate
.GetMethod("ProduceCommands", flags);
object updateCommands = prodCommands.Invoke(updTranslator, null);
List<DbCommand> dbCommands = new List<DbCommand>();

foreach (object obj in (IEnumerable)updateCommands)
{
if (funcUpdate.IsInstanceOfType(obj))
{
FieldInfo dbCommand = funcUpdate.
GetField("m_dbCommand", flags);
dbCommands.Add((DbCommand)dbCommand.GetValue(obj));
}
else if (dynUpdate.IsInstanceOfType(obj))
{
MethodInfo createCommand = dynUpdate.
GetMethod("CreateCommand", flags);
object[] mParams = new object[]
{updTranslator, new Dictionary<long, object>()};
dbCommands.Add((DbCommand)createCommand.Invoke(obj, mParams));
}
else
throw new NotImplementedException("Unbekannter
Update-Kommandotyp");
}

StringBuilder ts = new StringBuilder();
foreach (DbCommand cmd in dbCommands)
{
ts.AppendLine("****** Kommando Beginn ******");
ts.AppendLine(cmd.CommandText);
ts.AppendLine("*** Parameterwerte ***:");
foreach (DbParameter p in cmd.Parameters)
ts.AppendFormat("{0} = {1}", p.ParameterName, p.Value);
ts.AppendLine("****** Kommando Ende *********");
}

return ts.ToString();
}
}
}
_________

Aufruf dann:

Trace.WriteLine(context.ToTraceString());
context.SaveChanges();
_________

Ansonsten reicht ja ggf. auch ein SQL-Profiler:

[Verwenden von SQL Server Profiler]
http://msdn.microsoft.com/de-de/lib...87929.aspx


ciao Frank
Dipl.Inf. Frank Dzaebel [MCP/MVP C#]
http://Dzaebel.NET

Ähnliche fragen