Issues loading data into orchard using multiple threads.

Topics: Administration, Core, General, Troubleshooting
Dec 11, 2013 at 4:27 PM
Hi there,

In the application we are building we will be migrating data from an existing non orchard application into a solution we built on top of orchard. In order to facilitate this data conversion (and to allow 3rd parties to upload their own data into our orchard solution) we built a few REST based web services for inserting / updating / deleting / accessing information in our database.

We built a simple console application to load agent profile information to test out the data conversion and I am running into errors.

If I call the web service that migrates an agent profile into orchard using a single thread it works without an issue. The problem is that it is only loading 3 agent profiles a second which is pretty slow as we will have ten's of thousands of profiles (and this is just a tiny fraction of the data that will need to be migrated to the new orchard solution).

In order to speed this up I made the console application call the web service we built using a Parallel.ForEach statement (which makes it multithreaded). However then I run into this error caused by NHibernate.

Batch update returned unexpected row count from update; actual row count: 0 expected 1

I was able to track down exactly which line is causing it to blow up.

contentItem = _contentManager.Create(profileTypeDictionaryEntry.ContentTypeName, VersionOptions.Published);

If I change it to

contentItem = _contentManager.Create(profileTypeDictionaryEntry.ContentTypeName, VersionOptions.AllVersions);

Then it seems to work without an issue.

Is there something special about creating ContentItem's that have to be versioned and published in multiple threads that is causing an issue with Orchard?

I tried running SQL Profile to maybe get some sort of idea why it might be failing. To me it looked like when a content item is created a new row is created with initial empty information in the Orchard_Framework_ContentItemRecord record, it's ID is returned using SCOPE_IDENTITY() and then the row is updated using the SCOPE_IDENTITY() value. Could NHibernate be getting these SCOPE_IDENTITY() values mixed up perhaps?

Any help would be appreciated,

Dustin
Dec 11, 2013 at 5:13 PM
Edited Dec 11, 2013 at 5:14 PM
Here is the stack trace I am getting as well when the NHibernate error occurs if that is helpful.
Batch update returned unexpected row count from update; actual row count: 0; expected: 2
   at NHibernate.AdoNet.Expectations.VerifyOutcomeBatched(Int32 expectedRowCount, Int32 rowCount) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\AdoNet\Expectations.cs:line 106
   at NHibernate.AdoNet.SqlClientBatchingBatcher.DoExecuteBatch(IDbCommand ps) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\AdoNet\SqlClientBatchingBatcher.cs:line 94
   at NHibernate.AdoNet.AbstractBatcher.ExecuteBatchWithTiming(IDbCommand ps) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\AdoNet\AbstractBatcher.cs:line 412
   at NHibernate.AdoNet.AbstractBatcher.ExecuteBatch() in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\AdoNet\AbstractBatcher.cs:line 397
   at NHibernate.AdoNet.AbstractBatcher.OnPreparedCommand() in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\AdoNet\AbstractBatcher.cs:line 155
   at NHibernate.AdoNet.AbstractBatcher.PrepareCommand(CommandType type, SqlString sql, SqlType[] parameterTypes) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\AdoNet\AbstractBatcher.cs:line 142
   at NHibernate.AdoNet.AbstractBatcher.PrepareBatchCommand(CommandType type, SqlString sql, SqlType[] parameterTypes) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\AdoNet\AbstractBatcher.cs:line 132
   at NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:line 2735
   at NHibernate.Persister.Entity.AbstractEntityPersister.UpdateOrInsert(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:line 2702
   at NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Int32[] dirtyFields, Boolean hasDirtyCollection, Object[] oldFields, Object oldVersion, Object obj, Object rowId, ISessionImplementor session) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:line 3010
   at NHibernate.Action.EntityUpdateAction.Execute() in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Action\EntityUpdateAction.cs:line 79
   at NHibernate.Engine.ActionQueue.Execute(IExecutable executable) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Engine\ActionQueue.cs:line 136
   at NHibernate.Engine.ActionQueue.ExecuteActions(IList list) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Engine\ActionQueue.cs:line 126
   at NHibernate.Engine.ActionQueue.ExecuteActions() in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Engine\ActionQueue.cs:line 170
   at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:line 249
   at NHibernate.Event.Default.DefaultAutoFlushEventListener.OnAutoFlush(AutoFlushEvent event) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Event\Default\DefaultAutoFlushEventListener.cs:line 37
   at NHibernate.Impl.SessionImpl.AutoFlushIfRequired(ISet`1 querySpaces) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 1182
   at NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 1959
   at NHibernate.Impl.CriteriaImpl.List(IList results) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Impl\CriteriaImpl.cs:line 265
   at NHibernate.Impl.CriteriaImpl.List[T]() in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Impl\CriteriaImpl.cs:line 276
   at Orchard.ContentManagement.DefaultContentQuery.Slice(Int32 skip, Int32 count) in c:\TFS\Conductor\1.7.2\src\Orchard\ContentManagement\DefaultContentQuery.cs:line 162
   at Orchard.ContentManagement.DefaultContentQuery.ContentQuery`1.Orchard.ContentManagement.IContentQuery<T>.List() in c:\TFS\Conductor\1.7.2\src\Orchard\ContentManagement\DefaultContentQuery.cs:line 212
   at Conductor.Profile.Services.ProfileService.SaveProfileFields(ProfileViewModel profileData) in c:\TFS\Conductor\1.7.2\src\Orchard.Web\Modules\Conductor.Profile\Services\ProfileService.cs:line 1142
   at Conductor.Profile.Services.ProfileService.SaveUserProfileData(ProfileViewModel profileData) in c:\TFS\Conductor\1.7.2\src\Orchard.Web\Modules\Conductor.Profile\Services\ProfileService.cs:line 1103
   at Conductor.ProfileService.Controllers.ProfileController.Post(ProfileDEO profile) in c:\TFS\Conductor\1.7.2\src\Orchard.Web\Modules\Conductor.ProfileService\Controllers\ProfileController.cs:line 170