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

时间:2010-04-07 14:54:00

标签: nhibernate

我目前正在努力解决这个“集合被修改;枚举操作可能无法执行”的问题。

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

注意:

  1. 错误随机发生(每天约4-5次)。
  2. 该应用程序是MVC网站。
  3. 大约有5个用户操作此应用程序(每天大约150个订单)。可能是其他用户修改了这个集合,然后发生了这个错误吗?
  4. 我有log4net设置,可以找到设置here
  5. 确保控制器具有无参数的公共构造函数我在AdminProductController中有无参数的公共构造函数
  6. 有谁知道为什么会发生这种情况以及如何解决这个问题?

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

      

    “理论:问题可能就是这样   您的配置和会话工厂   在第一个请求时初始化   应用程序重启后。如果一秒钟   请求在第一个之前提出   请求已完成,也许会   也尝试初始化然后   以某种方式触发这个问题。“

    非常感谢。

    道明

    以下是错误消息:

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

1 个答案:

答案 0 :(得分:4)

奥斯卡是对的。两个独立的线程正在尝试同时初始化会话工厂。建议你对初始化代码进行一些锁定,可能只使用lock关键字和合适的同步对象。我们使用了这样的模式,使用Wintellect PowerThreading库中的一个锁:

using (_lock.WaitToRead())
{
    if (Factory != null) return Factory;
}
using (_lock.WaitToWrite())
{
    if (Factory != null) return Factory;
    Factory = ConfigureFactory();
    return Factory;
}

您可以更简单地使用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;
            }
        }
    }
}