3

Nhibernate Session.Get と Session.CreateCriteria の違いは何ですか?

私の話は:

私たちの製品では、インターフェイス ISoftDeletable を追加することで softDeletion を実装しました。このインターフェイスを実装する各クラスには、deletedDate および deletedBy フィールドがあります。また、AuditableEntity クラスがあります。つまり、それを実装する各クラスには、createdDate、createdBy、modifiedDate、modifiedBy があります。

ソースは次のとおりです。

public class SaveUpdateEventListener : DefaultSaveEventListener
{

    private readonly ISecurityContextService securityContextService;

    public SaveUpdateEventListener(ISecurityContextService securityContextService)
    {
        this.securityContextService = securityContextService;
    }

    protected override object PerformSaveOrUpdate(SaveOrUpdateEvent @event)
    {
        this.PrepareAuditableEntity(@event);
        return base.PerformSaveOrUpdate(@event);
    }


    private void PrepareAuditableEntity(SaveOrUpdateEvent @event)
    {
        var entity = @event.Entity as AuditableEntity;

        if (entity == null)
        {
            return;
        }

        if (this.securityContextService.EdiPrincipal == null)
        {
            throw new Exception("No logged user.");
        } 

        if (entity.Id == 0)
        {
            this.ProcessEntityForInsert(entity);
        }
        else
        {
            this.ProcessEntityForUpdate(entity);
        }
    }


    private void ProcessEntityForUpdate(AuditableEntity entity)
    {
        entity.ModifiedBy = securityContextService.GetLoggedUser();
        entity.ModifiedDate = DateTime.Now;
    }


    private void ProcessEntityForInsert(AuditableEntity entity)
    {
        entity.CreatedBy = securityContextService.GetLoggedUser();
        entity.CreatedDate = DateTime.Now;
    }

また、Session.Get メソッドをオーバーライドしました。

public virtual T Get(long id)
    {
        if (typeof(ISoftDeletable).IsAssignableFrom(typeof(T)))
        {
            return
                this.Session.CreateCriteria(typeof(T))
                .Add(Restrictions.Eq("Id", id))
                //.Add(Restrictions.IsNull("DeletedDate"))
                .UniqueResult<T>();
        }

        return Session.Get<T>(id);
    }

あるコンテキストで、アプリケーションは、softDeletable および監査可能なエンティティの Get メソッドで StackOverflow 例外をスローしました。調査の結果、PrepareEntityForUpdate/securityContextService.GetLoggedUser とカスタム リポジトリの Get メソッドの間にループが作成されることがわかりました。ご覧のとおり、DeletedDate への制限についてコメントしました。これは、Session.Get(id) が作成された基準と同じ結果を返す必要があることを意味します。しかし、 this.Session.CreateCriteria(typeof(T)) を通過すると、StackOverflow 例外が発生します。これをコメントして return Session.Get(id) (deletiondate を考慮せずに) のみを残すと、すべて正常に動作します。

これにより、Session.Get と Session.CreateCriteria の動作が異なるように思えます。何か案は?

4

2 に答える 2

6

Get はセッション キャッシュを使用します。基準はしません。

言い換えれば、基準は常にSQLクエリ/DBへの呼び出しになります。Get は常に SQL クエリになるとは限りません。エンティティがセッションで NHibernate によって既に読み込まれており、Get を使用してエンティティを再度取得する場合、NHibernate はキャッシュから既に読み込まれているエンティティを返します。

于 2009-12-29T08:22:05.430 に答える
1

これに加えて、マッピング クラスで where パラメータを設定できます。そこに「DeletedDate IS NULL」を追加できます。Get が実行されると、NHibernate は生成されたクエリにこの WHERE ステートメントを追加します。

于 2010-01-26T22:55:38.547 に答える