views:

550

answers:

2

Hi All

What is the difference between Nhibernate Session.Get and Session.CreateCriteria?

My story is:

In our product we implemented a softDeletion by adding a Interface ISoftDeletable, each class which implement this Interface has deletedDate and deletedBy field. Also we have AuditableEntity class which means that each class which implement it has: createdDate, createdBy, modifiedDate, modifiedBy.

here are the sources:

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;
    }

Also we have overrided the Session.Get method.

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);
    }

Now in some context the application thrown an StackOverflow exception in the Get methods on a softDeletable and auditable entity. After some investigation I noted that it creates a loop between PrepareEntityForUpdate/securityContextService.GetLoggedUser and Get method from our custom Repository. As you can see I've commented the restriction to DeletedDate, this means that Session.Get(id) should return same result as created criteria. But if I go though this.Session.CreateCriteria(typeof(T)) I get the StackOverflow exception, if I comment this one and leave only return Session.Get(id) (without taking in consideration deletiondate) all works fine.

This makes me to think that Session.Get and Session.CreateCriteria works differently. Any ideas?

+5  A: 

Get will use the Session cache. Criteria will not.

In other words: Criteria will always result in a SQL query / call to the DB. Get will not always result in a sql query. If an entity has already been loaded by NHibernate in a session, and you want to retrieve the entity again using Get, NHibernate will return the entity that it has already loaded from its cache.

Frederik Gheysels
A: 

In addition to this you can set where parameter at mapping class. There you can add: "DeletedDate IS NULL". When Get is executed NHibernate add this where to generated query.

dario-g