ASP Mvc Nhibernate 问题

发布于 2024-11-16 04:48:12 字数 1652 浏览 1 评论 0原文

我在 MVC Web 应用程序中遇到了 Nhibernate 的一些奇怪问题。

没有 1 个一致的错误,我不断收到大量随机错误:

  • 事务未成功启动
  • 不允许启动新请求,因为它应该带有有效的事务描述符
  • 意外的行计数:-1;预期:1

为了给设置提供一些背景信息,我使用 Ninject 来 DI 会话和其他 Nhibernate 相关对象,目前我正在使用 RequestScope,但我尝试过 SingletonScope。我有一个庞大而复杂的数据模型,它作为一个整体读出,但保留在单独的部分中,因为这些都可以单独编辑和保存。

一个例子是有一个 Customer 对象,它包含一个地址对象、一个联系人对象、朋友对象、以前的订单对象等等...

所以整个对象被读出,然后映射到 UI 域模型,然后以不同的方式显示页面内的部分内容。每个部分都可以通过 ajax 单独更新,因此您可以更新 1 个部分,也可以一起更新它们。当我尝试将它们全部保存在一起时,这似乎主要给我带来了问题(因此 2-4 个同时的 ajax 请求来保存模型的块)。

现在我的集成测试运行良好,它只是测试实体的持久性和检索。整体而言,单独而言,一切都很好,但是在 Web 应用程序中,它们似乎只是不断抛出随机异常,并且最初拒绝在 Nhibernate 缓存之外保留。我找到了解决这个问题的方法,将大多数工作单元包装在事务中,这使数据得以保留,但开始向混合中添加新的错误。

最初我想从项目中废弃 Nhibernate,因为虽然我真的想要它的持久/缓存层,但它对于我的领域来说似乎不够灵活,这看起来很奇怪,因为我以前使用过它没有太多问题,尽管它不喜欢 1-1 映射。

那么有没有其他人在 ASP MVC 应用程序中遇到过这样的不稳定事务/nhibernate 问题...我知道这可能有点含糊,因为错误并不指向一件事,而且它并不总是错误,所以它就像刺入黑暗,但我没有主意,所以任何帮助都会很棒!

-- 更新 --

我无法发布所有相关代码,因为该项目很大,但事务位看起来像:

using (var transaction = sessionManager.Session.BeginTransaction(IsolationLevel.ReadUncommitted))
            {
                try
                {
                    // Do unit of work
                    transaction.Commit();

                }
                catch (Exception)
                {
                    transaction.Rollback();
                    throw;
                }
            }

我在这个项目上遇到的一些主要问题源于:

  • 与组合键存在一些 1-1 关系,但从逻辑上讲,这是有道理的
  • Nhibernate 域实体通过映射层成为 UI 域实体,然后在保存时反之亦然。这里的问题是,使用 1-1 映射时,在保留示例地址时,我必须创建一个具有正确 ID 的代理客户对象,然后合并。
  • 有很多 Ajax 处理整个模型的块(我说的是只有一个模型,但有很多顶级模型,只有一个是最重要的)

I am experiencing some bizarre problems with Nhibernate within my MVC web application.

There is not 1 consistent error, I keep getting loads of random ones:

  • Transaction not successfully started
  • New request is not allowed to start because it should come with valid transaction descriptor
  • Unexpected row count: -1; expected: 1

To give a little context to the setup, I am using Ninject to DI the sessions and other Nhibernate related objects, currently I am using RequestScope however I have tried SingletonScope. I have a large and complicated data model, which is read out as a whole, but persisted back in separate parts, as these can all be edited and saved individually.

An example would be having a Customer object, which contains a address object, a contact object, friends object, previous orders object etc etc...

So the whole object is read out, then mapped to the UI domain models and then displayed in different partials within the page. Each partial can be updated individually via ajax, so you may update 1 section or you could update them all together. It seems mainly to give me the problems when I try to persist them all together (so 2-4 simultanious ajax requests to persist chunks of the model).

