简体   繁体   English

将Entity Framework 6模型生成的IQueryable转换为SQL

[英]Converting IQueryable generated by Entity Framework 6 model into SQL

My application was originally built using Entity Framework 4 and a database other than SQL Server. 我的应用程序最初是使用Entity Framework 4和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. 我编写了一个函数,该函数将IQueryable转换为原始SQL,该SQL在执行时将发送到数据库。 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. 我之所以需要它,是因为我所使用的数据库无法捕捉捕获发送到服务器以执行的SQL的方法-没有像SQL Server中的SQL Profiler工具那样的工具。 I needed the SQL so I could test the query that was generated and make changes as necessary to optimize performance. 我需要SQL,因此我可以测试所生成的查询,并根据需要进行更改以优化性能。

I recently upgraded the application to Entity Framework 6 and the function to convert the IQueryable to SQL doesn't work any more. 我最近将应用程序升级到了Entity Framework 6,并且将IQueryable转换为SQL的功能不再起作用。 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 . 这不起作用,因为IQueryable返回的IQueryable并非来自ObjectQuery It's a DbQuery . 这是一个DbQuery Calling the ToString method returns the SQL with the parameters in it. 调用ToString方法将返回带有参数的SQL。 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. DbQuery类中似乎没有Parameters集合,至少没有该名称的属性。 How do I get this to work in EF6? 如何在EF6中使用它?

Entity Framework 6 provides a flexible way of tracking the queries that are sent for execution to the database server. 实体框架6提供了一种灵活的方式来跟踪发送给数据库服务器执行的查询。

Logging and Intercepting Database Operations

http://msdn.microsoft.com/en-us/data/dn469464.aspx 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(); 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM