Tasks and EF thread safety in nopCommerce 1.9

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
11 anni tempo fa
Hi,

I've added a scheduled task to nopCommerce 1.9 and I got the following error:

System.Data.EntityException: An error occurred while starting a transaction on the provider connection. See the inner exception for details. ---> System.Data.SqlClient.SqlException: New transaction is not allowed because there are other threads running in the session.


To implement my data layer, I added new entities to the nopCommerce model, and wrote a service and entity following the same pattern as nop itself. My NopObjectContent is retrieved from Unity using the IoC.Resolve method.

On reading up on this, it appears that this occurs because I am using the same NopObjectContext instance on two threads.

I'm going to recode to ensure that I instantiate a different context for my Task, but 'long story short' my question is:

How does NopCommerce 1.9 get around the fact that it's own Scheduled Tasks could crash and burn in the same manner?

I just can't find how it protects against this eventuality, is it written in such a way that we hope that it never clashes, based on rarity of occurance etc?

Thanks for your help.

Mark Rabjohn
Integrated Arts Ltd
11 anni tempo fa
After I posted, I thought of a different way to search the forum. It appears that someone else is having a similar problem in NopCommerce 2.46. It certainly looks as though the Scheduled tasks can interfere with activity on the website thread in rare cases e.g. if someone inserts a customer session record whilst the delete old customer sessions task is running.

There is a very low window of opportunity for this to happen, but it can happen.

Does anybody have any comment on this?


Mark
11 anni tempo fa
mrabjohn wrote:
After I posted, I thought of a different way to search the forum. It appears that someone else is having a similar problem in NopCommerce 2.46. It certainly looks as though the Scheduled tasks can interfere with activity on the website thread in rare cases e.g. if someone inserts a customer session record whilst the delete old customer sessions task is running.

There is a very low window of opportunity for this to happen, but it can happen.

Does anybody have any comment on this?


Mark



Hi... I have the same error.If have you got any solution, then please share here.
Please help me.

Thanks.
11 anni tempo fa
Hi Herin,

I didn't find a "simple" solution, but I did find a solution for 1.9 - I guess that similar methods can be used in 2.6.

You have to be really careful to make sure that access to resources are thread safe - I only really bothered with the database connection.

To get my database connection, I used a duplicate of the NopObjectContext dependency code:


        private NopObjectContext _context = null;

if (InstallerHelper.ConnectionStringIsSet())
            {
                var ecsbuilder = new EntityConnectionStringBuilder();
                ecsbuilder.Provider = "System.Data.SqlClient";
                ecsbuilder.ProviderConnectionString = NopConfig.ConnectionString;
                ecsbuilder.Metadata = @"res://*/Data.NopModel.csdl|res://*/Data.NopModel.ssdl|res://*/Data.NopModel.msl";
                string connectionString = ecsbuilder.ToString();
                _context = new NopSolutions.NopCommerce.BusinessLogic.Data.NopObjectContext(connectionString);
            } else {
                return;
            }


That gives me a NopObjectContext that is not the same instance used by Nop. In effect, it's a second database connection with it's own ObjectSets and Entities.


If you want to use Nop business objects, you'd normally get them from IoC.Resolve, but if you do that in your thread, you'd get a single managed instance that wraps the shared NopObjectContext, which is not what you want.

Instead, take note of the fact that each business object can be passed a NopObjectContext in it's constructor:

       
     var sm = new SettingManager(_context);
     var customerService = new CustomerService(_context);


The instances returned can be used in the context of your own thread and database connection, yay!


I don't have any code available for doing this on the 2.X MVC sites - I haven't built any batch modules for it yet. Perhaps someone else can supply an equivalent example.


P.S. This won't remain thread safe if a called method uses IoC.Resolve internally - Nop just isn't ThreadSafe, hopefully somebody will make the core stuff threadsafe against itself, and expose a model for plugin writers to follow.


Hope that this helps:

Mark Rabjohn
Integrated Arts Ltd www.ia.uk.com
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.