Nhibernate Session.Get 和 Session.CreateCriteria 之间的区别

发布于 2024-08-16 10:02:06 字数 2553 浏览 5 评论 0原文

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 异常,如果我评论这个并只留下 return Session.Get(id) (不考虑删除日期)一切正常。

这让我认为 Session.Get 和 Session.CreateCriteria 的工作方式不同。 有什么想法吗?

What is the difference between Nhibernate Session.Get and Session.CreateCriteria?

My story is:

In our product we implemented a softDeletion by adding a Interface ISoftDeletable, each class which implement this Interface has deletedDate and deletedBy field. Also we have AuditableEntity class which means that each class which implement it has: createdDate, createdBy, modifiedDate, modifiedBy.

here are the sources:

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;
    }

Also we have overrided the Session.Get method.

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);
    }

Now in some context the application thrown an StackOverflow exception in the Get methods on a softDeletable and auditable entity. After some investigation I noted that it creates a loop between PrepareEntityForUpdate/securityContextService.GetLoggedUser and Get method from our custom Repository.
As you can see I've commented the restriction to DeletedDate, this means that Session.Get(id) should return same result as created criteria. But if I go though this.Session.CreateCriteria(typeof(T)) I get the StackOverflow exception, if I comment this one and leave only return Session.Get(id) (without taking in consideration deletiondate) all works fine.

This makes me to think that Session.Get and Session.CreateCriteria works differently.
Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

温折酒 2024-08-23 10:02:06

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

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

Get will use the Session cache.
Criteria will not.

In other words: Criteria will always result in a SQL query / call to the DB.
Get will not always result in a sql query. If an entity has already been loaded by NHibernate in a session, and you want to retrieve the entity again using Get, NHibernate will return the entity that it has already loaded from its cache.

一身骄傲 2024-08-23 10:02:06

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

In addition to this you can set where parameter at mapping class. There you can add: "DeletedDate IS NULL". When Get is executed NHibernate add this WHERE statement to generated query.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文