crazyDiamond
crazyDiamond

Reputation: 1080

Session.Query returns empty list (nHibernate)

Am new to Fluent and Nhibernate so maybe there is a simple issue I am not seeing here. Following is my mapping

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");

    }
}

Am using In memory testing to verify the repository returns the proper data. My RespositoryTestBase is as follows.

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();
    }
}

Now when I perform a get on the session as such ....I have DriverStatusChange records

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

BUT a simple Query as follows always returns an empty list.

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

Following is my test class that uses the 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
                };

    }




}

Upvotes: 0

Views: 3604

Answers (2)

moribvndvs
moribvndvs

Reputation: 42497

I don't see any transactions or Session.Flush, so I believe that's why you are not returning any results, as your changes are uncommitted. In CreateDriverStatusChanges, after

_driverStatusChangeRepository.Add(driverStatusChange);

Add

Session.Flush()

Upvotes: 1

Holf
Holf

Reputation: 6432

Try

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

_session.Query returns an IQueryable, which you can call 'ToList()' on directly.

EDIT: (Please ignore my foolishness above).

Is it because your session is getting closed and reopened before you are able to get hold of the records? I'm pretty sure SQLite InMemory just drops if the session closes. It will get recreated on the next read and will by this point be empty.

A solution is to use a Database Connection Provider that prevents connections being closed, which will also prevent the InMemory database dropping:

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;
    }
}

Then you can use this in your session factory thus:

 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();
}

Upvotes: 1

Related Questions