spring-projects / spring-net

Spring Framework for .NET
http://www.springframework.net
Apache License 2.0
849 stars 376 forks source link

asynchronous requests #194

Closed robertovaldesperez closed 2 years ago

robertovaldesperez commented 4 years ago

Good morning,

this is my Repository:

`[Transaction(ReadOnly = true)] public abstract class EntityRepository<T, K> : IEntityRepository<T, K> where T : Entity { [Autowired] public ISessionFactory SessionFactory { protected get; set; }

    protected ISession CurrentSession
    {
        get
        {
            return SessionFactory.GetCurrentSession();
        }
    }

    public FlushMode FlushMode
    {
        get
        {
            return CurrentSession.FlushMode;
        }
        set
        {
            CurrentSession.FlushMode = value;
        }
    }

    public K Save(T entity)
    {
        return (K)CurrentSession.Save(entity);
    }

    public async Task<K> SaveAsync(T entity)
    {
        return (K)await CurrentSession.SaveAsync(entity);
    }

    public void Save(IEnumerable<T> entities)
    {
        foreach (T entity in entities)
        {
            CurrentSession.Save(entity);
        }
    }

    public T Get(K id)
    {
        return CurrentSession.Get<T>(id);
    }

    public async Task<T> GetAsync(K id)
    {
        using (var session = SessionFactory.OpenSession())
        {
            return await session.GetAsync<T>(id);
        }
    }

    public IQueryable<T> GetAllQueryable()
    {
        return CurrentSession.Query<T>();
    }`

and to make asynchronous requests I have to create a new session: using (var session = SessionFactory.OpenSession()) { return await session.GetAsync<T>(id); }

@lahma how can I configure nhibernate and spring to use the current session in asynchronous requests?

lahma commented 4 years ago

This would probably require NHibernate's AsyncLocalSessionContext to be in use and Spring.NET definitely hasn't been updated to work with that. Spring.NET uses LogicalThreadContext which in turn uses ThreadStaticStorage (has backing field with [ThreadStatic] attribute). So this would require some changes to work with async flow.

robertovaldesperez commented 4 years ago

@lahma Will there be support in the future?

lahma commented 4 years ago

I personally would be more than willing to review a pull request for that 😉

robertovaldesperez commented 4 years ago

@lahma how can i create a pull request for that?

lahma commented 4 years ago

I think GitHub has quite good documentation about forking and creating PRs from your work .

lahma commented 3 years ago

@Exagram I can gladly have a look, I have rights to bring in PRs.

lahma commented 2 years ago

I'm doing a rude experiment with closing this, like what stale bot does, but maybe more human as I will probably actually react to feedback. As this issue has been stale for so long, I'll close it. If it's still an issue you would like to pursue, we can definitely reopen.

With limited resources this is just something that we need to do. Thank you for your understanding.

robsosno commented 4 months ago

I'm using Spring.NET from a long time. I stick to it because of Spring.Data, especially it's transaction management. Recently I've experimented with asynchronous code in ASP.NET Core with .NET 6. I've used following line in the controller to cause thread switching: Console.WriteLine("thisIsAsyncStart: " + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString()); await Task.Delay(3000); Console.WriteLine("thisIsAsyncEnd: " + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString()); This caused an error:

'No value for key [Spring.Data.Common.DbProvider] bound to thread [.NET TP Worker]'

I have the transaction open at the beginning of controller method. However when I've placed following in Startup.cs: ThreadStaticStorage.UseAsyncLocal = true; then everything works fine. I'm using mix of NHibernate and Spring.Data with HibernateTransactionManager. I think that this could be useful info for somebody.

Possible it would be better to have something like this: LogicalThreadContext.SetStorage(new AsyncLocalStorage()); but anyway it just works.