c# - WCF 和 nHibernate 的并发问题

标签 c# wcf nhibernate

我们有一个 WCF 网络服务来处理一些业务实体。 ORM 是 nhibernate 4.0.4,.NET 4.0。 我们正在使用 IDispatchMessageInspector 在 AfterReceiveRequest 中打开 session 和事务,上下文类是 wcf_operation:

public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
    if (!CurrentSessionContext.HasBind(this.factory))
    {
        this.log.Log.Debug("Creating NH Session");
        var session = this.factory.OpenSession();
        session.FlushMode = FlushMode.Never;
        session.BeginTransaction();
        CurrentSessionContext.Bind(session);
    }

    return null;
}

在 BeforeSendReply 中提交事务并关闭 session 。 只要一次只有一个调用处理特定实体,这就有效。

如果两个并发的 web 服务尝试更新同一个实体,我会得到一个 nhibernate 异常

NHibernate.HibernateException: Illegal attempt to associate a collection with two open sessions

据我所知,两个更新在数据库级别发生冲突,我不明白 nhibernate 在这里有什么问题。 根据我的理解,两次调用的两个 session 应该是相互独立的;我在这里错过了什么吗?也许是配置?

如前所述,我看到了数据库的问题;尽管如此,我还是希望有一个异常(exception)声明有关并发更新的内容。 由于 Web 服务上的流量增加,我担心我的 session 处理存在一般性问题。

最佳答案

这个问题不是并发问题。问题是您正在以非设计的方式使用 session 。

当从数据库加载实体对象时,它属于加载它的 session 。 session 保存它已加载的所有对象的内部映射。如果您尝试让此 session 与另一个 session 加载的对象交互,它将识别出该对象不在其内部映射中并抛出异常。

请记住, session 遵循 UnitOfWork设计模式。它们注定是短暂的。您创建一个 session ,从数据库中读取,进行更改,然后丢弃该 session 以及所有内存中的对象。

NHibernate 确实提供了一种从 session 中分离对象然后将其附加到不同 session 的方法,但这种方法在并发环境中会充满危险。相反,我建议您修改您的设计,使共享对象不是 nHibernate 实体,而是对该实体的某种关键引用,它可以允许任何单独的 session 在需要时重新加载它。

如果您觉得某些对象确实应该在您的 WCF 服务的生命周期内保留在内存中,您可以使用 nHibernate 二级缓存。 This blog entry很好的解释了二级缓存。

关于c# - WCF 和 nHibernate 的并发问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37141405/

相关文章:

hibernate - 如果我学习 NHibernate,我会知道 Hibernate 吗? Spring.net 和 (Java) Spring 怎么样?

c# - 将 lambda 表达式传递给 LINQ Include() (SharePoint CSOM)

c# - 将 "TOP 1"添加到 sql 语句是否会显着提高性能?

c# - 在 WPF 中折叠网格

c# - NinjectDependencyResolver 绑定(bind) ModelValidatorProvider 失败

c# - WCF 服务 - 如何保护只有我的客户才能使用它?

c# - WCF 中的两个接口(interface)和一个具体类

c# - WCF 枚举,如果我不将成员标记为 EnumMember 会怎样?

java - 关于 hibernate 缓存

NHIbernate:投影所有属性的快捷方式?