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异常,如果我评论这个并且只留下返回Session.Get(id)(不考虑Deledate)一切正常。
这让我认为Session.Get和Session.CreateCriteria的工作方式不同。 有任何想法吗?
答案 0 :(得分:6)
Get将使用Session缓存。 标准不会。
换句话说:Criteria将始终导致对DB的SQL查询/调用。 获取不会总是导致SQL查询。如果NHibernate已经在一个会话中加载了一个实体,并且你想使用Get再次检索该实体,那么NHibernate将返回它已经从其缓存中加载的实体。
答案 1 :(得分:1)
除此之外,您还可以在映射类中设置where参数。在那里你可以添加:“DeletedDate IS NULL”。当执行Get时,NHibernate将此WHERE语句添加到生成的查询中。