This project is read-only.


Topics: Core
Oct 7, 2013 at 8:11 PM

when implementing OnRemoving events of two related parts, when deleting one will trigger deletion of the other (deleting owner of a blog will trigger deletion the blog which will trigger deletion of blog posts in the blog) I faced an issue. Although a green notification said the content is deleted, it wasn't and there was an error log that reads:

2013-10-07 19:46:55,143 [23] NHibernate.Event.Default.AbstractFlushingEventListener - Could not synchronize database state with session
NHibernate.Exceptions.GenericADOException: could not execute batch command.[SQL: SQL not available] ---> System.Data.SqlClient.SqlException: The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 11 ("@p8"): The supplied value is not a valid instance of data type float. Check the source data for invalid values. An example of an invalid value is data of numeric type with scale greater than precision.

When debugging I realized the problem is that: second handler updates the content item removed in the first (which is a valid scenario in my case, like deleting a blog post before deleting the blog) . Although I get the record with ContentManager.Get with no version option, which is supposed to return only Published version, or nothing since the content item is deleted, the resulting content item is not published and trying to set properties of this item caused the exception.

To make it work I checked if content item is really published:
var owner= _contentManager.Get<MyPart>(part.ContentItem.As<CommonPart>().Record.OwnerId);
if (owner != null && owner.IsPublished()) // deleted?
// stuff here
DefaultContentManagerSession is the reason. As far as I understand, it works as a cache to store content items during a session of content manager. It stores two dictinaries, one for every version fetched and one for only published versions. The thing is it doesn't remove anything in case a published item is unpublished or removed, it only clears everything when the session is cleared. So if Get is called for an item which is previously deleted in the same session, it returns the item without checking if its published.

The fix would be to do the check in DefaultContentManagerSession
        public bool RecallContentRecordId(int id, out ContentItem item) {
            if (_publishedItemsByContentRecordId.TryGetValue(id, out item))
                if (item.IsPublished())
                    return true;

            item = null;
            return false;
or in DefaultContentManager.Get where the method above is called.