Discussion:
[nhusers] Consumer Producer architecture Could not initialize proxy - no Session
Gökhan Abatay
2018-11-29 12:05:01 UTC
Permalink
I try to implement Consumer(Multiple Thread), Producer(Single Thread that
is main one) architecture;
Producer thread owns it' NH session and retrieves data and if it' fetch
enough to process(limited by parameter like 500 record) send to Consumer
thread (consumer owns another session) to process them.

While Consumer and producer sessions both active at the same time, to
process the records I need to "Session.Evict(x)" for all records.

To access oldState for logging at Post Events I need to Consumer thread
session attach the records with below code without access to second level
cache nor database.

public static T Attach<T>(this ISession session, T entity)
{
ISessionImplementor sessionImplementor = session.GetSessionImplementation();
IEntityPersister persister = sessionImplementor.GetEntityPersister(NHibernateProxyHelper.GuessClass(entity).FullName, entity);
Object[] loadedState = persister.GetPropertyValues(entity);
Object id = persister.GetIdentifier(entity);
EntityEntry entry = sessionImplementor.PersistenceContext.AddEntry(entity, Status.Loaded, loadedState, null, id, null, LockMode.None, true, persister, true, true);
return entity;
}

Everything is fine but proxy objects stores "_session" in private variables
and it's null because I evicted by retrieval session.

How to set "_session" variable in proxy classes at entity level, is there
any function to do that.
If I use reflection to get Proxy Properties I am afraid for bad performance
and it needed to be recursive.
If I can get entity owned proxy properties with recursive I can call
ILazyInitializer.SetSession?

Am I doing something wrong because I need very good performance using
parallel threads.

