首先抱歉我的英语。我有问题,需要帮助。 我有一个由c#自己制作的简单工具。此工具可连接到本地或远程firebird服务器(v.2.5)。我的工具可以在服务器上的某个地方创建指定的.fdb文件(数据库)。
我还有一个带有SQL语句的文件(创建表,触发器等)。我想在创建数据库后执行此文件。执行此文件将填充用户数据库的结构 - 而不是数据,只有结构。
然后我尝试执行我的SQL脚本 - firebird服务器返回
SQL错误代码= -104令牌未知行xxx列xxx。
这是CREATE TABLE
SQL语句中的行,例如:
CREATE TABLE tb1
(
col1 INTEGER NOT NULL,
col2 VARCHAR(36)
);
/* This next create statement causes an error */
CREATE TABLE tb2
(
col1 INTEGER NOT NULL,
col2 VARCHAR(36)
);
如果我只在我的文件中留下一个创建语句 - 一切都会好...我不知道我是如何解释的(很明显或不是)) - 另一个词 - 为什么我不能执行完整查询一个事务中有多个create语句?我的主要方法是执行查询:
public static string Do(string conString, string query)
{
using (FbConnection conn = new FbConnection())
{
try
{
conn.ConnectionString = conString;
conn.Open();
FbTransaction trans = conn.BeginTransaction();
FbCommand cmd = new FbCommand(query, conn, trans);
cmd.ExecuteNonQuery();
trans.Commit();
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.ToString());
return "Transaction Fail";
}
}
return "Transaction Commited";
}
查询是我的SQL文件。
答案 0 :(得分:4)
正如Victor在他的最终评论中所说,您可以使用FBScript类进行批量执行。
我刚刚遇到了同样的任务。这个问题指出了我正确的方向,但我不得不进一步挖掘。
我在这个例子中,语句的来源是一个外部脚本文件:
private void ExecuteScript(FbConnection myConnection, string scriptPath) {
if (!File.Exists(scriptPath))
throw new FileNotFoundException("Script not found", scriptPath);
FileInfo file = new FileInfo(scriptPath);
string script = file.OpenText().ReadToEnd();
// use FbScript to parse all statements
FbScript fbs = new FbScript(script);
fbs.Parse();
// execute all statements
FbBatchExecution fbe = new FbBatchExecution(myConnection, fbs);
fbe.Execute(true);
}
这样可以正常工作,但您可能想知道为什么整个事情都没有被事务所包围。实际上,没有支持直接将FbBatchExecution“绑定”到事务中。
我尝试的第一件事是(无效)
private void ExecuteScript(FbConnection myConnection, string scriptPath) {
using (FbTransaction myTransaction = myConnection.BeginTransaction()) {
if (!File.Exists(scriptPath))
throw new FileNotFoundException("Script not found", scriptPath);
FileInfo file = new FileInfo(scriptPath);
string script = file.OpenText().ReadToEnd();
// use FbScript to parse all statements
FbScript fbs = new FbScript(script);
fbs.Parse();
// execute all statements
FbBatchExecution fbe = new FbBatchExecution(myConnection, fbs);
fbe.Execute(true);
myTransaction.Commit();
}
}
这将导致异常,指出:“当分配给命令的Connection对象处于挂起的本地事务中时,Execute要求Command对象具有Transaction对象.Command的Transaction属性尚未初始化。”< / p>
这意味着FbBatchExecution执行的命令不会分配给代码块周围的本地事务。这有助于FbBatchExecution提供 事件CommandExecuting我们可以拦截每个命令并分配我们的本地事务,如下所示:
private void ExecuteScript(FbConnection myConnection, string scriptPath) {
using (FbTransaction myTransaction = myConnection.BeginTransaction()) {
if (!File.Exists(scriptPath))
throw new FileNotFoundException("Script not found", scriptPath);
FileInfo file = new FileInfo(scriptPath);
string script = file.OpenText().ReadToEnd();
// use FbScript to parse all statements
FbScript fbs = new FbScript(script);
fbs.Parse();
// execute all statements
FbBatchExecution fbe = new FbBatchExecution(myConnection, fbs);
fbe.CommandExecuting += delegate(object sender, CommandExecutingEventArgs args) {
args.SqlCommand.Transaction = myTransaction;
};
fbe.Execute(true);
// myTransaction.Commit();
}
}
请注意,我已取消注释myTransaction.Commit()行。我对这种行为感到有些惊讶,但如果你保留该行,那么事务将抛出一个异常,表明它已经被提交。 bool参数fbe.Execute(true)被命名为“autoCommit”,但将其更改为false似乎没有效果。
如果您发现以这种方式分配本地交易的任何潜在问题,或者它是否有任何好处或者可以省略,我想要一些反馈。
答案 1 :(得分:1)
在一个批处理中启动两个create语句可能会出错。如果你将它分解为单独的查询,它会工作吗?它在您的SQL工具中有效吗?