【问题标题】:Difference betwwen Nhibernate Session.Get and Session.CreateCriteriaNhibernate Session.Get 和 Session.CreateCriteria 的区别
【发布时间】:2009-12-29 08:15:00
【问题描述】:

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) (不考虑删除日期)一切正常。

这让我觉得 Session.Get 和 Session.CreateCriteria 的工作方式不同。 有任何想法吗?

【问题讨论】:

    标签: nhibernate soft-delete


    【解决方案1】:

    Get 将使用会话缓存。 标准不会。

    换句话说:条件总是会导致对数据库的 SQL 查询/调用。 Get 不会总是产生 sql 查询。如果 NHibernate 已经在会话中加载了一个实体,并且您想使用 Get 再次检索该实体,NHibernate 将返回它已经从其缓存中加载的实体。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 这不是一个好主意,因为 Where 子句每次都会执行,但在某些情况下可能需要显示已删除的实体,例如显示历史项目日志,您需要显示用户以太所做的所有操作,无论它是否被删除。我通过过滤器实现了这一点。这允许我在需要时启用或禁用软删除过滤器。不幸的是,过滤器不适用于获取/加载。
      猜你喜欢
      • 1970-01-01
      • 2010-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-16
      • 2021-09-11
      • 1970-01-01
      相关资源
      最近更新 更多