Now I have integration tests that work fine, which just test the persistence and retrieval of entities. As a whole and individually and all pass fine, however in the web app they just seem to keep throwing random exceptions, and originally refused to persist outside of the Nhibernate cache. I found a way round this by wrapping most units of work within transactions, which got the data persisting but started adding new errors to the mix.

Originally I was thinking of just scrapping Nhibernate from the project, as although I really want its persistance/caching layer, it just didnt seem to be flexible enough for my domain, which seems odd as I have used it before without much problem, although it doesn't like 1-1 mappings.

So has anyone else had flakey transaction/nhibernate issues like this within an ASP MVC app... I know this may be a bit vague as the errors dont point to one thing, and it doesn't always error, so its like stabbing in the dark, but I am out of ideas so any help would be great!

-- Update --

I cannot post all relevant code as the project is huge, but the transaction bit looks like:

using (var transaction = sessionManager.Session.BeginTransaction(IsolationLevel.ReadUncommitted))
            {
                try
                {
                    // Do unit of work
                    transaction.Commit();

                }
                catch (Exception)
                {
                    transaction.Rollback();
                    throw;
                }
            }

Some of the main problems I have had on this project have stemmed from:

  • There are some 1-1 relationships with composite keys, but logically it makes sense
  • The Nhibernate domain entities go through a mapping layer to become the UI domain entities, then vice versa when saving. Problem here is that with the 1-1 mappings, when persisting the example Address I have to make a Surrogate Customer object with the correct Id then merge.
  • There is ALOT of Ajax that deals with chunks of the overall model (I talk like there is one single model, but there are quite a few top level models, just one that is most important)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

纵情客 2024-11-23 04:48:12

一些可能有帮助的注释。我使用温莎,但想象概念是相同的。听起来可能是多种因素的结合。

  • SessionFactory 应创建为单例,并且会话应针对每个 Web 请求。像这样的东西:

     绑定()
            .ToProvider()
            .InSingletonScope();
    
        绑定()
            .ToMethod( context => context.Kernel.Get().OpenSession() )
            .InRequestScope();
    
  • 小心保持事务打开时间过长,尽可能缩短它们的生命周期,以避免死锁。

    小心保持

  • 使用 NProf 等工具检查您的查询是否按预期运行。人们通常会加载过多的图表,这会影响性能并可能造成死锁。
  • 检查您的映射是否有 not.lazyload() 之类的内容,并查看您是否确实需要查询中的附加数据并将返回的结果保持在最小值。检查您的查询执行计划并确保有足够的索引。
  • 我在缓存 mvc3 操作过滤器时遇到了问题,这意味着事务并不总是启动,而是会尝试关闭,从而导致问题。将我的所有事务提交移至控制器中的 ActionResults 中,以使事务尽可能短并接近操作。
  • 检查映射中的级联并将更新保持在最低限度。

Some notes that may help. I use windsor but imagine the concepts are the same. Sounds like there may be a combination of things.

  • SessionFactory should be created as singleton and session should be per web request. Something like:

        Bind<ISessionFactory>()
            .ToProvider<SessionFactoryBuilder>()
            .InSingletonScope();
    
        Bind<ISession>()
            .ToMethod( context => context.Kernel.Get<ISessionFactory>().OpenSession() )
            .InRequestScope();
    
  • Be careful of keeping transactions open for too long, keep them as short lived as possible to avoid deadlocks.

  • Check your queries are running as as expected by using a tool like NHProf. Often people load up too much of the graph which impacts performance and can create deadlocks.
  • Check your mappings for things like not.lazyload() and see if you actually need the additional data in the queries and keep results returned to a min. Check your queries execution plans and ensure adequate indexes are in place.
  • I have had issues with mvc3 action filters being cached, which meant transactions were not always started, but would attempt to be closed causing issues. Moved all my transaction commits into ActionResults in the controllers to keep transaction as short as possible and close to the action.
  • Check your cascades in your mappings and keep the updates to a minimum.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文