H. *_*vez 16 c# sqlcommand sqlclient
我正在构建一个自定义数据库部署实用程序,我需要读取包含sql脚本的文本文件并对数据库执行它们.
非常简单的东西,到目前为止一切顺利.
但是我遇到了一个障碍,文件的内容被成功完整地读取,但是一旦传入SqlCommand然后用SqlCommand.ExecuteNonQuery执行,只执行部分脚本.
我启动了Profiler并确认我的代码没有传递所有脚本.
private void ExecuteScript(string cmd, SqlConnection sqlConn, SqlTransaction trans)
{
SqlCommand sqlCmd = new SqlCommand(cmd, sqlConn, trans);
sqlCmd.CommandType = CommandType.Text;
sqlCmd.CommandTimeout = 9000000; // for testing
sqlCmd.ExecuteNonQuery();
}
// I call it like this, readDMLScript contains 543 lines of T-SQL
string readDMLScript = ReadFile(dmlFile);
ExecuteScript(readDMLScript, sqlConn, trans);
Run Code Online (Sandbox Code Playgroud)
Chr*_*ter 35
是的,每当他们第一次开始将SQL脚本文件的内容发送到数据库时,每个人都会遇到这个问题.
GO不是T-SQL命令.它是所有Microsoft交互式SQL工具(Management Studio,isql,osql)都认可的批处理结束标记.为了处理它,您必须编写自己的解析器来在GO语句之间分解文件中的每个文本块,并将它们作为单独的命令提供给数据库.
您如何实现解析器取决于您自己.它可能很简单(一次读取每一行,检测除了GO空格和空格之外的任何行)或复杂(标记所有语句并确定GO一个字符串中的真实语句或一些文本或多个行评论).
就个人而言,我选择了第一个选项.它可以处理您可能遇到的所有SQL文件的99%而不用大惊小怪.如果你想要全力以赴并写一个tokeniser,我相信很多人已经做了一个,只有谷歌.
例:
using(var reader = new SqlBatchReader(new StreamReader(dmlFile))) {
string batch;
while((batch = reader.ReadBatch()) != null) {
var cmd = new SqlCommand(batch, conn, trans) { CommandType = CommandType.Text };
cmd.ExecuteNonQuery();
}
}
class SqlBatchReader : IDisposable {
private TextReader _reader;
public SqlBatchReader(TextReader reader) {
_reader = reader;
}
/// <summary>
/// Return the next command batch in the file, or null if end-of-file reached.
/// </summary>
public string ReadBatch() {
// TODO: Implement your parsing logic here.
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
我在搜索此问题的答案时找到了以下代码:
优点:它简短易懂,完全符合我的需求.
缺点:它比基于流的解决方案效率低,并且区分大小写(即"GO"不是"去").
string[] commands = sql.Split(new string[]{"GO\r\n", "GO ", "GO\t"}, StringSplitOptions.RemoveEmptyEntries );
foreach (string c in commands)
{
var command = new SqlCommand(c, masterConnection);
command.ExecuteNonQuery();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14517 次 |
| 最近记录: |