Разница между Nhibernate Session.Get и Session.CreateCriteria
В чем разница между Nhibernate Session.Get и Session.CreateCriteria?
Моя история такова:
В нашем продукте мы реализовали softDeletion, добавив интерфейс ISoftDeletable, у каждого класса, который реализует этот интерфейс, есть поля deleteDate и deleteBy. Также у нас есть класс AuditableEntity, который означает, что у каждого класса, который его реализует, есть: creationDate, creationBy,ifiedDate,ifiedBy.
Вот источники:
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);
}
Теперь в некотором контексте приложение сгенерировало исключение Stackru в методах Get для объекта softDeletable и Auditable. После некоторого исследования я заметил, что он создает цикл между PrepareEntityForUpdate/securityContextService.GetLoggedUser и методом Get из нашего пользовательского репозитория. Как вы можете заметить, я прокомментировал ограничение на DeletedDate, это означает, что Session.Get(id) должен возвращать тот же результат, что и созданные критерии. Но если я пойду через this.Session.CreateCriteria(typeof(T)), я получу исключение Stackru, если я прокомментирую это и оставлю только return Session.Get(id) (без учета deletetiondate), все работает нормально.
Это заставляет меня думать, что Session.Get и Session.CreateCriteria работают по-разному. Есть идеи?
2 ответа
Get будет использовать кеш сессии. Критерии не будут.
Другими словами: критерии всегда приводят к SQL-запросу / обращению к БД. Get не всегда приводит к SQL-запросу. Если сущность уже была загружена NHibernate в сеансе, и вы хотите снова извлечь сущность, используя Get, NHibernate вернет сущность, которую он уже загрузил, из своего кеша.
В дополнение к этому вы можете установить, где параметр в классе отображения. Там вы можете добавить: "DeletedDate IS NULL". Когда Get выполняется NHibernate, добавьте этот оператор WHERE в сгенерированный запрос.