如果在参数替换后有一种简单的方法可以获得完整的SQL语句?即,我想保留该程序运行的所有SQL的日志文件。
或者,如果我想这样做,我是否只想摆脱参数,并用一个大字符串完成旧学校的整个查询?
简单示例:我想捕获输出:
SELECT subcatId FROM EnrollmentSubCategory WHERE catid = 1
..来自此代码:
Dim subCatSQL As String = "SELECT subcatId FROM EnrollmentSubCategory WHERE catid = @catId"
Dim connectionString As String = "X"
Dim conn As New SqlConnection(connectionString)
If conn.State = ConnectionState.Closed Then
conn.Open()
End If
Dim cmd As New SqlCommand(subCatSQL, conn)
With cmd
.Parameters.Add(New SqlParameter("@catId", SqlDbType.Int, 1))
End With
Console.WriteLine("Before: " + cmd.CommandText)
cmd.Prepare()
Console.WriteLine("After: " + cmd.CommandText)
我曾假设Prepare()会做替换,但显然不是。
思考?建议吗?提前致谢。
答案 0 :(得分:6)
不,.Prepare
不这样做,事实上Command中没有任何内容。参数值永远不会替换为实际的命令字符串。它被单独发送到DB,这有几个原因:
除非您使用的是真正旧的数据库(sql server 7?),否则.Prepare()
不是必需的,实际上并没有为您做任何事情。它曾经有用,因为它会在服务器上编译查询,但现在自动完成。我很长时间没有使用.Prepare()
。
Hmmmmm。看here似乎.Prepare()
仍然为你做了一些事情:如果任何值大于参数定义的长度,.Prepare()会截断该值,这样当你执行时你不会得到错误和查询成功。凉爽。
答案 1 :(得分:5)
我通常会在项目中添加一个实用程序函数,给定一个DbCommand对象(OracleCommand的父类,SqlCommand等)将记录查询和参数值。它可能看起来像这样:
Public Shared Sub LogQuery(ByRef cmd As DbCommand)
If cmd.CommandText Is Nothing Or cmd.CommandText.Length = 0 Then
Return
End If
Dim logFile As CLog = New CLog("sql.log")
Dim msg As New StringBuilder
msg.AppendLine("*** Query ***")
msg.AppendLine(cmd.CommandText)
msg.AppendLine("*** End Query ***")
msg.AppendLine("*** Parameters ***")
For Each p As DbParameter In cmd.Parameters
msg.AppendLine(String.Format("{0}: {1}", p.ParameterName, p.Value.ToString()))
Next
msg.AppendLine("*** End Parameters ***")
logFile.WriteLog(msg.ToString() & System.Environment.NewLine)
End Sub
当我写这篇文章时,我发现它不是单独记录参数值,而是可以执行一些String.Replace()来将参数值替换为查询然后记录它:
For Each p As DbParameter In cmd.Parameters
msg = msg.Replace(p.ParameterName, p.Value.ToString())
Next
答案 2 :(得分:2)
不替换参数。 sql原样,参数本身作为参数传递给sp_executesql系统存储过程
答案 3 :(得分:1)
发送到SQL Server的内容不是用值替换的变量,而是一个准备好的语句,这样就可以重用
在SQL Server中打开探查器,你会看到正在运行的是不是SELECT subcatId FROM EnrollmentSubCategory WHERE catid = 1
答案 4 :(得分:0)
这是recently asked here。正如其他答案所指出的那样,这些参数是在带外发送的。
如果您想在服务器上执行此操作,可能是您要用于捕获的Profiler,您可以create a trace and use it as a startup job。
答案 5 :(得分:0)
您可以围绕System.Data.SqlClient
提供程序构建一个包装器(*例如,在配置文件中注册的提供程序为...... * providerName="System.Data.SqlClient"
)。基本上是一个拦截代理,您可以访问通过提供程序的所有信息,并可以虹吸您需要的内容,聚合和/或丰富它并将其发送到日志。这是一个更先进的,但打开了捕获一系列信息的大门,可以作为一个单独的关注层插入/替换/删除。
答案 6 :(得分:0)
尝试使用CommandAsSql NuGet软件包