1

バッチで処理されているItemエンティティのリストがあります。次のようなものです。

foreach (var itemId in ItemIdList)
{
    var item = getById(itemId); //load line
    if(item != null)
    {
      //...do some processing 
      delete(item)
    }
}

問題は、同じitemIdがItemIdListに複数回リストされる可能性があるため、アイテムを削除した後、アイテムをもう一度ロードしようとすると、ロードラインがエラーで失敗することです。

Unexpected row count: 0; expected: 1  (stale state exception)

エンティティがもう存在しないことは理解していますが、get関数がnullを返すことを期待していました。これが私のgetById関数です:

var item = (from i in UnitOfWork.CurrentSession.QueryOver<T>()
                        where i.Id == id
                        select i
                        ).SingleOrDefault();

SingleOrDefaultがnullを返さないのはなぜですか?

私のItemエンティティには自動生成されたキーが1つしかなく、ハッシュ関数は次のようになります。

public override int GetHashCode()
    {
        int hashCode = 0;

        hashCode = hashCode ^ Id.GetHashCode();

        return hashCode;
    }

編集:

これが私の削除方法です

    public void Delete(T t) //T would be Item in this case
    {
       UnitOfWork.CurrentSession.Delete(t);
    }
4

1 に答える 1

2

私はあなたのdeleteメソッドを見ていませんが、これらのアイテムは「バッチ」で実行されていると述べているので、すべてが削除されるまでフラッシュするのを待つと仮定します。

すべてのアイテムを削除しようとするまでフラッシュは発生しないため、データベースにはまだ存在しています。したがって、アイテムを2回取得すると、「削除」する必要があると見なされますが、見よ、それはまだ存在しています。これが、NHibernateが状態が「古い」と考える理由です。

これを修正する簡単な方法の1つは、ItemIdListをセット(HashSetなど)にすることです。これにより、重複するIDが存在するのを防ぎ、問題を修正する必要があります。

別の注意点として、IDのリスト内のすべてのエンティティを削除しようとしている場合は、データベースから各エンティティを一度に1つずつ読み取り、それらを削除するよりもはるかに効率的な方法があります。

于 2012-08-17T19:11:30.883 に答える