【问题标题】:Problem with StructureMap/nhibernate setup:StructureMap/nhibernate 设置的问题:
【发布时间】:2010-02-27 21:50:28
【问题描述】:

我不断收到以下错误:

无法访问已处置的对象。 对象名称:“AdoTransaction”。

设置遵循http://trason.net/journal/2009/10/7/bootstrapping-nhibernate-with-structuremap.html 中给出的示例

这是 IUnitOfWork 类(与链接中的完全相同):

public class UnitOfWork : IUnitOfWork
{
    private readonly ISessionFactory _sessionFactory;
    private readonly ITransaction _transaction;

    public UnitOfWork(ISessionFactory sessionFactory)
    {
        _sessionFactory = sessionFactory;
        CurrentSession = _sessionFactory.OpenSession();
        _transaction = CurrentSession.BeginTransaction();
    }

    public ISession CurrentSession { get; private set; }

    public void Dispose()
    {
        CurrentSession.Close();
        CurrentSession = null;
    }

    public void Commit()
    {
        _transaction.Commit();
    }

}

这里是 NHibernateModule(还是完全一样的!):

public class NHibernateModule : IHttpModule, IDisposable
{
    private IUnitOfWork _unitOfWork;

    public void Init(HttpApplication context)
    {
        context.BeginRequest += ContextBeginRequest;
        context.EndRequest += ContextEndRequest;
    }

    private void ContextBeginRequest(object sender, EventArgs e)
    {
        _unitOfWork = ObjectFactory.GetInstance<IUnitOfWork>();
    }

    private void ContextEndRequest(object sender, EventArgs e)
    {
        Dispose();
    }

    public void Dispose()
    {
        if (_unitOfWork == null) return;
        _unitOfWork.Commit();
        _unitOfWork.Dispose();
    }
}

这是我的仓库:

 public class Repository<T> : IRepository<T>
{
    public readonly IUnitOfWork _uow;

    public Repository(IUnitOfWork uow)
    {
        _uow = uow;
    }

    public Repository()
    {

    }

    #region IRepository<T> Members

    public IList<T> GetAll()
    {
        using (var session = _uow.CurrentSession)
        {
            return session.CreateCriteria(typeof (T)).List<T>();
        }
    }

    public IList<T> FindAll<T>(IList<Expression<Func<T, bool>>> criteria)
    {
        var session = _uow.CurrentSession;

        var query = from item in session.SessionFactory.OpenSession().Query<T>()
                              select item;
        foreach (var criterion in criteria)
        {
            query = query.Where(criterion);
        }
        return query.ToList();
    }

    public T FindFirst<T>(IList<Expression<Func<T, bool>>> criteria)
    {

        var col = FindAll(criteria);

        if (col.Count > 0)
        {
            return col.First();
        }
        else
        {
            return default(T);
        }
    }

    public T Get(int id)
    {
        using (var session = _uow.CurrentSession)
        {
            return session.Get<T>(id);
        }
    }

    public void Save(T entity)
    {
        using (var session = _uow.CurrentSession)
        {
            session.Save(entity);
        }
    }

    public void Update(T entity)
    {
        using (var session = _uow.CurrentSession)
        {
            session.Update(entity);
            session.Flush();
        }
    }

    #endregion
}
}

这是我的引导程序:

 public class BootStrapper : IBootstrapper
{
    private static bool _hasStarted;

    public virtual void BootstrapStructureMap()
    {
        ObjectFactory.Initialize(x =>
        {
            x.Scan(s =>
            {
                s.TheCallingAssembly();
                s.AssemblyContainingType<User>();
                s.AssemblyContainingType<UserRepository>();
                s.AssemblyContainingType<NHibernateRegistry>();
                s.LookForRegistries();
            });

            // Repositories
            x.For<WmcStar.Data.IUserRepository>()
                .CacheBy(InstanceScope.HttpContext)
                .TheDefault.Is.OfConcreteType<UserRepository>();

            x.For<IDatabaseBuilder>().TheDefaultIsConcreteType<DatabaseBuilder>(); 

        });
    }

    public static void Restart()
    {
        if (_hasStarted)
        {
            ObjectFactory.ResetDefaults();
        }
        else
        {
            Bootstrap();
            _hasStarted = true;
        }
    }

    public static void Bootstrap()
    {
        new BootStrapper().BootstrapStructureMap();
    }

}

这是我的 NHibernateRegistry:

