My application was originally built using Entity Framework 4 and a database other than SQL Server. I wrote a function which translated an IQueryable
into the raw SQL that would be sent to the database when it was executed. I needed this because the database I was using had no way I knew of to capture the SQL that was sent to the server for executing -- there was no tool like the SQL Profiler tool in SQL Server. I needed the SQL so I could test the query that was generated and make changes as necessary to optimize performance.
I recently upgraded the application to Entity Framework 6 and the function to convert the IQueryable
to SQL doesn't work any more. Here's the function:
public static string GetSql<T>( this IQueryable<T> query ) {
string sql = ( (ObjectQuery<T>) query ).ToTraceString();
ObjectQuery<T> q = query as ObjectQuery<T>;
// Loop over the parameters in REVERSE ORDER!
foreach ( ObjectParameter p in q.Parameters.OrderByDescending( p => p.Name ) ) {
string pName = ":" + p.Name;
if ( p.Value == null )
sql = sql.Replace( pName, "NULL" );
else {
switch ( p.Value.GetType().Name ) {
case "Boolean": sql = sql.Replace( pName, (bool) p.Value ? "1" : "0" ); break;
case "Byte": sql = sql.Replace( pName, "0x" + ( (byte) p.Value ).ToString( "X2" ) ); break;
case "DateTime": sql = sql.Replace( pName, "'" + ( (DateTime) p.Value ).ToString() + "'" ); break;
case "DateTimeOffset": sql = sql.Replace( pName, "'" + ( (DateTimeOffset) p.Value ).ToString() + "'" ); break;
case "Decimal": sql = sql.Replace( pName, ( (Decimal) p.Value ).ToString() ); break;
case "Double": sql = sql.Replace( pName, ( (Double) p.Value ).ToString() ); break;
case "Guid": sql = sql.Replace( pName, "'" + ( (Guid) p.Value ).ToString( "D" ) + "'" ); break;
case "Int16": sql = sql.Replace( pName, ( (Int16) p.Value ).ToString() ); break;
case "Int32": sql = sql.Replace( pName, ( (Int32) p.Value ).ToString() ); break;
case "Int64": sql = sql.Replace( pName, ( (Int64) p.Value ).ToString() ); break;
case "Single": sql = sql.Replace( pName, ( (Single) p.Value ).ToString() ); break;
case "String": sql = sql.Replace( pName, "'" + (String) p.Value + "'" ); break;
case "UInt16": sql = sql.Replace( pName, ( (UInt16) p.Value ).ToString() ); break;
case "UInt32": sql = sql.Replace( pName, ( (UInt32) p.Value ).ToString() ); break;
case "UInt64": sql = sql.Replace( pName, ( (UInt64) p.Value ).ToString() ); break;
}
}
}
return sql;
}
This doesn't work because the IQueryable
returned by EF6 does not descend from ObjectQuery
. It's a DbQuery
. Calling the ToString
method returns the SQL with the parameters in it. I want to replace the parameters in the query with the values actually passed, as the code above did, so I can just paste the query into the query tool without editing it.
There doesn't seem to be a Parameters
collection in the DbQuery
class, at least no property with that name. How do I get this to work in EF6?
Entity Framework 6 provides a flexible way of tracking the queries that are sent for execution to the database server.
Logging and Intercepting Database Operations
http://msdn.microsoft.com/en-us/data/dn469464.aspx
using (var context = new BlogContext())
{
context.Database.Log = Console.Write;
var blog = context.Blogs.First(b => b.Title == "One Unicorn");
blog.Posts.First().Title = "Green Eggs and Ham";
blog.Posts.Add(new Post { Title = "I do not like them!" });
context.SaveChangesAsync().Wait();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.