Session.Query返回空列表(nHibernate)

时间:2012-05-16 17:02:25

标签: nhibernate session fluent-nhibernate

对Fluent和Nhibernate不熟悉所以也许有一个我在这里看不到的简单问题。以下是我的映射

public class DriverStatusChangeMapping : ClassMap<DriverStatusChange>
{
    public DriverStatusChangeMapping()
    {
        Id(x => x.Id).GeneratedBy.GuidComb();
        Map(x => x.CreateReceivedAt);
        Map(x => x.RemoveReceivedAt);
        Map(x => x.Status);
        Component<AuditAction>(x => x.Created, m =>
        {
            m.Map(x => x.ActionByUser).Column("CreatedByUser");
            m.Map(x => x.ActionByUserType).Column("CreatedByUserType");
            m.Map(x => x.ActionOccurredAt).Column("CreatedAt");
        });
        Component<AuditAction>(x => x.Removed, m =>
        {
            m.Map(x => x.ActionByUser).Column("RemovedByUser");
            m.Map(x => x.ActionByUserType).Column("RemovedByUserType");
            m.Map(x => x.ActionOccurredAt).Column("RemovedAt");
        });

        References(c => c.DriverLogEntry)
            .Column("DriverLogEntryID")
            .Access.Property()
            .Cascade.All();

        Table("tblDriverStatusChange");

    }
}

使用内存测试来验证存储库是否返回了正确的数据。我的RespositoryTestBase如下。

public class RepositoryTestBase : IDisposable
{
    private static NHConfiguration.Configuration _configuration;
    private static ISessionFactory _sessionFactory;

    protected ISession Session { get; set; }

    public RepositoryTestBase()
    {
        _sessionFactory = CreateSessionFactory();
        Session = _sessionFactory.OpenSession();
        BuildSchema(Session);
    }

    private static ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
          .Database(SQLiteConfiguration.Standard.InMemory().ShowSql())
          .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Driver>())
          .ExposeConfiguration(cfg => _configuration = cfg)
          .BuildSessionFactory();

    }

    public void BuildSchema(ISession session)
    {
        var export = new SchemaExport(_configuration);
        export.Execute(true, true, false, Session.Connection, null);
    }



    public void Dispose()
    {
        Session.Dispose();
    }
}

现在,当我按照这样的方式执行get ...时,我有DriverStatusChange记录

_session.Get<DriverStatusChange>(new Guid("6c9b5d4d-986d-4ff7-86ae-a05300d34a8b")); 

但如下所示的简单查询总是返回一个空列表。

_session.Query<DriverStatusChange>().Select(d => d).ToList();

以下是我使用RepositoryTestBase

的测试类
public class DriverStatusChangeRepositoryTests:RepositoryTestBase
{
    private IDriverStatusChangeRepository _driverStatusChangeRepository;


    [SetUp]
    public void Init()
    {

        var mockLogger = new Mock<ILogger>();
        _driverStatusChangeRepository = new DriverStatusChangeRepository(Session, mockLogger.Object);


    }


    [TearDown]
    public void TearDown()
    {
        Session.Clear();
    }

    [TestFixtureTearDown]
    public void TestFixtureTearDown()
    {
        Dispose();
    }


    [Test]
    public void get_where_removed_at_is_null()
    {
      var driverStatusChanges = CreateDriverStatusChanges(4);
               var removedDriverStatusChange = driverStatusChanges[1];
                removedDriverStatusChange.Removed = new AuditAction()
                                                {
                                                    ActionByUser = "John Doe",
                                                    ActionByUserType = "User Type",
                                                    ActionOccurredAt = DateTime.UtcNow
                                                };
                removedDriverStatusChange.RemoveReceivedAt = DateTime.UtcNow;
                _driverStatusChangeRepository.Update(removedDriverStatusChange);

                var actual = _driverStatusChangeRepository.GetCurrent(10001, DateTime.MinValue, DateTime.UtcNow).Count;
                Assert.AreEqual(3,actual, "Get current did not match");




    }


    private List<DriverStatusChange> CreateDriverStatusChanges(int number)
    {

        var driverStatusChanges = new List<DriverStatusChange>();
        for (int i = 0; i < number; i++)
        {
            var driverStatusChange = new DriverStatusChange()
            {
                Created = GetCreated(i),
                CreateReceivedAt = DateTime.UtcNow,
                DriverLogEntry = new DriverLogEntry() {CreateReceivedAt = DateTime.UtcNow, Id = Guid.NewGuid(), Driver = new Driver() { DriverID = i+10000}},
                Removed = null,
                RemoveReceivedAt = null
            };
            _driverStatusChangeRepository.Add(driverStatusChange);
            driverStatusChanges.Add(driverStatusChange);

        }
        return driverStatusChanges;
    }

    private AuditAction GetCreated(int number)
    {
        return
            new AuditAction()
                {
                    ActionByUser = "Jane Doe" + number.ToString(CultureInfo.InvariantCulture),
                    ActionByUserType = "User Type",
                    ActionOccurredAt = DateTime.UtcNow
                };

    }




}

2 个答案:

答案 0 :(得分:1)

尝试

_session.Query<DriverStatusChange>().ToList();

_session.Query返回一个IQueryable,您可以直接调用'ToList()'。

编辑:(请忽略我上面的愚蠢行为)。

是否因为您的会话在关闭并重新打开之前才能获取记录?我很确定如果会话结束,SQLite InMemory就会丢失。它将在下次读取时重新创建,此时将为空。

解决方案是使用数据库连接提供程序来阻止连接被关闭,这也会阻止InMemory数据库丢失:

public class DatabaseConnectionProviderThatCachesTheConnection : DriverConnectionProvider
{
    static IDbConnection _databaseConnection;

    public override void CloseConnection(IDbConnection conn)
    {
        // Deliberately override to do nothing.
    }

    public override IDbConnection GetConnection()
    {
        if (_databaseConnection == null)
        {
            _databaseConnection = base.GetConnection();
        }

        return _databaseConnection;
    }
}

然后你可以在你的会话工厂中使用它:

 private static ISessionFactory CreateSessionFactory()
{
    return Fluently.Configure()
      .Database(SQLiteConfiguration
          .Standard
          .InMemory()
          .Raw(Environment.ConnectionProvider, 
               typeof(DatabaseConnectionProviderThatCachesTheConnection)
               .AssemblyQualifiedName)
          .ShowSql())
      .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Driver>())
      .ExposeConfiguration(cfg => _configuration = cfg)
      .BuildSessionFactory();
}

答案 1 :(得分:1)

我没有看到任何交易或Session.Flush,因此我认为这就是为什么您没有返回任何结果,因为您的更改未提交。在CreateDriverStatusChanges之后,

之后
_driverStatusChangeRepository.Add(driverStatusChange);

添加

Session.Flush()