【问题标题】:windsor nHibernate ISession温莎 nHibernate ISession
【发布时间】:2014-01-15 05:47:13
【问题描述】:

我有一个 MVC5 应用程序并像这样设置我的休眠内容:

  public class PersistenceInstaller : IWindsorInstaller
{

    public void Install(IWindsorContainer container, IConfigurationStore store)
    {


        container.Register(

            //Nhibernate session factory
            Component.For<ISessionFactory>().UsingFactoryMethod(CreateNhSessionFactory).LifeStyle.Singleton,


            Component.For<ISession>().UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession()).LifestylePerWebRequest(),

            //All repoistories
            Classes.FromAssembly(Assembly.GetAssembly(typeof(HdtRepository))).InSameNamespaceAs<HdtRepository>().WithService.DefaultInterfaces().LifestyleTransient()




            );
    }

我的基础存储库如下所示:

  public abstract class RepositoryBase<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey> where TEntity : Entity<TPrimaryKey>
{

    /// <summary>
    /// Gets the NHibernate session object to perform database operations.
    /// </summary>
    public ISession Session { get; set; }


    /// <summary>
    /// Used to get a IQueryable that is used to retrive object from entire table.
    /// </summary>
    /// <returns>IQueryable to be used to select entities from database</returns>
    public IQueryable<TEntity> GetAll()
    {
        return Session.Query<TEntity>();
    }

    /// <summary>
    /// Gets an entity.
    /// </summary>
    /// <param name="key">Primary key of the entity to get</param>
    /// <returns>Entity</returns>
    public TEntity Get(TPrimaryKey key)
    {
        return Session.Get<TEntity>(key);
    }

    /// <summary>
    /// Inserts a new entity.
    /// </summary>
    /// <param name="entity">Entity</param>
    public void Insert(TEntity entity)
    {
        Session.Save(entity);
    }

    /// <summary>
    /// Updates an existing entity.
    /// </summary>
    /// <param name="entity">Entity</param>
    public void Update(TEntity entity)
    {
        Session.Update(entity);
    }

    /// <summary>
    /// Deletes an entity.
    /// </summary>
    /// <param name="id">Id of the entity</param>
    public void Delete(TPrimaryKey id)
    {
        Session.Delete(Session.Load<TEntity>(id));
    }
}

当我插入实体时,一切正常。 当我将 Session.Flush() 添加到我的 Update 方法时,更新才起作用。

这是从 Ajax 调用并执行插入或更新的方法。

 [Authorize]
    [ValidateInput(false)]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public JsonNetResult CreateOrUpdateTimeRecord(TimeRecord tr)
    {

        TimeRecord trLocal;
        if (tr.Id == -1 || tr.Id == 0)
        {
            trLocal = new TimeRecord();

            trLocal.Description = tr.Description;
            trLocal.StartTime = tr.StartTime;
            trLocal.EndTime = tr.EndTime;

            trLocal.User = _userRepo.Get(tr.User.Id);
            trLocal.Hdt = _hdtRepo.Get(tr.Hdt.Id);

            _timeRepo.Insert(trLocal);
        }
        else
        {
            trLocal = _timeRepo.Get(tr.Id);

            trLocal.Description = tr.Description;
            trLocal.StartTime = tr.StartTime;
            trLocal.EndTime = tr.EndTime;

            _timeRepo.Update(trLocal);
        }



        return new JsonNetResult() { Data = trLocal};
    }

我不明白为什么这适用于插入而不适用于更新。 我必须关心交易和打开/关闭会话吗? 我认为“LifestylePerWebRequest”会为我做到这一点。

干杯, 斯蒂芬

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-4 nhibernate castle-windsor castle


    【解决方案1】:

    :edit:(我最初的回答部分错误)

    您的实现实际上应该可以正常工作(刚刚测试过)。 尽管我可以重现尽管会话对象得到正确处理但更新未刷新的行为

    LifestylePerWebRequest 实际上处理得很好,它会在请求结束时释放会话。因此,您必须将请求句柄添加到 web.config 等......所以 Windsor 的东西完全清楚 ISession 是一次性的并且它必须处理它......

    这是因为会话的 FlushMode。

    默认模式是自动,这可能不是您真正想要的,因为您不能依赖存储的更改(尤其是更新调用)。

    您可以更改已创建会话对象的 FlushMode,或者,这是我推荐的,使用事务。

    让我们看下面的例子:

    var session = container.Resolve<ISession>();
    
    var obj = new Paper()
    {
        Author = "Author",
        Description = "Description",
    };
    session.Save(obj);
    
    obj.Author = "Author2";
    session.Update(obj);
    

    在这种情况下,更新将永远不会刷新/存储在数据库中。我猜这就是你目前的行为。

    现在让我们围绕它添加一个事务:

    var session = container.Resolve<ISession>();
    using (var transaction = session.BeginTransaction())
    {
        var obj = new Paper()
        {
            Author = "Author",
            Description = "Description",
        };
        session.Save(obj);
    
        obj.Author = "Author2";
        session.Update(obj);
    
        transaction.Commit();
    }
    

    现在肯定会保存更改。

    【讨论】:

    • 我根据以下文章尝试了 UoW:codeproject.com/Articles/543810/… 但这会导致延迟加载问题。
    • 据我了解,UoW 与 LazyLoading 不兼容,因为我在使用 UoO 属性标记的方法完成时关闭并提交了我的 Session。在我的情况下,然后我访问 Razor 中的一个属性,我完全清楚会话不能再打开了。但是我对所有这些东西都很陌生,所以如果我错了,请纠正我。目前我正在测试您发布的链接中的方法。似乎有效,但仍在测试
    • 用 UoW 属性标记控制器方法不是最简单的方法吗?
    • 但我还有一个问题,因为我想了解那些东西。在我的初始实现(上面发布的代码)中,我像这样注册了我的 ISession: Component.For().UsingFactoryMethod(k => k.Resolve().OpenSession()).LifestylePerWebRequest() 我已经问过了我自己在这个会话被关闭和刷新的地方,并认为框架将为我处理它,并且我通过“PerWebRequest()”调用来控制它。但情况似乎并非如此,因为我必须在存储库的 Update 方法中刷新我的会话。你能帮我理解吗?
    • 只是为了清楚。当我说我用 UoW 属性标记方法时,我的意思是我实现了一个 aspekt,它在开始时接受“打开”,最后接受“刷新、关闭、处置”。
    猜你喜欢
    • 1970-01-01
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多