使用参数检索 LINQ to SQL 语句 (IQueryable)

55

我正在尝试找出是否有一种方法可以检索在数据库服务器上执行的(完整)SQL语句。
我已经找到了一些东西,但它并不完全符合我的要求:

IQueryable<SomeType> someQuery = ...
string command = dataContext.GetCommand(query).CommandText;

在我的情况下,这会给我一个类似于命令字符串的东西:

SELECT TOP (50) [t0].[ID], ....
FROM [dbo].[someTable] AS [t0]
WHERE ([t0].[someColumn] IS NOT NULL) AND (([t0].[someColumn]) IN (@p0))

在数据库中执行了:

exec sp_executesql N'SELECT TOP (50) [t0].[ID], ...
FROM [dbo].[someTable] AS [t0]
WHERE ([t0].[someColumn] IS NOT NULL) AND (([t0].[someColumn]) IN (@p0, @p1))',N'@p0  int,@p1 int',@p0=401,@p1=201

有没有办法从 C# 代码中检索出这个“完整”的语句(包括参数值)?


1
请参考此处的类似问题(关于生成的SQL):https://dev59.com/QXVC5IYBdhLWcg3wihmv,它可能会提供一些见解。 - John K
6个回答

26

如果您有一个 IQueryable<T> 实例,并调用 .ToString() 方法,您也可以查看生成的 SQL 查询。
例如:

var db = new DbContext();
IQueryable<Blog> query = db.Blog.Where(tt=> tt.Id > 100).OrderByDescending(tt=>tt.Id);
var sqlString = query.ToString();
Console.WriteLine(sqlString);

这将生成以下输出:

SELECT [Extent1].[Id] AS [Id], 
[Extent1].[Title] AS [Title], 
[Extent1].[Author] AS [Author], 
[Extent1].[Text] AS [Text], 
[Extent1].[CreatedAt] AS [CreatedAt], 
[Extent1].[UpdatedAt] AS [UpdatedAt]
FROM [dbo].[Blogs] AS [Extent1]
WHERE [Extent1].[Id] > 100
ORDER BY [Extent1].[Id] DESC

8
问题是如何检索完整的语句,但您的解决方案没有包括参数。 - ViRuSTriNiTy
2
如果你使用了变量(我在示例中没有使用任何变量),它将打印出这些变量。但它不会打印变量的值。(但这很容易做到) - Nick Polyderopoulos
@phil123456,你正在使用哪个版本的EntityFramework? - Nick Polyderopoulos
1
@NickPolyderopoulos 如问题所述,他不使用EF而是使用LinqToSql,这是一种不同的技术,我认为你的答案与此无关。 - Skary

19
在EF Core 5的最新版本中,ToQueryString方法已经更新。
query.ToQueryString()

1
问题明确指出了 LinqToSql,我不明白你在这里回答关于 EF Core 5 的问题,这是完全不同的技术。 - Skary
3
@Skary,它们并不完全是不同的技术。EF是Linq to Sql的后继者。Linq to Sql今天几乎已经死亡。很多人在SO上寻找关于EF或EF Core的答案。 https://www.infoq.com/news/2008/11/DLINQ-Future/ - Emil
它们都是ORM,但在我的看法中,它们的架构非常不同。如果不是这样,请给我一个微软声明的参考。就个人而言,我不介意它是否是一种旧的死亡技术,这里的话题是LinqToSql(这是一个2011年的问题),而不是EF Core或其他ORM技术,如NHibernate或LLBL。 - Skary
抱歉,但 ToQueryString() 不返回参数。 - rChavz

15

一旦您获得命令,您可以打印CommandText,然后循环遍历参数集合并打印所有单独的参数。

此外,在调试模式下还有 linq-to-sql 调试可视化工具 可以执行相同的操作。

一个非常好用的查看查询过程的工具是 Linq-to-sql 分析器


12
(SqlCommand)dataContext.GetCommand(query)

将为您提供访问参数集合的权限。


11
需要完整的 SQL 语句。 - John K
2
@John 当向 SqlServer 发送参数化查询时,并不存在完整的 SQL 语句,首先发送的是带有参数占位符的 CommandText,然后再发送具有其类型和值的参数。 - cdel
5
同意,但是你的回答没有提供这种有用的上下文。如果你提供一个更详尽的回答,那么它的质量就会更高,观众们将能够快速地将其与问题联系起来,我会撤销踩票。 - John K
他要求完整的语句,就像你需要传递给 bcl 命令行实用程序以导出语句数据的那种。我需要完整的文本,包括 'exec' 命令以及字符串化的参数值(一个非常昂贵的映射任务)。基本上是一个你可以直接在 SSMS 中粘贴并运行的字符串。 - Triynko

7
我正在使用 Datacontext.Log 属性来获取生成的 SQL 语句(它包括语句文本和参数)
只需设置 YourDataContext.Log = SomeTextWriter
它可以写入文件(Log = new StreamWriter(@"c:\temp\linq.log"))或调试窗口,参见此文章

2
是的,所有由该DataContext生成的语句(包括selects、inserts、updates)都是。 - jaraics

1

在“本地”窗格中查看IQueryable时,您可以访问DebugView > Query,其中将包含SQL语句。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接