Accessing IOrderStore from different thread context

Discussions related to SoftPro Select Server development.

Moderator: Phil Barton

Post Reply
aowolabi
Posts: 2
Joined: Thu Sep 12, 2019 7:07 pm

Accessing IOrderStore from different thread context

Post by aowolabi » Tue Sep 17, 2019 12:58 pm

I have a Package that listens on an event that is fired on a different thread. When I attempt to query the order store from a Package Event Handler (setup in the Initialize() method) I am met with the following NHibernate.ADOException:

Code: Select all

NHibernate.ADOException
  HResult=0x80131600
  Message=While preparing SELECT 
  [truncated order fields]
  FROM pf.OrderInfoView this_ an error occurred
  Source=NHibernate
  StackTrace:
   at NHibernate.AdoNet.AbstractBatcher.Prepare(IDbCommand cmd)
   at NHibernate.AdoNet.AbstractBatcher.ExecuteReader(IDbCommand cmd)
   at NHibernate.Loader.Loader.GetResultSet(IDbCommand st, Boolean autoDiscoverTypes, Boolean callable, RowSelection selection, ISessionImplementor session)
   at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
   at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
   at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)
   at NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters)
   at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes)
   at NHibernate.Loader.Criteria.CriteriaLoader.List(ISessionImplementor session)
   at NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results)
   at NHibernate.Impl.CriteriaImpl.List(IList results)
   at NHibernate.Impl.CriteriaImpl.List[T]()
   at Castle.Proxies.Invocations.IDataContext_Query_1.InvokeMethodOnTarget()
   at SoftPro.PersistenceModel.DeadlockDetectionAspect.SoftPro.ServerModel.Aspects.IAspect.Process(Action method)
   at SoftPro.PersistenceModel.UniqueConstraintViolationAspect.SoftPro.ServerModel.Aspects.IAspect.Process(Action method)
   at SoftPro.PersistenceModel.StaleObjectStateExceptionAspect.SoftPro.ServerModel.Aspects.IAspect.Process(Action method)
   at Castle.Proxies.IOrdersDataContextProxy.Query[T](Criteria criteria)
   at SoftPro.OrderTracking.Server.Orders.OrderStore.QueryOrders(OrdersCriteria criteria)
   at SoftPro.ClientModel.Linq.CriteriaQueryProvider`2.Execute(Expression expression, Boolean enumerable)
   at SoftPro.ClientModel.Linq.CriteriaQueryProvider`2.Execute[TResult](Expression expression)
   [truncated]

Inner Exception 1:
InvalidOperationException: The current thread is not properly configured for execution. Ensure that an appropriate impersontation context has been established. This is most commonly accomplished using the RuntimeContext::Impersonate() method.
The Event handler looks like this:

Code: Select all

private IOrder FindOrder(string orderNumber)
{
    IOrderStore os = GetService<IOrderStore>();
    if (os == default) return default;
    var order = os.Orders.FirstOrDefault(o => o.Number.ToLower() == orderNumber.ToLower());
    if (order == default(IOrderInfo)) return default;
    return os.OpenOrder(order, OrderEditMode.PromotableRead);
}

private void EventSource_UpdateRecieved(object sender, EventArgs<Data> e)
{
    var o = FindOrder(e.Data.Number);
    if (o == default) return;
    [truncated]
}
It is registered in the Initialize method of the package like this:

Code: Select all

partial class MyPackage : Package
{
    public EventSource Source { get; private set; } = new EventSource();

    // This method is called when the package is loaded by the server.
    protected override void OnInitialize()
    {
        EventSource.UpdateRecieved += EventSource_UpdateRecieved;
    }
}
```

BobRichards
Posts: 1009
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: Accessing IOrderStore from different thread context

Post by BobRichards » Tue Sep 17, 2019 4:15 pm

When your code accesses the server, you should wrap all your code in an Impersonate block. This will insure that your user information (such as profile, security context, etc.) are available as needed. Try adding it like below.

Code: Select all

private void EventSource_UpdateRecieved(object sender, EventArgs<Data> e)
{
    using (RuntimeContext.Impersonate())
    {
        var o = FindOrder(e.Data.Number);        
        ...
    }
}
Bob Richards, Software Developer, SoftPro

aowolabi
Posts: 2
Joined: Thu Sep 12, 2019 7:07 pm

Re: Accessing IOrderStore from different thread context

Post by aowolabi » Tue Sep 17, 2019 9:10 pm

Thanks! Worked like a charm!

Post Reply