2009-12-29 96 views
3

Nhibernate Session.Get和Session.CreateCriteria之间的区别是什么?Nhibernate Session.Get和Session.CreateCriteria之间的区别

我的故事是:

在我们的产品,我们通过增加一个接口ISoftDeletable,每一个实现该接口具有deletedDate和deletedBy领域类实现的softDeletion。我们还有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; 
    } 

同样,我们也overrided的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)(没有考虑删除日期),所有工作正常。

这让我认为Session.Get和Session.CreateCriteria的工作方式不同。 任何想法?

回答

6

获取将使用会话缓存。 准则不会。

换句话说:标准将始终导致SQL查询/调用数据库。 获取不会总是导致sql查询。如果一个实体已经被NHibernate加载到一个会话中,并且你想使用Get再次获取实体,那么NHibernate将返回它已经从其缓存中加载的实体。

1

除此之外,您可以设置映射类的参数。在那里你可以添加:“DeletedDate IS NULL”。当执行Get时,NHibernate将这个WHERE语句添加到生成的查询中。

+0

这不是个好主意,因为Where子句每次都会执行,但在某些情况下可能需要显示已删除的实体e.q.显示历史记录项目日志,您需要显示用户以太网所做的所有操作,如果删除或不删除,则不显示。我通过Filters实现了这一点。这允许我在需要时启用或禁用软删除的过滤器。不幸的是,过滤器不适用于获取/加载。 – isuruceanu 2011-09-12 14:15:25

相关问题