0
votes

I'm looking at async-ifying some of our existing code. Unfortunately my experience with NHibernate is lacking. Most of the NHibernate stuff has been easy, considering NHibernate 5 has a lot of support for async. I am, however, stuck.

Originally, we do something like this using our Dependency Injection:

private readonly IRepository repository;

public MovieRepository(IRepository repository)
{
    this.repository = repository;
}

public Movie Get(int id)
{
    return (from movie in repository.Query<Movie>()
        select new Movie
        {
            ID = movie.ID,
            Title = movie.Title,
            Genre = new Genre
            {
                ID = movie.Genre.ID,
                Name = movie.Genre.Name,
            },
            MaleLead = movie.MaleLead,
            FemaleLead = movie.FemaleLead,
        }).FirstOrDefault();
    }

    //Repository Query method in Repository.cs
    public IQueryable<TEntity> Query<TEntity>() where TEntity : OurEntity
    {
        session = session.OpenSession();
        return from entity in session.Query<TEntity>() select entity;
    }

This works great for our current uses. We write things this way to maintain control over our queries, especially related to more complex objects, ensuring we get back exactly what we need.

I've tried a few things, like making the Query method return a Task< List< TEntity>> and using the ToListAsync() method, however because I am returning it as that kind of list I cannot query on it.

I'm sure I've missed something. If anyone can help me out, I would appreciate it.

2

2 Answers

1
votes

You need to use FirstOrDefaultAsync in this case.

public async Task<Movie> Get(int id)
{
    return await (from movie in repository.Query<Movie>()
        select new Movie
        {
            ID = movie.ID,
            Title = movie.Title,
            Genre = new Genre
            {
                ID = movie.Genre.ID,
                Name = movie.Genre.Name,
            },
            MaleLead = movie.MaleLead,
            FemaleLead = movie.FemaleLead,
        }).FirstOrDefaultAsync();
}
0
votes

Add this using statement to your file

using NHibernate.Linq;

Then you can change your method to

public async Task<Movie> Get(int id)
{
    return await (from movie in repository.Query<Movie>()
        select new Movie
        {
            ID = movie.ID,
            Title = movie.Title,
            Genre = new Genre
            {
                ID = movie.Genre.ID,
                Name = movie.Genre.Name,
            },
            MaleLead = movie.MaleLead,
            FemaleLead = movie.FemaleLead,
        }).FirstOrDefaultAsync();
}

NB: This is only available from NHibernate 5

Addendum: The code you have in Repository.cs can be simplified to something like this:

//Repository Query method in Repository.cs
public IQueryable<TEntity> Query<TEntity>() where TEntity : OurEntity
{
    //session = session.OpenSession();  //this is obviously wrong, but it's beside the point
    var session = sessionFactory.OpenSession();
    return session.Query<TEntity>();  //the fix
}