2009-05-04 5 views
0

メッセージテーブルにプライマリキー(Id)と外部キー(サイト)がある状況があります。どのサイトでもメッセージレコードを作成できますが、レコードを作成したサイトだけが更新できます。問題は、デフォルトではIdとSiteではなくIdに基づいて更新されるということです。プライマリキーを、IDとサイトまたはNative SQLからなる複合/複合IDに変更することができます。しかし、追加の更新基準を追加する方法があるかどうかは疑問でした。例えば、これは、デフォルトで何を得るNHibernateを使用して更新コマンドに追加の基準を追加するにはどうすればよいですか?

されています:

 
public void MessageUpdate(Message oneMessage) 
{ 
    using(ISession session = SessionFactory.OpenSession()) 
    using(ITransaction trans = session.BeginTransaction()) 
    { 
     session.Update(oneMessage); 
     trans.Commit(); 
    } 
} 

だから私は、化合物のIDを作成したり、ネイティブSQLを使用せずにNHibernateでこれをどのように行うのか:

 
Update MessageTable set MessageStatus = 2 where Id = ? and Site = ?; 
+0

サイドノートとして、あなたのコードにsession.Updateは必要ありません。これに関する詳細はこちらhttp://www.tobinharris.com/past/2009/6/11/nhibernate-calling-update-unnecessarily/ – autonomatt

答えて

0

私の最初の質問に対する簡単な答えは、アップデートに基準を追加できないことです。私が最初に提案したように、ネイティブSQLを使ってこの状況を処理することができます:

更新メッセージテーブルセットMessageStatus = 2ここでId =?サイト=?

また、Jamie Ideが示唆しているように問題に近づくこともできますが、元のメッセージを引き出すためにデータベースに対して追加のクエリが必要になります。

0

私は理解してどのようなあなたの質問のルールはビジネス上の要件ですので、おそらくNHibernateはこのルールの場所ではありません。 http://nhibernate.info/blog/2009/04/29/nhibernate-ipreupdateeventlistener-amp-ipreinserteventlistener.html

他の解決策は、レコードのサイトが変更されないようにfalseを指定してプロパティをfalseに設定することです。 http://nhibernate.info/doc/nh/en/index.html#mapping-generatedは(生成されたプロパティを参照)

+0

セキュリティルールは次のようになります。「ユーザーは、所有していないサイトのメッセージレコードを更新できませんへのアクセス"。ユーザーのログオンが侵害された場合、攻撃者は特定のサイトに関連するメッセージを混乱させるだけです。追加の更新基準があれば、受信したIDとステータスをユーザーから取得し、サイトIDをデータベースから取得できます。次に、id、siteid、statusを使用して更新文を作成できます。したがって、サイトへのアクセス権を持たないユーザーは、別のサイトのレコードを混乱させることはありません。 –

0

あなたはNHibernateの中で直接それを行うことはできませんが、あなたがあなたの更新方法を変更することができます:サイトを想定し

public void MessageUpdate(Message oneMessage, string currentSite) 
{ 
    if (oneMessage.Site != currentSite) 
    { 
     throw new Exception("meaningful error message"); 
    } 
    using(ISession session = SessionFactory.OpenSession()) 
    using(ITransaction trans = session.BeginTransaction()) 
    { 
     session.Update(oneMessage); 
     trans.Commit(); 
    } 
} 

文字列とメッセージのプロパティです。また、例外が発生した場合は、try..catchで更新をラップしてトランザクションをロールバックすることもできます。

+0

唯一の問題は、Idに基づいてレコードが更新されるため、サイトが間違っていて間違ったレコードを更新する可能性があることです。サイトを確認する唯一の真の方法は、メッセージのデータベースを照会し、サイトIDを確認し、ユーザーがアクセスできるサイトIDと比較することです。これは、私が避けようとしていたデータベースへの追加の旅行を必要とするでしょう。コンポジットIDは、サイトIDとIDの使用を要求することでこの問題を解決します。現在のところ、この問題を解決するためにネイティブSQLを使用しましたが、更新に追加の基準を追加できることを期待していました。 –

+0

"サイトが間違っていて、間違ったレコードを更新する可能性があります。 - 私が例として書いたのと同じ方法を使って更新を実行するのではない。ログインが侵害された場合、攻撃者はアプリケーションが許可するものだけを行うことができます。アプリの場合。またはサーバーが侵害され、攻撃者がこの方法を迂回したり独自のSQLを書き込んだりする可能性があります。唯一の保護は頻繁なバックアップです。 –

+0

Jamie、ご返信ありがとうございます。私は私の元の質問への短い答えは、更新プログラムに条件を追加できないことだと思います。 例では、データベース内の元のメッセージを照会し、ステータスフィールドを更新し、サイトIDだけを残して、ユーザーがアクセスできるメッセージと現在のサイトでMessageUpdateメソッドを呼び出す必要があります。 これは確かに動作しますが、ネイティブSQLを使用して、クエリを回避してwhereステートメントを使用して、ユーザーのサイトIDがレコードのサイトIDと一致することを確認できます。レコードが更新されていない場合、私は様々なアクションを取ることができます。 –

関連する問題