2009-12-29 1 views
3

В чем разница между Nhibernate Session.Get и Session.CreateCriteria?Разница между Nhibernate Session.Get и Session.CreateCriteria

Моя история:

В нашем продукте мы реализовали softDeletion путем добавления интерфейса ISoftDeletable, каждый класс, которые реализуют этот интерфейс имеет 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); 
    } 

Теперь в некотором контексте приложение брошено исключение StackOverflow в ГЭТ методов на softDeletable и проверяемой организацией. После некоторого исследования я заметил, что он создает цикл между PrepareEntityForUpdate/securityContextService.GetLoggedUser и методом Get из нашего пользовательского репозитория. Как вы можете видеть, я прокомментировал ограничение на DeletedDate, это означает, что Session.Get (id) должен возвращать тот же результат, что и созданные критерии. Но если я пойду, пусть это this.Session.CreateCriteria (typeof (T)) Я получаю исключение StackOverflow, если я прокомментирую это и оставлю только return Session.Get (id) (без учета удаления) все работает нормально.

Это заставляет меня думать, что Session.Get и Session.CreateCriteria работают по-разному. Любые идеи?

ответ

6

Get будет использовать кеш сеанса. Критерии не будут.

Другими словами: Критерии всегда будут приводить к SQL-запросу/вызову в БД. Get не всегда приведет к запросу sql. Если объект уже загружен NHibernate в сеансе, и вы хотите снова получить объект с помощью Get, NHibernate вернет объект, который он уже загрузил из своего кеша.

1

В дополнение к этому вы можете указать, где параметр в классе сопоставления. Там вы можете добавить: «DeletedDate IS NULL». Когда Get выполняется NHibernate, добавьте эту инструкцию WHERE к сгенерированному запросу.

+0

Это не очень хорошая идея, так как предложение Where будет выполняться каждый раз, но в некоторых случаях может потребоваться отображать удаленные объекты, e.q. показать журналы журналов истории, вам нужно показать все действия, сделанные пользователем, а также отсутствие матер, если они удалены или нет. Я реализовал это через фильтры. Это позволяет мне включать или отключать мягкий удаленный фильтр, когда это необходимо. К сожалению, фильтры не применяются для Get/Load. – isuruceanu