NHibernate.Proxy.AbstractLazyInitializer.Initialize() in C:\nhibernate-master\nhibernate-core-master\src\NHibernate\Proxy\AbstractLazyInitializer.cs:line 115
at NHibernate.Proxy.AbstractLazyInitializer.GetImplementation() in C:\nhibernate-master\nhibernate-core-master\src\NHibernate\Proxy\AbstractLazyInitializer.cs:line 191
at MemberDefinitionProxy.get_IsAdmin()
at Framework.Batch.Eod.ConsumerProducerBatch.Consume(List`1 items) in D:\Framework.Batch\Eod\SampleEodBatch.cs:line 85
at Framework.Facilities.Batch.BaseBatch`1.<>c__DisplayClass26_0.<RunConsume>b__1() in D:\Framework.Facilities.Batch\BaseBatch.cs:line 289
at Framework.Facilities.Batch.BaseBatch.Handle(UnitOfWorkAttribute unitOfWork, Action T0, Action T1, Action T2) in D:\Framework.Facilities.Batch\BaseBatch.cs:line 54
--
You received this message because you are subscribed to the Google Groups "nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhusers+***@googlegroups.com.
To post to this group, send email to ***@googlegroups.com.
Visit this group at https://groups.google.com/group/nhusers.
For more options, visit https://groups.google.com/d/optout.
Oskar Berggren
2018-11-29 18:25:59 UTC
Permalink
I looks to me like you are accessing a bunch of interfaces that are not
necessarily the official way to work with NHibernate. The ISession provides
the interface to reattach objects.

Personally I've always found Evict/Attach messy, to be honest.

You mention that you need very good performance. I'm not convinced that
shifting loaded entities between threads and sessions using evict/attach is
the best way to achieve that. Have you explored having multiple threads
just reading from the database themselves?

/Oskar
Post by Gökhan Abatay
I try to implement Consumer(Multiple Thread), Producer(Single Thread that
is main one) architecture;
Producer thread owns it' NH session and retrieves data and if it' fetch
enough to process(limited by parameter like 500 record) send to Consumer
thread (consumer owns another session) to process them.
While Consumer and producer sessions both active at the same time, to
process the records I need to "Session.Evict(x)" for all records.
To access oldState for logging at Post Events I need to Consumer thread
session attach the records with below code without access to second level
cache nor database.
public static T Attach<T>(this ISession session, T entity)
{
ISessionImplementor sessionImplementor = session.GetSessionImplementation();
IEntityPersister persister = sessionImplementor.GetEntityPersister(NHibernateProxyHelper.GuessClass(entity).FullName, entity);
Object[] loadedState = persister.GetPropertyValues(entity);
Object id = persister.GetIdentifier(entity);
EntityEntry entry = sessionImplementor.PersistenceContext.AddEntry(entity, Status.Loaded, loadedState, null, id, null, LockMode.None, true, persister, true, true);
return entity;
}
Everything is fine but proxy objects stores "_session" in private
variables and it's null because I evicted by retrieval session.
How to set "_session" variable in proxy classes at entity level, is there
any function to do that.
If I use reflection to get Proxy Properties I am afraid for bad
performance and it needed to be recursive.
If I can get entity owned proxy properties with recursive I can call
ILazyInitializer.SetSession?
Am I doing something wrong because I need very good performance using
parallel threads.
NHibernate.Proxy.AbstractLazyInitializer.Initialize() in C:\nhibernate-master\nhibernate-core-master\src\NHibernate\Proxy\AbstractLazyInitializer.cs:line 115
at NHibernate.Proxy.AbstractLazyInitializer.GetImplementation() in C:\nhibernate-master\nhibernate-core-master\src\NHibernate\Proxy\AbstractLazyInitializer.cs:line 191
at MemberDefinitionProxy.get_IsAdmin()
at Framework.Batch.Eod.ConsumerProducerBatch.Consume(List`1 items) in D:\Framework.Batch\Eod\SampleEodBatch.cs:line 85
at Framework.Facilities.Batch.BaseBatch`1.<>c__DisplayClass26_0.<RunConsume>b__1() in D:\Framework.Facilities.Batch\BaseBatch.cs:line 289
at Framework.Facilities.Batch.BaseBatch.Handle(UnitOfWorkAttribute unitOfWork, Action T0, Action T1, Action T2) in D:\Framework.Facilities.Batch\BaseBatch.cs:line 54
--
You received this message because you are subscribed to the Google Groups "nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at https://groups.google.com/group/nhusers.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhusers+***@googlegroups.com.
To post to this group, send email to ***@googlegroups.com.
Visit this group at https://groups.google.com/group/nhusers.
For more options, visit https://groups.google.com/d/optout.
Gökhan Abatay
2018-11-29 19:00:06 UTC
Permalink
Hi Oskar Berggren,
Thank you for quick response, actually I change my perspective after posing
this message now I have the same idea with you.
I change my flow producer thread just select unique id and passes to worker
consumer threads.
Then consumer threads just selects what they need to implement their
business.
Everything works like charm.

public class ConsumerProducerBatch : BaseBatch<long>
{
[UnitOfWork]
protected override void Consume(params List<long>[] pagedItems)
{
List<EodJobRunLog> runLogs = new List<EodJobRunLog>();
foreach (var items in pagedItems)
{
var result = ISession.Query<EodJobRunLog>()
.Where(x => items.Contains(x.Guid))
.ToList();
runLogs.AddRange(result);
}

foreach (var item in runLogs)
{
if (item.MemberDefinition.IsAdmin == true)
{
item.ErrorCode = "000001";
ISession.Update(item);
}
}
}

[UnitOfWork]
protected override IQueryable<long> Produce()
{
return ISession.Query<EodJobRunLog>().Select(x=>x.Guid);
}
}
Post by Oskar Berggren
I looks to me like you are accessing a bunch of interfaces that are not
necessarily the official way to work with NHibernate. The ISession provides
the interface to reattach objects.
Personally I've always found Evict/Attach messy, to be honest.
You mention that you need very good performance. I'm not convinced that
shifting loaded entities between threads and sessions using evict/attach is
the best way to achieve that. Have you explored having multiple threads
just reading from the database themselves?
/Oskar
Post by Gökhan Abatay
I try to implement Consumer(Multiple Thread), Producer(Single Thread that
is main one) architecture;
Producer thread owns it' NH session and retrieves data and if it' fetch
enough to process(limited by parameter like 500 record) send to Consumer
thread (consumer owns another session) to process them.
While Consumer and producer sessions both active at the same time, to
process the records I need to "Session.Evict(x)" for all records.
To access oldState for logging at Post Events I need to Consumer thread
session attach the records with below code without access to second level
cache nor database.
public static T Attach<T>(this ISession session, T entity)
{
ISessionImplementor sessionImplementor = session.GetSessionImplementation();
IEntityPersister persister = sessionImplementor.GetEntityPersister(NHibernateProxyHelper.GuessClass(entity).FullName, entity);
Object[] loadedState = persister.GetPropertyValues(entity);
Object id = persister.GetIdentifier(entity);
EntityEntry entry = sessionImplementor.PersistenceContext.AddEntry(entity, Status.Loaded, loadedState, null, id, null, LockMode.None, true, persister, true, true);
return entity;
}
Everything is fine but proxy objects stores "_session" in private
variables and it's null because I evicted by retrieval session.
How to set "_session" variable in proxy classes at entity level, is there
any function to do that.
If I use reflection to get Proxy Properties I am afraid for bad
performance and it needed to be recursive.
If I can get entity owned proxy properties with recursive I can call
ILazyInitializer.SetSession?
Am I doing something wrong because I need very good performance using
parallel threads.
NHibernate.Proxy.AbstractLazyInitializer.Initialize() in C:\nhibernate-master\nhibernate-core-master\src\NHibernate\Proxy\AbstractLazyInitializer.cs:line 115
at NHibernate.Proxy.AbstractLazyInitializer.GetImplementation() in C:\nhibernate-master\nhibernate-core-master\src\NHibernate\Proxy\AbstractLazyInitializer.cs:line 191
at MemberDefinitionProxy.get_IsAdmin()
at Framework.Batch.Eod.ConsumerProducerBatch.Consume(List`1 items) in D:\Framework.Batch\Eod\SampleEodBatch.cs:line 85
at Framework.Facilities.Batch.BaseBatch`1.<>c__DisplayClass26_0.<RunConsume>b__1() in D:\Framework.Facilities.Batch\BaseBatch.cs:line 289
at Framework.Facilities.Batch.BaseBatch.Handle(UnitOfWorkAttribute unitOfWork, Action T0, Action T1, Action T2) in D:\Framework.Facilities.Batch\BaseBatch.cs:line 54
--
You received this message because you are subscribed to the Google Groups
"nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an
<javascript:>.
Visit this group at https://groups.google.com/group/nhusers.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhusers+***@googlegroups.com.
To post to this group, send email to ***@googlegroups.com.
Visit this group at https://groups.google.com/group/nhusers.
For more options, visit https://groups.google.com/d/optout.
Oskar Berggren
2018-11-30 17:19:42 UTC
Permalink
That sounds much more straight-forward an easier to understand. :)

/Oskar
Post by Gökhan Abatay
Hi Oskar Berggren,
Thank you for quick response, actually I change my perspective after
posing this message now I have the same idea with you.
I change my flow producer thread just select unique id and passes to
worker consumer threads.
Then consumer threads just selects what they need to implement their
business.
Everything works like charm.
public class ConsumerProducerBatch : BaseBatch<long>
{
[UnitOfWork]
protected override void Consume(params List<long>[] pagedItems)
{
List<EodJobRunLog> runLogs = new List<EodJobRunLog>();
foreach (var items in pagedItems)
{
var result = ISession.Query<EodJobRunLog>()
.Where(x => items.Contains(x.Guid))
.ToList();
runLogs.AddRange(result);
}
foreach (var item in runLogs)
{
if (item.MemberDefinition.IsAdmin == true)
{
item.ErrorCode = "000001";
ISession.Update(item);
}
}
}
[UnitOfWork]
protected override IQueryable<long> Produce()
{
return ISession.Query<EodJobRunLog>().Select(x=>x.Guid);
}
}
Post by Oskar Berggren
I looks to me like you are accessing a bunch of interfaces that are not
necessarily the official way to work with NHibernate. The ISession provides
the interface to reattach objects.
Personally I've always found Evict/Attach messy, to be honest.
You mention that you need very good performance. I'm not convinced that
shifting loaded entities between threads and sessions using evict/attach is
the best way to achieve that. Have you explored having multiple threads
just reading from the database themselves?
/Oskar
Post by Gökhan Abatay
I try to implement Consumer(Multiple Thread), Producer(Single Thread
that is main one) architecture;
Producer thread owns it' NH session and retrieves data and if it' fetch
enough to process(limited by parameter like 500 record) send to Consumer
thread (consumer owns another session) to process them.
While Consumer and producer sessions both active at the same time, to
process the records I need to "Session.Evict(x)" for all records.
To access oldState for logging at Post Events I need to Consumer thread
session attach the records with below code without access to second level
cache nor database.
public static T Attach<T>(this ISession session, T entity)
{
ISessionImplementor sessionImplementor = session.GetSessionImplementation();
IEntityPersister persister = sessionImplementor.GetEntityPersister(NHibernateProxyHelper.GuessClass(entity).FullName, entity);
Object[] loadedState = persister.GetPropertyValues(entity);
Object id = persister.GetIdentifier(entity);
EntityEntry entry = sessionImplementor.PersistenceContext.AddEntry(entity, Status.Loaded, loadedState, null, id, null, LockMode.None, true, persister, true, true);
return entity;
}
Everything is fine but proxy objects stores "_session" in private
variables and it's null because I evicted by retrieval session.
How to set "_session" variable in proxy classes at entity level, is
there any function to do that.
If I use reflection to get Proxy Properties I am afraid for bad
performance and it needed to be recursive.
If I can get entity owned proxy properties with recursive I can call
ILazyInitializer.SetSession?
Am I doing something wrong because I need very good performance using
parallel threads.
NHibernate.Proxy.AbstractLazyInitializer.Initialize() in C:\nhibernate-master\nhibernate-core-master\src\NHibernate\Proxy\AbstractLazyInitializer.cs:line 115
at NHibernate.Proxy.AbstractLazyInitializer.GetImplementation() in C:\nhibernate-master\nhibernate-core-master\src\NHibernate\Proxy\AbstractLazyInitializer.cs:line 191
at MemberDefinitionProxy.get_IsAdmin()
at Framework.Batch.Eod.ConsumerProducerBatch.Consume(List`1 items) in D:\Framework.Batch\Eod\SampleEodBatch.cs:line 85
at Framework.Facilities.Batch.BaseBatch`1.<>c__DisplayClass26_0.<RunConsume>b__1() in D:\Framework.Facilities.Batch\BaseBatch.cs:line 289
at Framework.Facilities.Batch.BaseBatch.Handle(UnitOfWorkAttribute unitOfWork, Action T0, Action T1, Action T2) in D:\Framework.Facilities.Batch\BaseBatch.cs:line 54
--
You received this message because you are subscribed to the Google
Groups "nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send
Visit this group at https://groups.google.com/group/nhusers.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at https://groups.google.com/group/nhusers.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhusers+***@googlegroups.com.
To post to this group, send email to ***@googlegroups.com.
Visit this group at https://groups.google.com/group/nhusers.
For more options, visit https://groups.google.com/d/optout.
Loading...