NHibernate:集合被修改; 枚举操作可能无法执行

Dao*_*ang 5 nhibernate

我目前正在努力解决这个问题" 收集被修改;枚举操作可能无法执行 "问题.

我搜索了这个错误消息,它都与foreach语句有关.我确实有一些foreach语句,但它们只是简单地表示数据.我没有在foreach语句中使用任何删除添加.

注意:

  1. 错误随机发生(每天约4-5次).
  2. 该应用程序是MVC网站.
  3. 大约有5个用户操作此应用程序(每天约150个订单).可能是其他用户修改了该集合,然后发生此错误?
  4. 我有log4net设置,可以在这里找到设置
  5. 确保控制器有一个无参数的公共构造函数 我在AdminProductController中有无参数的公共构造函数

有谁知道为什么会发生这种情况以及如何解决这个问题?

一位朋友(奥斯卡)提到了这一点

"理论:问题可能是你的配置和会话工厂在应用程序重启后第一次请求时被初始化.如果在第一个请求完成之前第二个请求进来,也许它也会尝试初始化然后以某种方式触发这个问题. "

非常感谢.

道明

这是错误消息:

System.InvalidOperationException集合已被修改; 枚举操作可能无法执行.System.InvalidOperationException:尝试创建"WebController.Controllers.Admin.AdminProductController"类型的控制器时发生错误.确保控制器具有无参数的公共构造函数.---> System.Reflection.TargetInvocationException:调用目标抛出了异常.---> NHibernate.MappingException:无法从输入流DomainModel.Entities.Mappings.OrderProductVariant.hbm.xml ---> System.InvalidOperationException配置数据存储:集合已被修改; 枚举操作可能无法执行. 在System.Xml.Schema的System.Xml.Schema.XmlSchemaSet.Add(String targetNamespace,XmlSchema schema)的System.Xol.Schema.XmlSchemaSet.AddSchemaToSet(XmlSchema架构)的System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext()处. NHibernate.Cfg.Configuration.LoadMappingDocument(XmlReader hbmReader,String name)中的XmlSchemaSet.Add(XmlSchema schema)位于NHibernate.Cfg.Configuration.AddInputStream(Stream xmlInputStream,String name)---内部异常堆栈跟踪结束--- at在NHibernate.Cfg.Configuration.AddAssembly的NHibernate.Cfg.Configuration.AddResource(String path,Assembly assembly)的NHibernate.Cfg.Configuration.AddInputStream(Stream xmlInputStream,String name)中的NHibernate.Cfg.Configuration.LogAndThrow(异常异常)( WebMtroller.Controllers._baseController()的DomainModel.RepositoryBase..ctor()处的SystemModel.RepositoryBase..ctor(),System.RuntimeType.CreateInstanceImpl的WebController.Controllers.Admin.AdminProductController..ctor()(Boolean publicOnly,Boolean ski pVisibilityChecks,Boolean fillCache)---内部异常堆栈跟踪的结束---在System.Web上的System.Activator.CreateInstance(Type type,Boolean nonPublic)的System.RuntimeType.CreateInstanceImpl(Boolean publicOnly,Boolean skipVisibilityChecks,Boolean fillCache)中.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext,Type controllerType)---内部异常堆栈跟踪的结束---在System.Web.Mvc.DefaultControllerFactory的System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext,Type controllerType)中System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext,AsyncCallback回调,对象状态)的System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext,IController&controller,IControllerFactory&factory)中的.CreateController(RequestContext requestContext,String controllerName)at at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()在System.Web.HttpApplication.ExecuteStep(IExecutionStep step,Boolean&completedSynchronously)

Dav*_*d M 4

奥斯卡是对的。两个单独的线程正在尝试同时初始化会话工厂。建议您在初始化代码周围放置一些锁定,也许只使用lock关键字和合适的同步对象。我们使用了这样的模式,使用 Wintellect PowerThreading 库中的锁之一:

using (_lock.WaitToRead())
{
    if (Factory != null) return Factory;
}
using (_lock.WaitToWrite())
{
    if (Factory != null) return Factory;
    Factory = ConfigureFactory();
    return Factory;
}
Run Code Online (Sandbox Code Playgroud)

您可以更简单地使用lock关键字和双重检查锁定模式,如下所示:

class NestedSessionManager
{
    internal static SessionManager _sessionManager;
    private static readonly object _syncRoot = new object();

    internal static SessionManager sessionManager
    {
        get
        {
            if (_sessionManager != null) return _sessionManager;
            lock (_syncRoot)
            {
                if (_sessionManager != null) return _sessionManager;
                _sessionManager = new SessionManager();
                return _sessionManager;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)