Removing entity does not update attribute list

Vote:
 

Problem description:

I´m having two custom entities, EntityA and EntityB. EntityA has an attribute of type EntityB. I use the attribute to store a List of EntityB objects (List<EntityB>). All works fine when adding and removing entities to the list. (See this thread for info on how)

My problem occurs when I remove an object of type EntityB from the system. The communitysystem removes all references to that entity from other entities (using FrameworkFactoryBase.RemoveEntity()), but since EntityA has an attribute that is a List of EntityB, the removed entity is still referenced in the list.

Is there a way of getting this to work?

#32785
Sep 17, 2009 14:28
Vote:
 

The immediate workaround would have to be to write a bit of defensive code with regard to the entries in such lists, handling the case that there might be a stale entry.

However that should not really happen so I've added this as a bug (#28877), so that we will look into fixing this in an upcoming version.

 

There are two sides to the problem, one is a caching issue, the other is updating the database to reflect that the referenced entity has been removed.

 

The database side of the problem can be solved (which will make sure the problem is resolved over time) by adding this to spEPiServerCommonRemoveObjectReferences (no guarantees that this code snippet will be part of the final solution to the bug):


        -- Remove any attribute values that reference the removed entities
DELETE tblEPiServerCommonAttributeValueInteger
FROM tblEPiServerCommonAttribute
INNER JOIN tblEPiServerCommonObjectType ON tblEPiServerCommonAttribute.strDataType = tblEPiServerCommonObjectType.strName
INNER JOIN tblEPiServerCommonAttributeValueInteger ON tblEPiServerCommonAttribute.intID = tblEPiServerCommonAttributeValueInteger.intAttributeID
WHERE tblEPiServerCommonObjectType.intID = @intObjectTypeID AND tblEPiServerCommonAttributeValueInteger.intValue IN (SELECT ObjectID FROM OPENXML (@intXmlDocHandle, ''/Root/Obj'', 1) WITH (ObjectID int))
#32886
Sep 22, 2009 17:34
Vote:
 

Just want to say that I added the code snippet and it broke the query.

So if you are not experiencing the problemsdescribed above, check that your queries work after implementing the fix.

I'm not a Comunity expert so I leave you the task to explore the error if you want :)

 

This is the stacktrace

Exception message: Could not remove connected information from entity with id 13.
Exception message: Unable to remove entity id 13
Stack trace:
at EPiServer.Common.Data.FrameworkFactoryBase.<>c__DisplayClass3.b__0()
at EPiServer.Common.Data.DatabaseHandler.RunInTransaction(TransactionCode transactionCode)
at EPiServer.Common.Data.FrameworkFactoryBase.RemoveObjectReferences(IEntity entity)
at EPiServer.Common.Data.FrameworkFactoryBase.RemoveEntity(IFrameworkEntity entity)

Exception message: Could not find prepared statement with handle 1.
The statement has been terminated.
Stack trace:
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at EPiServer.Common.Data.DatabaseHandler.ExecuteNonQuery(Boolean inTransaction, String sp, CommandType commandType, Object[] args)
at EPiServer.Common.Data.DatabaseHandler.ExecuteNonQuery(String sp, Object[] args)
at EPiServer.Common.Data.FrameworkFactoryBase.<>c__DisplayClass3.b__0()

 

#32913
Sep 24, 2009 10:47
Vote:
 

Sorry, I should probably have been more clear on where you can add the SQL snippet.

It has to be put somewhere in the scope of where @intXmlDocHandle is set to the prepared XML document. That is, somewhere between where it's prepared ("EXEC sp_xml_preparedocument @intXmlDocHandle OUTPUT, @strObjectXml") and where it's removed ("EXEC sp_xml_removedocument @intXmlDocHandle").

 

If we just put the snippet at the end, the very end of the sproc would look like this:

 

         -- Remove any attribute values that reference the removed entities
DELETE tblEPiServerCommonAttributeValueInteger
FROM tblEPiServerCommonAttribute
INNER JOIN tblEPiServerCommonObjectType ON tblEPiServerCommonAttribute.strDataType = tblEPiServerCommonObjectType.strName
INNER JOIN tblEPiServerCommonAttributeValueInteger ON tblEPiServerCommonAttribute.intID = tblEPiServerCommonAttributeValueInteger.intAttributeID
WHERE tblEPiServerCommonObjectType.intID = @intObjectTypeID AND tblEPiServerCommonAttributeValueInteger.intValue IN (SELECT ObjectID FROM OPENXML (@intXmlDocHandle, ''/Root/Obj'', 1) WITH (ObjectID int))

EXEC sp_xml_removedocument @intXmlDocHandle
END
END

 

#32917
Sep 24, 2009 11:49
This thread is locked and should be used for reference only. Please use the Legacy add-ons forum to open new discussions.