0

クライアント用の小さなデータベース アプリケーションを作成しました。彼らは、スタッフが Access に慣れているので、Access でそれを望んでいました。問題ありません。バックエンドに使用する SQL Server があります。大まかに言えば、プロパティの継承を追跡および調査するために使用されます。

アクションのほとんどは、"Person" フォームで発生します。このフォームは、Person テーブルをいくつかの単純なルックアップ テーブル (すべてのリンク テーブルを SQL Server) に結合するクエリにバインドされています。人を調査するスタッフメンバーを割り当てるためのサブフォームと、さらにいくつかのサブフォーム (人の詳細、親戚、リンクされた法的文書など) を持つタブコントロールがあります。あちこちに少し VBA がありますが、何もありません。ファンシーすぎる。

これが私たちが目にしている問題であり、これまでのところクライアントは再現を突き止めることができませんでした (私の開発システムで再現できたことは一度もありません): Person フォームでは、サブフォームの 1 つにフォーカスしてスタッフ メンバーに割り当てるか、親戚を設定すると、Person フォームがデータベース内の別のレコードに突然切り替わります。

別のフォームが既存のレコードに対して開いているかどうかに基づいてボタンを有効/無効にするだけだった、Person フォームの Form_Activate のイベント プロシージャを無効にしようとしました。ユーザーが誤って Page Up/Page Down を押して別のレコードに移動する可能性はほとんどないことを確認しました。これは、1 人のユーザーによるテストでも時折発生していたため、同時実行の問題ではないと思われます。

これまでにこのようなものを遠くから見た人はいますか? Access がランダムに別のレコードに切り替わったことは一度もありません。また、SQL Server をバックエンドとして使用していくつかの Access アプリを作成しました。

4

1 に答える 1

0

さて、私は何が起こっているのかを理解しました。私はフロントエンドに腰を下ろし、最終的に不安定な動作に到達するまでデータを打ち込み始めました。プロファイラーは常に実行されていました。予期しないレコードの切り替えが発生するとすぐに、Profiler の出力を調べたところ、非常に明白な発火点が見つかりました。

SELECT @@IDENTITY

Access は@@IDENTITY変数を使用して、新しく挿入されたレコードの ID を取得します。問題: このテーブルにはトリガーがあり、フィールドに特定の値が含まれている場合、別のテーブルにもレコードが挿入されます。当然、この 2 番目のテーブルには ID 列があります。これは clobbering@@IDENTITYであり、Access が挿入したばかりのレコードを再クエリしようとすると、完全に別のレコードになります (ID のおかげで Person テーブルでほぼ確実に一致します)。

理想的な状況は、このトリガーを排除し、この自動挿入を VBA コードに移動することであることはわかっていますが、最小限の変更で「今すぐ機能させる」必要があるため、今のところ本当に恐ろしいハックを使用しています。

追加のレコードを挿入するトリガーで、最初の行でこれを行います。

DECLARE @id int = @@IDENTITY

次に、トリガーの最後で、次の操作を行います。

DECLARE @sql nvarchar(max) = 'DECLARE @hack TABLE (id int NOT NULL IDENTITY(' + CAST(@id AS varchar) + ', 1), a char(1)); INSERT INTO @hack (a) VALUES (''a'');'
EXEC (@sql)

これにより、 の値がローカル変数に保存@@IDENTITYされ、(動的 SQL を介して) の前の値で始まる ID 列を持つテーブル変数が宣言されます@@IDENTITY。ダミー行を挿入すると、その変数の値が、トリガーが別の場所に行を挿入する前の値にリセットされます。

これはひどい、ひどいハックですが、今のところは十分です。

于 2013-08-07T17:50:32.380 に答える