查看ORM (EFCore)生成 SQL 的方法:
通用定位 ORM 生成 SQL 的方法可以总结成一条链路:
接口请求 -> TraceId -> EF Core SQL 日志 -> TagWith 标签 -> 慢 SQL / 表名 / 参数 -> SSMS 执行计划推荐做法
本地开发先看 EF Core 控制台日志
调接口后直接看控制台输出的 SQL,最快确认 ORM 到底生成了什么。日志多时先按
TraceId / RequestId过滤
一次 HTTP 请求会有一个请求标识,用它把“这个接口”和“它执行的 SQL”关联起来。给关键 LINQ 加
TagWith()
例如:
var rows = await db.Orders .TagWith("Orders.ProjectedList") .AsNoTracking() .Where(o => o.Status == status) .OrderByDescending(o => o.OrderDate) .Skip((pageIndex - 1) * pageSize) .Take(pageSize) .Select(o => new OrderListItemDto( o.OrderId, o.OrderNo, o.Customer.Name, o.TotalAmount, o.Status, o.OrderDate)) .ToListAsync();我这边添加这一行:
日志里的 SQL 会带:
-- Orders.ProjectedList SELECT ...以后直接搜:
Orders.ProjectedList就能准确定位对应 SQL。
所以日志很多时,你就搜:
Orders.ProjectedList找到它之后,从标签这一行开始,到这条 SQL 结束,就是对应的 ORM SQL。
你这段可以提取成 SSMS 可执行版本:
SET STATISTICS IO ON; SET STATISTICS TIME ON; DECLARE @__status_0 nvarchar(20) = N'Paid'; DECLARE @__p_1 int = 0; DECLARE @__p_2 int = 10; -- Orders.ProjectedList SELECT [t].[OrderId], [t].[OrderNo], [c].[Name], [t].[TotalAmount], [t].[Status], [t].[OrderDate] FROM ( SELECT [o].[OrderId], [o].[CustomerId], [o].[OrderDate], [o].[OrderNo], [o].[Status], [o].[TotalAmount] FROM [Orders] AS [o] WHERE [o].[Status] = @__status_0 ORDER BY [o].[OrderDate] DESC OFFSET @__p_1 ROWS FETCH NEXT @__p_2 ROWS ONLY ) AS [t] INNER JOIN [Customers] AS [c] ON [t].[CustomerId] = [c].[CustomerId] ORDER BY [t].[OrderDate] DESC;怎么提取
- 找日志里的
Executed DbCommand - 看
Parameters=[...],把参数转成DECLARE - 搜
Orders.ProjectedList - 从:
-- Orders.ProjectedList开始复制 5. 一直复制到本条 SQL 的最后一行 6. 放到 SSMS,前面补:
SET STATISTICS IO ON; SET STATISTICS TIME ON;这段日志怎么读
Executed DbCommand (10ms)数据库执行耗时约10ms。
@__status_0='Paid' @__p_1='0' @__p_2='10'参数值分别是:
状态 = Paid 跳过 = 0 取 10 条-- Orders.ProjectedList这是 ORM 查询标签,用来定位是哪段 LINQ。
FROM [Orders] AS [o] WHERE [o].[Status] = @__status_0 ORDER BY [o].[OrderDate] DESC OFFSET @__p_1 ROWS FETCH NEXT @__p_2 ROWS ONLY说明分页在 SQL Server 里完成。
INNER JOIN [Customers] AS [c]说明为了拿客户名,关联了客户表。
SELECT [t].[OrderId], [t].[OrderNo], [c].[Name], ...说明这是 DTO 投影查询,只查需要的列,不是SELECT *。
一句话总结
日志多时,先搜 TagWith 标签,比如 Orders.ProjectedList。 找到标签后,从标签开始复制 SQL。 再把 Parameters 转成 DECLARE,放到 SSMS 看执行计划。4. 再用表名、参数、耗时缩小范围
比如搜:
Orders Customers @__status_0='Paid' Executed DbCommand (214ms)5. 找到 SQL 后复制到 SSMS
补上参数DECLARE,打开实际执行计划和STATISTICS IO/TIME分析。
大型项目标准组合
TraceId / RequestId + EF Core Database.Command 日志 + TagWith 查询标签 + 慢 SQL 日志 + Query Store一句话:
小项目靠控制台和表名定位;大项目靠 TraceId 串请求、TagWith 标查询、慢 SQL 找重点、Query Store 看历史表现。