【问题标题】:C# - NHibernate: evicting an entity and then getting itC# - NHibernate:驱逐一个实体然后得到它
【发布时间】:2019-03-04 12:41:42
【问题描述】:

我试图了解 NHibernate 的工作原理。为此,我创建了一个小测试,如下所示。但是测试在标记线上失败了,我不明白为什么。

我误会了什么?

为了简要解释代码块...我在数据库中创建了一个实体。然后我调用 Evict 从会话缓存中删除实体,以便下一次调用它会强制读取数据库。然后我进行 DB 读取,但不是从 DB 中取回实体实例,而是在标记的行上得到 NULL。

using NHibernate;
using MyCorp.MyProject.Resources.MyEntity;
using MyCorp.MyProjectTests.Common.Fixture;
using Xunit;

namespace MyCorp.MyProjectTests.Common.DB
{
    [Collection("Component")]
    public class NHibernateTest
    {
        private readonly ISessionFactory dbSessionFactory;

        public NHibernateTest(ComponentFixture componentFixture)
        {
            this.dbSessionFactory = componentFixture.DatabaseFixture.DBSessionFactory;
        }

        [Fact]
        [Trait("Category", "Component")]
        public void TestSessionCache()
        {
            const string QUERY = @"DELETE MyEntityModel mg WHERE mg.Id = :id";
            const string TITLE = "NHibernate session test object";

            using (ISession dbSession = this.dbSessionFactory.OpenSession())
            {
                // Create new entity and then remove it from session cache.
                long id = (long) dbSession.Save(new MyEntityModel
                {
                    Title = TITLE
                });
                dbSession.Evict(dbSession.Get<MyEntityModel>(id));

                // Entity loaded from DB and stored into session cache.
                Assert.Equal(TITLE, dbSession.Get<MyEntityModel>(id).Title); // ===== FAILS HERE =====

                // Delete entity from DB, but don't evict from session cache yet.
                dbSession.CreateQuery(QUERY).SetParameter("id", id).ExecuteUpdate();

                // Entity still reachable through session cache.
                Assert.Equal(TITLE, dbSession.Get<MyEntityModel>(id).Title);

                // Evict deleted entity from session cache.
                dbSession.Evict(dbSession.Get<MyEntityModel>(id));

                // Entity not available in neither DB nor session cache.
                Assert.Null(dbSession.Get<MyEntityModel>(id));
            }
        }
    }
}

【问题讨论】:

    标签: c# .net nhibernate .net-core


    【解决方案1】:

    Save() 不等于 SQL INSERT。

    Save() 意味着:让会话知道这个对象并让会话在合适的时间将它发送到数据库。根据映射和配置,这个可以在 Save() 返回之前,也可以不在。

    因此,您在对象被持久化之前将其从会话中逐出。

    如果您省略对 Evict() 的调用,您的测试将有效,因为其他代码实际上都不依赖于数据库中的项目(DELETE 语句可能表明它找到了要删除的 0 行,但这不是问题用于测试)。

    要使用自动刷新行为,您应该始终处于事务中,而不仅仅是会话中。事实上,为了获得最佳可靠性,当您在会话中时,您确实应该始终在事务中(其他模式也是可能的,但要正确使用往往更复杂)。

    以下是有关何时刷新数据库更改的文档: http://nhibernate.info/doc/nhibernate-reference/manipulatingdata.html#manipulatingdata-flushing

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-26
      • 1970-01-01
      • 1970-01-01
      • 2012-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多