public class NHibernateRegistry : Registry
{
    public NHibernateRegistry()
    {
        var cfg = new Configuration()
             .SetProperty(NHibernate.Cfg.Environment.ReleaseConnections, "on_close")
             .SetProperty(NHibernate.Cfg.Environment.Dialect, typeof(NHibernate.Dialect.MsSql2005Dialect).AssemblyQualifiedName)
             .SetProperty(NHibernate.Cfg.Environment.ConnectionDriver, typeof(NHibernate.Driver.SqlClientDriver).AssemblyQualifiedName)
             .SetProperty(NHibernate.Cfg.Environment.ConnectionString, @"my connstring")
             .SetProperty(NHibernate.Cfg.Environment.ProxyFactoryFactoryClass, typeof(ProxyFactoryFactory).AssemblyQualifiedName)
             .AddAssembly(typeof(User).Assembly);

        var sessionFactory = cfg.BuildSessionFactory();

        For<Configuration>().Singleton().Use(cfg);

        For<ISessionFactory>().Singleton().Use(sessionFactory);


        For<ISession>().HybridHttpOrThreadLocalScoped()
            .Use(ctx => ctx.GetInstance<ISessionFactory>().OpenSession());

        For<IUnitOfWork>().HybridHttpOrThreadLocalScoped()
            .Use<UnitOfWork>();

        For<IDatabaseBuilder>().Use<DatabaseBuilder>();
        SetAllProperties(x => x.OfType<IUnitOfWork>());
    }
}

最后是我的 global.asax:

    public class Global : System.Web.HttpApplication
{

    protected void Application_Start(object sender, EventArgs e)
    {
        BootStrapper.Bootstrap();
        new SchemaExport(ObjectFactory.GetInstance<Configuration>()).Execute(false, true, false);
        ObjectFactory.GetInstance<IDatabaseBuilder>().RebuildDatabase();

        AutoMapper.Mapper.CreateMap<WmcStar.Model.User, WmcStar.Data.Dto.User>();
    }
}

有人知道这是什么原因造成的吗?

w://

【问题讨论】:

    标签: nhibernate structuremap


    【解决方案1】:

    我在使用 StructureMap 和 NHibernate 时遇到了这个问题。基本上,我有结构映射映射一个命名对象(例如,CurrentUser)。在该映射中,它使用 NHibernate 会话从数据库中检索当前用户。

    然后在我的代码某处,我正在做类似的事情:

    using (var transaction = _session.BeginTransaction())
    {
      var user = ObjectFactory.GetNamedInstance<User>("CurrentUser");
      var myObjects = _session.QueryOver<myObject>().Where(x => x.User == CurrentUser).Future();
      transaction.Commit();
    }
    

    由于事务是作为当前用户操作的一部分进行处理,因此引发错误。因此,当程序执行到 transaction.Commit() 行时,没有要提交的事务。我的解决方案是将用户行移到事务语句之外:

    var user = ObjectFactory.GetNamedInstance<User>("CurrentUser");
    using (var transaction = _session.BeginTransaction())
    {
      var myObjects = _session.QueryOver<MyObject>().Where(x => x.User == CurrentUser).Future();
      transaction.Commit();
    }
    

    这将允许围绕当前用户检索的事务独立于 MyObject 的事务。

    【讨论】:

    • 谢谢,这个技巧为我节省了很多时间
    【解决方案2】:

    我不知道导致异常的确切问题是什么,但我发现了一些潜在问题:

    1. 在请求结束时提交工作单元,并在提交失败时回滚。
    2. 在请求期间抛出异常时回滚工作单元。
    3. 不要在请求结束时调用 dispose,这是在滥用类的 IDisposable。
    4. 在请求结束时处置工作单元(如果尚未处置)。
    5. 不要在存储库中的每个方法中释放会话。
    6. 在工作单元处理方法中处理会话。
    7. 您不必明确关闭会话。处理就够了。
    8. 在 dispose 方法中在会话之前释放事务。
    9. 在工作单元方法的 dispose 中使用检查来防止内存泄漏并使 dispose 方法具有垃圾收集器证明。

    键入此列表后,我认为异常是由存储库中的 using 块引起的。

    如果您想对其中一件事情进行解释,请在 cmets 中询问我。

    【讨论】:

    • 非常感谢 - 我已经完成了您所说的大部分内容,但列表中的内容:在工作单元的处置方法中使用检查以防止内存泄漏并使处置方法成为垃圾收集器证明。你能扩展一下吗?谢谢你的出色回答:) w://
    【解决方案3】:

    也许它与 StructureMap 和 NHibernate 的组合无关,而与您的代码有关?我猜测没有看到代码,但很可能您正在处理事务,然后尝试访问它。

    【讨论】:

    • 对不起老兄 - 我确实说过 nhibernate/structuremap 设置有问题
    【解决方案4】:

    当我删除对象时,我遇到了同样的错误消息。 在我的情况下,根本原因是实体属性值之一是 NULL。 我清除空值后,命令执行成功。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-09
      • 2011-10-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多