We have a simple nservicebus (v4) setup in which a web app sends various messages to a backend endpoint for processing. Everything was going smoothly until ramping up the concurrency level. Often, but not all of the time we'll get the following exception -
System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
I'm guessing this has to be an issue with the NHibernate(v3.1) Session management. Right now, we create a new session factory and session with a singleton lifecycle in each of the handlers (so each handler should have it's own session, right?). My best guess based on this exception is that the connection on the session is being used by another handler?
Can anyone shed some light? Why is this an inconsistent problem?
Found the problem. I was initializing the structuremap ObjectFactory in every handler so every new message would would overwrite what another message (on a another thread) originally initialized. This meant that all of the threads were using the session that the most recent message created. Bootstrapping in the Init() method from IWantCustomInitialization seems to have fixed the issue.
Related
I am facing an annoying problem. During my development work I modified some methods of the *DPC_EXT classes of a Gateway service in SE24. After releasing the task containing these changes I realized one of this service's entities needed some extra properties added in SEGW. I added them and saved them in a new task within the same transport request as the original. But when generating the runtime artifacts I always receive the following error:
Object components locked in different requests
I have tried un-releasing the released task using program RDDIT076 but this is no longer possible. RDDIT076 can't change task statuses anymore due to security concerns.
Is there some benign trick to resolve this issue? Or should the transport request just be imported by our SAP BASIS team and should we start with a clean slate?
Thank you in advance,
Joshua
Here is the scenario. I have a WCF service, when this service is called it passes control to an instance of another class (created via Ninject). In that class I need to do some work, specifically with Entity Framework and repositories. To cut a long story short, I have the following binding declared.
Bind<IGenericProductRepository>()
.To<GenericProductRepository>()
.WithConstructorArgument( "context", new StagingDataContext());
When I want to use this repository I have the following.
using (var genericProductRepository = IoC.Resolve<IGenericProductRepository>())
The problem is, that I only get a new instance of genericProductRepository if it's a brand new request, if the method is called multiple times in the same request I get an error stating that the context (the EF context) is already disposed, this is because it seems like I am getting the same instance back that was already disposed in the using statement. To explain it another way, using the Microsoft WCF Test Client, if I invoke it the first time, the code runs fine, if I push the invoke button again (without restarting the test client, i.e. the same request) then it throws this error about it being disposed already.
I have tried to play around with the various "scopes" that come with Ninject, but clearly I am missing something.
So my basic question is, how do I get a new repository whenever it hits that line, instead of using the same one ? Help would be greatly appreciated, I'm really trying to push for my company to adopt Ninject and drop Spring.
Look at your binding again. Even without any knowledge about Ninject you should notice that the instance of your context is created exactly once at the time the binding is defined. But what you want is have a new context on every resolve. Best it is done by not using WithConstructorArgument and let Ninject create the instance. Therefore you have to define a additional binding for the type of context. If this is not possible for some reason you have to use the lazy version of WithConstructorArgument
WithConstructorArgument("context", ctx => new StagingDataContext())
Furthermore, you might want to try The WCF extension for Ninject:
https://github.com/ninject/ninject.extensions.wcf
That way you can get rid of the ServiceLocator like usage.
I am getting the following exception when using Nhibernate and ADO.Net operations inside the transaction Scope.Eg. It was fine with Nhibernate 2.1 but now upgraded to 3.0 which throws error.
using (var scope = new TransactionScope(TransactionScopeOption.Required))
{
GetmemberId(); --> NHibernate Call
Update(); ADO Call OracleDB
}
Since this acts as ambient transaction, Nhibernate tries to dispose the transaction soon before the outer transaction completes.correct me if I am wrong, Is there any solution because help me , But When I move the Nhibernate call outside TransactionScope everything works fine. The example I have given is sample one, mines involves a more complex one, since I have keep both the calls inside TransactionScope and the error Iam getting is as following,
ERROR 13 NHibernate.Impl.AbstractSessionImpl - DTC transaction prepre
phase failed System.ObjectDisposedException: Cannot access a disposed
object. Object name: 'Transaction'. at
System.Transactions.Transaction.DependentClone(DependentCloneOption
cloneOption) at
System.Transactions.TransactionScope.SetCurrent(Transaction
newCurrent) at System.Transactions.TransactionScope.PushScope()
at System.Transactions.TransactionScope.Initialize(Transaction
transactionToUse, TimeSpan scopeTimeout, Boolean interopModeSpecified)
at System.Transactions.TransactionScope..ctor(Transaction
transactionToUse) at
NHibernate.Transaction.AdoNetWithDistributedTransactionFactory.DistributedTransactionContext.System.Transactions.IEnlistmentNotification.Prepare(PreparingEnlistment
preparingEnlistment) 2011-02-08 13:41:46,033 ERROR 13
NHibernate.Impl.AbstractSessionImpl - DTC transaction prepre phase
failed System.ObjectDisposedException: Cannot access a disposed
object. Object name: 'Transaction'. at
System.Transactions.Transaction.DependentClone(DependentCloneOption
cloneOption) at
System.Transactions.TransactionScope.SetCurrent(Transaction
newCurrent) at System.Transactions.TransactionScope.PushScope()
at System.Transactions.TransactionScope.Initialize(Transaction
transactionToUse, TimeSpan scopeTimeout, Boolean interopModeSpecified)
at System.Transactions.TransactionScope..ctor(Transaction
transactionToUse) at
NHibernate.Transaction.AdoNetWithDistributedTransactionFactory.DistributedTransactionContext.System.Transactions.IEnlistmentNotification.Prepare(PreparingEnlistment
preparingEnlistment)
Try
Configuration.SetProperty(Environment.TransactionStrategy,"NHibernate.Transaction.AdoNetTransactionFactory")
Or in nhibernate config
<property name="transaction.factory_class">
NHibernate.Transaction.AdoNetTransactionFactory
</property>
It worked for me =)
We ran into this same error, and it was caused by the way we used sessions and transactions in our Web Api with NHibernate.
We should have been using session-per-request. (This can be a web request or the execution of a NServiceBus handler.) When a request starts, you should open a session and start a transaction.
We were not doing that. In our repositories, we created a new session and transaction for every database request. This meant that rather than having a single session/transaction for a request, we had many.
The root cause of the bug for us was that we were loading an entity (domain model object) in one session, modifying it, and saving it using a different session. By the time NHibernate executed the update call, the loading session/transaction had already been committed, flushed, and closed.
Solution was to pull our session/transaction creation out of the repositories and up to the Controller layer (doable using a HttpModule for REST calls and/or with aspect oriented programming using dependency injection). This one session/transaction then lives for the lifetime of the REST call or NServiceBus handler execution and is used for all database access during that call. When that call ends, it will be committed or rolled back as appropriate.
The answer given above setting the config property simply turns off DTC and reverts to the older way of doing NHibernate transactions. That may solve the problem for you if you never have to scale up your Web Api to multiple instances, but if you do, this will cause you problems.
One of 4 production servers once in a while generates tons of error claiming:
Method RunRules is not supported on this proxy, this can happen if the method is not marked with OperationContractAttribute or if the interface type is not marked with ServiceContractAttribute.
The method "RunRules" is one of the methods in wcf [ServiceContract] interface, and it is marked as [OperationContract].
Before this error, in the same method, occasionally it would get a wrong service through castle container. After I put more logging information to nail down exact cause, it mutated into the current error.
It is a webservice the error comes out of, it tries to call into a windows service through wcf endpoint when this happens. And this only happens on one specific machine. The frequency is about once a week or 2 weeks. Once recycle of the webservice happens (3 hours), the error stops.
To me it is almost like corrupted vtable. Just wondering, how would you approach this problem? Hate to ask IT people start to re-image the machine without solid proof.
Thanks!
No simple answer for such abstract magic error, so try out logging entire call stack, especially internal Castle DLL calls, if standart exception does not contain such deep call stack information - use reflection.
// use this in loop incrementing levelIndex up to st.FrameCount
// to grab all possible callstack entries
StackTrace st = new StackTrace();
st.GetFrame(levelIndex).GetMethod().Name;
Then using utility like ILSpy disassemble Castle DLL and try out analyze which state causes concrete execution flow which ends up with exception you got.
If you able log callstack - please share so I would be able check it as well.
At first I treated them as any dependency passing them in the ctor to the class consuming the service:
var serviceConsumer = new ServiceConsumer(new MailingServiceClient())
The problem was that once an exception was thrown from the service it entered a faulted state and would not reply to any requests, so re-initialization was due.
Further more, I became familiar with the fact that wcf services may not be disposed properly on several occasions, because the dispose method of the generated proxy is broken (calls close without checking the fault state) and encountered a couple of ways to overcome that:
wrapping every call to every service.
override the default IDisposable behavior of the scvutil.exe-generated class
Since I wouldn't like the consumer code to create the service client himself for testing reasons, my questions are:
how can I maintain a working un-faulted service?
how can I still use dependency injection for testability?
Found a nice solution.
a proxy generator that replaces the VS one, and generates a wrapper around the default proxy that deals with proxy faults, timeouts, and correct disposal.
http://wcfproxygenerator.codeplex.com/
seems to be working fine for me.