2

まずは英語でごめんなさい。問題があり、助けが必要です。私はc#で自分で作った簡単なツールを持っています。このツールは、ローカルまたはリモートのfirebirdサーバー(v.2.5)に接続します。そして、私のツールは、サーバー上のどこかに指定された.fdbファイル(データベース)を作成できます。

また、SQLステートメント(テーブルの作成、トリガーなど)を含むファイルがあります。データベース作成後にこのファイルを実行したい。このファイルを実行すると、ユーザーデータベースの構造がいっぱいになります。データではなく、構造だけです。

しかし、それから私は自分のSQLスクリプトを実行しようとします-firebirdサーバーは

SQLエラーコード=-104トークン不明の行xxx列xxx。

これがこのCREATE TABLESQLステートメントの行です。例:

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ステートメントを1つだけ残すと、すべてがうまくいきます...どのように説明したかわかりません(明確かどうかはわかりません))-別の言葉-多くのcreateステートメントで完全なクエリを実行できないのはなぜですか1つのトランザクションで?クエリを実行する私のメインメソッドがあります:

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ファイルというクエリがあります。

4

2 に答える 2

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();
    }
}

これにより、次のような例外が発生します。

これは、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 に変更しても効果がないようです。

このようにローカル トランザクションを割り当てることで問題が発生する可能性がある場合、またはそれが何らかの利点がある場合、または省略することができる場合は、フィードバックをお願いします。

于 2012-12-10T18:01:20.063 に答える
1

1つのバッチで2つのcreateステートメントを起動するときにエラーが発生する可能性があります。クエリを分離するために分割すると機能しますか?SQLツールで機能しますか?

于 2010-07-20T18:52:48.740 に答える