0

IOC用のNhibernateとCastleで.Netを使用しています(すべてのサービスとリポジトリ用)。最近の展開で何か奇妙なことが起こり始めており、問題を追跡するのに苦労しています。

ObjA の作成後にサービスから呼び出される次のコードのチャンクがリポジトリにあります。

    public void Save(IList<ObjA> listA, IList<ObjB> listB, ObjC c, Objd d) {
        using (var session = GetSession()) {
            using (var tx = session.BeginTransaction()) {
                try {
                    session.Save(c);
                    foreach (var a in listA) {
                        session.Update(a);
                    }
                    foreach (var b in listB) {
                        // unrelated field updates here
                        session.Save(b);
                    }
                    session.Update(d);
                    if (!tx.WasCommitted) {
                        tx.Commit();
                    }
                } catch (Exception) {
                    if (tx != null) {
                        tx.Rollback();
                    }
                    throw;
                }
            }
        }
    }

このコードは、listA で 1 つの ObjA、listB で 1 つの ObjB、さらに ObjC と ObjD を渡すと呼ばれます。

ランダムに (呼び出された時間の約半分)、重複した ObjB および ObjC レコード (更新ではなく作成されているオブジェクトのみ) を取得していることがわかります。ObjC には datetime フィールドがあるため、レコードがいつ作成されたかを追跡でき、12 時間から 18 時間の間に 5 から 100 の重複レコードが作成されることがあります。これは、データベースに ObjB および ObjC レコードを作成している唯一のコードです。

私は前にこのようなものを見たことがありません. 何かがメモリに詰まっていて、断続的にこの関数 (または Nhibernate 呼び出し) を呼び出し続けているようです. この問題が発生していると思われるサーバーの 1 つで IIS を再起動すると、問題は停止しましたが、翌日別のサーバーで起動しました。

これを引き起こしている可能性のあるものについて何か考えがある人はいますか? Castle または Nhibernate の構成に、これらの呼び出しがスタックして 12 ~ 18 時間 (100 回以上) 繰り返される原因となっているものはありますか?

どんな助けでも大歓迎です:)

Service(){

    _saveLater = null;

    CalledByWS(){
        CreateObjA();
        CreateOtherObjs();  

    }   

    CreateObjA(){
        //Do a lot of stuff here

        var a = new ObjA{ };
        listToBeSaved.Add(a, SaveOrUpdate.Save);

        //Update other objects & add to the list

        if(xyz){
            _saveLater.ObjA = a
            _saveLater.ObjB = GetObjB(a);
            _saveLater.ObjC = GetObjC(a);   
        }

        _repo.SaveOrUpdate(listToBeSaved);
    }

    CreateOtherObjs(){
        if(_saveLater == null) return;

        Save(new List<ObjA> {_saveLater.ObjA}, new List<ObjB> {_saveLater.ObjB},
                _saveLater.Objc, _saveLater.ObjD);  //The original function posted
    }
}

Repo(){

  SaveOrUpdate(Dictionary<IEntity, SaveOrUpdate> objs){
    using (var session = GetSession()){
      using (var tx = session.BeginTransaction()) {
        try {
            foreach (var o in objs) {
                if (o.Key == null) continue;
                if (o.Value == SaveOrUpdate.Update)
                    session.Update(o.Key);
                else
                    session.Save(o.Key);
            }
            if (!tx.WasCommitted) {
                tx.Commit();
            }
        } catch (Exception) {
            if (tx != null) {
                tx.Rollback();
            }
            throw;
        }
      }
        }
    }


}
4

2 に答える 2

0

エイミー、何が起こっているかの最終結果を見れば、何が起こっているかがわかります。ObjA を渡すと、複数の ObjB レコードと、一意の ObjA ごとに 1 つの ObjC レコードを「作成」することになっています。この関数の範囲外で ObjA を ObjB および ObjC に関連付けてから、その変更を永続化するために保存に依存していると思います。このように考えてください。最終的には、同じ ObjA レコードに戻る外部キーを持つ多くの異なる ObjB レコードがあり、それらのほとんどは正しくありません。 何らかの理由で、実稼働コードは、この関数に渡される ObjB と ObjC の同じ ID を持つ ObjA を関連付けています。関係コードは、関数に渡される ObjA を設定する前にそれらを関連付けることさえできます。保存を呼び出す前に、ObjA とレコードの関連付けコードの新規作成を確認してください。サービスを呼び出しているサードパーティ ベンダーの 1 つが同じデータを複数回送信している可能性があることを考慮する必要がある場合があります。

于 2012-04-25T18:50:41.940 に答える
0

呼び出しがメモリにスタックするなどのより複雑な問題を探す前に、Save 関数自体が複数回トリガーされることにお金をかけていました。気付いている唯一の重複は、保存されているオブジェクトであることに注意してください。更新が複数回実行されている可能性が高く、これによる副作用は見られません。

このメソッドは Web アプリケーションから呼び出されていますか? 送信ボタンがダブルクリックされていませんか? この理論をテストするには、ログ メカニズムを追加し、Save メソッドが呼び出されたときにログを記録し、呼び出しに使用されたパラメーターを記録します。

于 2012-04-23T20:55:00.617 に答える