偶尔“无法初始化代理 - 无会话”

时间:2013-09-03 14:08:20

标签: c# asp.net-mvc nhibernate

我正在使用:   - NHibernate 3.1版   - C#4.5   - 温莎城堡2.5.3

NHibernate在几分钟内写下了以下类型的错误:

[36]错误NHibernate.LazyInitializationException [(null)] - 初始化[.Core。#23] - 不能初始化代理 - 没有会话。

NHibernate.LazyInitializationException:初始化[.Core。#23] - 不能初始化代理 - 没有会话。

通常工作正常,系统运行数天和负载等等。但有时候(特别是在发生一些数据库异常之后),它只是变得不稳定,并且在很多分钟内不会在许多请求的过程中恢复。 IIS重置“修复”它。

你能告诉我应该研究的地方/可能的原因是什么?我可以做些什么来强制执行NHibernate重置等等?

代码:

  private void ConfigureContainer()
    {
        _container = new DefaultTransientWindsorContainer();
        _container.Register(Component.For<IRequestState>().ImplementedBy<PerHttpRequestState>(),
                            Component.For<ISessionFactory>()
                                .UsingFactoryMethod(x => InitNHibernate())
                                .LifeStyle.Singleton
            );
        _container.Install(FromAssembly.Containing<ZetesRegistry>());
        _container.Install(FromAssembly.Containing<BusConnectorRegistry>());
        Container.InitializeWith(_container);
    }

更多代码:

  internal class TransactionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        var uow = UnitOfWork.Start();
        System.Web.HttpContext.Current.Items["uow"] = uow;
        base.OnActionExecuting(actionContext);
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext.Exception == null)
        {
            var uow = System.Web.HttpContext.Current.Items["uow"] as UnitOfWork;
            if (uow != null)
                uow.Complete();
        }
        base.OnActionExecuted(actionExecutedContext);
    }
}
提前谢谢!

更新1:

工作单位实施:

public class UnitOfWork : IUnitOfWork
{
    public ISession Session { get; private set; }

    public static IUnitOfWork Current
    {
        get { return Container.Resolve<IRequestState>().Get<IUnitOfWork>(); }
        private set { Container.Resolve<IRequestState>().Store(value); }
    }

    private UnitOfWork(bool transactional)
    {
        var sessionFactory = Container.Resolve<ISessionFactory>();
        Session = sessionFactory.OpenSession();
        if (transactional) Session.BeginTransaction(IsolationLevel.ReadCommitted);
    }

    public static IUnitOfWork Start()
    {
        return Start(true);
    }

    private static IUnitOfWork Start(bool transactional)
    {
        if (Current != null)
            throw new UnitOfWorkException("you cannot start more that one unit of work per request");
        Current = new UnitOfWork(transactional);
        return Current;
    }

    public static IUnitOfWork StartWithoutTransaction()
    {
        return Start(false);
    }

    public void Complete()
    {
        if (Session.Transaction.IsActive)
        {
            try
            {
                Session.Transaction.Commit();
            }
            catch
            {
                Session.Transaction.Rollback();
                throw;
            }
            finally
            {
                Session.Close();
            }
        }
        else
        {
            Session.Flush();
        }
    }

    public void Dispose()
    {
        if (Session != null)
        {
            var transaction = Session.Transaction;
            if (transaction != null
                && transaction.IsActive
                && !transaction.WasCommitted
                && !transaction.WasRolledBack)
            {
                transaction.Rollback();
            }
            Session.Dispose();
        }
        Current = null;
    }
}

引发错误的代码:

 public class ShippingsController : ApiController
{
    private readonly IRepository _repository;
    private readonly IPlanningDateProvider _planningDateProvider;
    private readonly IStrategicPlanningProvider _strategicPlanningProvider;

    public ShippingsController(IRepository repository, IPlanningDateProvider planningDateProvider, IStrategicPlanningProvider strategicPlanningProvider)
    {
        _repository = repository;
        _planningDateProvider = planningDateProvider;
        _strategicPlanningProvider = strategicPlanningProvider;
    }

    public Shippings Get(int id)
    {
        return Get(id, null);
    }
    public Shippings Get(int id, int? today)
    {
        var operationalPlanningCutOff = System.Web.Configuration.WebConfigurationManager.AppSettings["OperationalPlanningCutOff"];
        if (string.IsNullOrEmpty(operationalPlanningCutOff))
            operationalPlanningCutOff = "5";
        var operationalPlanningCutOffHour = int.Parse(operationalPlanningCutOff);

        if (today.HasValue && today.Value == 1)
            return _repository.Query(new GetUrgentShippingInfoForCity(id)).UniqueResult();
        return _repository.Query(new GetShippingInfoForCity(id, _planningDateProvider, operationalPlanningCutOffHour, _strategicPlanningProvider)).UniqueResult();
    }
}

3 个答案:

答案 0 :(得分:1)

不确定这是否相关但我注意到我需要为未命中onResultExecuted的过滤器异常添加回滚。不记得为什么我需要这个,但在某些情况下,我注意到我的数据库可能会留下一个已启动但从未提交/回滚的事务,因为onResultExecuted从未被命中,从而导致后续访问时出现数据库连接问题。也许你正在经历这种情况。您需要将其更改为适合您的UOW模式。

    public void OnException(ExceptionContext filterContext)
    {
        if (CurrentSessionContext.HasBind(SessionFactory))
        {
            var currentTransaction = CurrentSessionContext.Unbind(SessionFactory).Transaction;

            try
            {
                if (currentTransaction.IsActive)
                    currentTransaction.Rollback();
            }
            finally
            {
                currentTransaction.Dispose();
            }
        }
    }

答案 1 :(得分:1)

我猜你实现了无效的会话管理。执行操作后,结果将转到查看引擎。查看从对象中读取一些属性,其中一些属性可能未初始化。需要会话来初始化它们,但是在操作后关闭它。所以我认为你必须选择:

  1. 推动适当的会话管理。这是一个good example,你可以谷歌更多。
  2. 在查询级别将NHibernate指示为fetch lazy properties eagerly。但是NHibernate的冗余抽象可能会阻止你这样做。

答案 2 :(得分:0)

抱歉浪费了你的时间,但延迟加载配置中有一个拼写错误。该实体有2个属性Route And Routes,我们延迟加载Route而不是Routes。

对不起

此致