如何查看由Entity Framework生成的SQL语句?
(在我的特定情况下,我正在使用MySQL提供程序 - 如果有影响)
如何查看由Entity Framework生成的SQL语句?
(在我的特定情况下,我正在使用MySQL提供程序 - 如果有影响)
using (MyDatabaseEntities context = new MyDatabaseEntities())
{
context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
// query the database using EF here.
}
关于在EF6中登录的更多信息,请参阅这个很棒的博客系列:http://blog.oneunicorn.com/2013/05/08/ef6-sql-logging-part-1-simple-logging/
注意:确保您的项目在DEBUG模式下运行。
你可以按照以下方式操作:
IQueryable query = from x in appEntities
where x.id == 32
select x;
var sql = ((System.Data.Objects.ObjectQuery)query).ToTraceString();
或者在EF6中:
var sql = ((System.Data.Entity.Core.Objects.ObjectQuery)query)
.ToTraceString();
或者在EF6.3+中:
var sql = ((dynamic)flooringStoresProducts).Sql;
那将为您提供生成的SQL语句。
.Single()
后,您的对象不再是IQueryable
,我想。 - Suhasresult.ToString()
。 - Scott Chamberlain从 EF6.1 开始,您可以使用拦截器注册数据库日志记录器。 请参阅章节“拦截器”和“将数据库操作记录到文件”此处。
<configuration>
<entityFramework>
<interceptors>
<interceptor type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework">
<parameters>
<parameter value="C:\Temp\LogOutput.txt"/>
<parameter value="true" type="System.Boolean"/>
</parameters>
</interceptor>
</interceptors>
</entityFramework>
</configuration>
.ToString()
来获取 SQL 语句。
var result = from i in myContext.appEntities
select new Model
{
field = i.stuff,
};
var sql = result.ToString();
ToString()
方法会将查询语句中的变量显示为 p__linq__0
等形式,而不是其最终的值(例如:显示 p__linq__0
而非 34563)。 - sports这个期待已久的功能在 EF Core 5.0 中可用!这是来自每周状态更新的消息:
var query = context.Set<Customer>().Where(c => c.City == city); Console.WriteLine(query.ToQueryString())
使用SQL Server数据库提供程序时,此输出结果如下:
DECLARE p0 nvarchar(4000) = N'London'; SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c] WHERE [c].[City] = @__city_0
注意到正确类型的参数声明也包含在输出中。这使得可以将其复制/粘贴到SQL Server Management Studio或类似工具中,以便进行调试/分析。
哇呼!!!
(注意:您需要
using Microsoft.EntityFrameworkCore;
)
using Microsoft.EntityFrameworkCore;
添加到您的類中,則可以使用以下方法直接調用擴展方法: Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToQueryString(query);
- Heitor Marcos适用于EF 6.0及以上版本: 对于那些想要了解更多关于日志功能和添加到已有答案中的人。
从EF发送到数据库的任何命令都可以被记录。 要查看来自EF 6.x生成的查询,请使用DBContext.Database.Log
属性。
被记录的内容
- SQL for all different kinds of commands. For example:
- Queries, including normal LINQ queries, eSQL queries, and raw queries from methods such as SqlQuery.
- Inserts, updates, and deletes generated as part of SaveChanges
- Relationship loading queries such as those generated by lazy loading
- Parameters
- Whether or not the command is being executed asynchronously
- A timestamp indicating when the command started executing
- Whether or not the command completed successfully, failed by throwing an exception, or, for async, was canceled
- Some indication of the result value
- The approximate amount of time it took to execute the command. Note that this is the time from sending the command to getting the result object back. It does not include time to read the results.
需要翻译的内容未提供,请提供需要翻译的内容。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();
}
输出:
SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[Title] AS [Title]
FROM [dbo].[Blogs] AS [Extent1]
WHERE (N'One Unicorn' = [Extent1].[Title]) AND ([Extent1].[Title] IS NOT NULL)
-- Executing at 10/8/2013 10:55:41 AM -07:00
-- Completed in 4 ms with result: SqlDataReader
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Title] AS [Title],
[Extent1].[BlogId] AS [BlogId]
FROM [dbo].[Posts] AS [Extent1]
WHERE [Extent1].[BlogId] = @EntityKeyValue1
-- EntityKeyValue1: '1' (Type = Int32)
-- Executing at 10/8/2013 10:55:41 AM -07:00
-- Completed in 2 ms with result: SqlDataReader
UPDATE [dbo].[Posts]
SET [Title] = @0
WHERE ([Id] = @1)
-- @0: 'Green Eggs and Ham' (Type = String, Size = -1)
-- @1: '1' (Type = Int32)
-- Executing asynchronously at 10/8/2013 10:55:41 AM -07:00
-- Completed in 12 ms with result: 1
INSERT [dbo].[Posts]([Title], [BlogId])
VALUES (@0, @1)
SELECT [Id]
FROM [dbo].[Posts]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()
-- @0: 'I do not like them!' (Type = String, Size = -1)
-- @1: '1' (Type = Int32)
-- Executing asynchronously at 10/8/2013 10:55:41 AM -07:00
-- Completed in 2 ms with result: SqlDataReader
记录到外部文件:
using (var context = new BlogContext())
{
using (var sqlLogFile = new StreamWriter("C:\\temp\\LogFile.txt"))
{
context.Database.Log = sqlLogFile.Write;
var blog = context.Blogs.First(b => b.Title == "One Unicorn");
blog.Posts.First().Title = "Green Eggs and Ham";
context.SaveChanges();
}
}
更多信息请查看:记录和拦截数据库操作
你可以在EF 4.1中执行以下操作:
var result = from x in appEntities
where x.id = 32
select x;
System.Diagnostics.Trace.WriteLine(result .ToString());
那将会给你生成的 SQL 语句。
ToString()
输出是该自定义类型的命名空间。例如,如果上面的代码是 select new CustomType { x = x.Name }
,则返回的值将类似于 Company.Models.CustomType
而不是生成的 SQL。 - Chad LevySystem.Data.Objects.ObjectQuery``1[MyProject.Models.Product]
。 - Carl G我的答案涉及EF core。我参考了这个Github问题和有关配置DbContext
的文档:
简单方法
覆盖您的DbContext
类(YourCustomDbContext
)的OnConfiguring
方法,如此示例所示,使用ConsoleLoggerProvider;您的查询应记录到控制台:
public class YourCustomDbContext : DbContext
{
#region DefineLoggerFactory
public static readonly LoggerFactory MyLoggerFactory
= new LoggerFactory(new[] {new ConsoleLoggerProvider((_, __) => true, true)});
#endregion
#region RegisterLoggerFactory
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseLoggerFactory(MyLoggerFactory); // Warning: Do not create a new ILoggerFactory instance each time
#endregion
}
复杂
这个复杂情况避免覆盖DbContext的OnConfiguring方法,这在文档中是不鼓励的:“这种方法不适合测试,除非测试目标是完整的数据库。”
这个复杂情况使用:
Startup
类的ConfigureServices
方法中使用IServiceCollection
(而不是覆盖OnConfiguring
方法; 好处是DbContext
和要使用的ILoggerProvider
之间的耦合更松散)ILoggerProvider
的实现(而不是使用上面显示的ConsoleLoggerProvider
实现; 好处是我们的实现显示了如何记录到文件(我没有看到EF Core带有的文件日志提供程序))像这样:
public class Startup
public void ConfigureServices(IServiceCollection services)
{
...
var lf = new LoggerFactory();
lf.AddProvider(new MyLoggerProvider());
services.AddDbContext<YOUR_DB_CONTEXT>(optionsBuilder => optionsBuilder
.UseSqlServer(connection_string)
//Using the LoggerFactory
.UseLoggerFactory(lf));
...
}
}
这是一个MyLoggerProvider
的实现(以及它的MyLogger
),它将日志附加到一个您可以配置的文件中;您的 EF Core 查询将出现在该文件中。
public class MyLoggerProvider : ILoggerProvider
{
public ILogger CreateLogger(string categoryName)
{
return new MyLogger();
}
public void Dispose()
{ }
private class MyLogger : ILogger
{
public bool IsEnabled(LogLevel logLevel)
{
return true;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
File.AppendAllText(@"C:\temp\log.txt", formatter(state, exception));
Console.WriteLine(formatter(state, exception));
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
}
}
为了使查询方便,且不改变代码,将以下内容添加到您的DbContext中,在Visual Studio的输出窗口中检查它即可。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.Log = (query)=> Debug.Write(query);
}
与@Matt Nibecker的答案类似,但是使用这种方法,您无需每次需要查询时都将其添加到当前代码中。
.Log
方法/属性,真是遗憾。 :( - Scott FraleyToTraceString()
。您可以将其添加到监视窗口并设置断点,以查看任何 LINQ 查询在任何给定时间点的查询情况。tail -f
尾部查询日志。您可以在 官方文档中了解有关 MySQL 日志记录工具的更多信息。对于 SQL Server 来说,最简单的方法是使用附带的 SQL Server 分析器。