deletion possible?

Hi

Is there a possibility to ask a record if it can be deleted (like controller.canRecordBeDeleted())?

My Servoy relations would prevent a record to be deleted if it is still “in use” (‘allow parent delete when having related records’ is unchecked). So, when the user clicks the delete button, this is what I want to do:

  • check if deletion would be possible
  • if yes: let the user confirm the deletion and delete the record
  • if no: inform the user that the record is still in use

What I do so far:

  • let the user confirm the deletion
  • if he or she confirms: var ok = controller.deleteRecord()
  • if not ok: inform the user that the record is still in use

This way, the user first confirms the deletion. Later I might inform him ‘Sorry, deletion is not possible’.

Thanks for any help and regards

I’m not able to answer your question, but this is an excellent suggestion for handling ‘allow parent delete when having related records’!

Hi Birgit,

you could create a global function where you loop through all relations where the primary table is the table you want to delete from.
Using the solution model, you can also check what the checkbox-settings are.

For each relation where ‘allow parent delete when having related records’ is unchecked, you should check if there are any related records.
If so, the result should return false, otherwise if you did not found any issues, return true.

Be carefull this is gonna be an expensive operation as you might need to check several relations. They all need to query your database…
I think this is also the reason there’s no standard function for this…

If possible I’ll crop a code-snippet later on.

Thank you for the idea of looping over all relations. I thought about this but had no idea how to start. A code snippet would be appreciated. I can imagine it is expensive. Espacially since it will be a recursive operation.

I thought, inside Servoy there must already be a similar implementation: deleteRecord() returns false if Servoy relations prevent the deletion. Since we do not have these constraints in the database, I imagine the check is done in Servoy. Do you know how this is done?

Let’s say the table your user wants to delete from is A, and there are 3 relations with A as their source where you have unchecked ‘allow parent delete…’ - they are called A_to_X, A_to_Y and A_to_Z.

if (utils.hasRecords(A_to_X)  || utils.hasRecords(A_to_Y) || utils.hasRecords(A_to_Z))
    // tell user he can't delete
else
   controller.deleteRecord()

Thank you for the code example.

Two things:

  1. I’d prefer to iterate over the list of all relations. And ask each relation for its attribute ‘allow parent delete…’ If I don’t, I’d have to keep both in sync: The check boxes in the relation definitions and the list of relations in the if clause.
  2. There will be more relations to check, one level deeper: If none of the relations of the first level prevents the deletion, I’ll have to check the relations defined in the next level. But only for those who delete recursively. This is why I’d like a generic method to recursively iterate over the list of relations. An if clause would become huge. Don’t you think so?

Do you know how controller.deleteReceord() is implemented?

Kind regards

Personally, I just rely on controller.deleteRecord() to figure it out for me…

if(! // confirmation dialog of your choice //)
  return;

if(!controller.deleteRecord())
   // unable to delete dialog of your choice //;

Yes, you ask for a confirmation before knowing if they can delete in this instance, but it’s less expensive and easier to manage.

If I have more complex business logic that determines if it’s OK to delete a record, I put that in a “can_delete” unstored calc on the data provider that checks relations, or order status, or other things like that…then I can do:

if( can_delete != 1 )
   // sorry, charlie! //

That makes it cleaner to manage, also, because you can also check that “can_delete” from any forms that use the record, or even in the table events.

g.

Hi Birgit,

as promised, a codesnippet:

function canRecordBeDeleted()
{
	var $table		= arguments[0];
	var $server		= arguments[1];
	var $currentRec = arguments[2];
	var $relations	= new Array();
	
	var $jsRelations = solutionModel.getRelations($server, $table);
	
	for (var i = 0; i < $jsRelations.length; i++)
	{
		if(!$jsRelations[i].allowParentDeleteWhenHavingRelatedRecords)
		{
			$relations[$relations.length] = $jsRelations[i].name;
		}
	}
	
	for (var i = 0; i < $relations.length; i++)
	{
		if(databaseManager.hasRecords($currentRec[$relations[i]])) return false;
	}
	
	return true;
}

This code is only 1 level deep and should be recursive to check all levels.
Actually this means that you could end up checking hundreds of records to check for related records…

I think this method can prevent displaying some ‘unneeded’ dialogs for the users, but if records on a 4th level prevent deletion on the 1st level, then just try to delete and display a message on fail.

Hi Greg

Thank you for your reply. I agree, it might be a lot easier just to base on the return value of the delete operation. And so bring up two dialogs in the worst case.

About the business logic: I try to use the table events (onRecordDelete and also onRecordInsert) to check the business logic, the business integrity. What relations or the database can check, I let them check. What they can guarantee is data integrity.

Kind regards

Hi Marc

Thank you for the code! Now I see how this could be done. I agree, it is probably too expensive to check. And yes, it might be better to use the return value of the delete operation (I still ask myself how the return value is calculated inside Servoy :?:

I wonder, ‘how’ expensive it would be. Maybe I give it a try. In the example I’m implementing right now, I would have to go three levels deep, I think.

Since our datamodel is quite big (>100 entities, >300 relationships), it is important to store all information only once. Otherwise I could never be able to keep it in sync. I hope the Servoy relations are the right place to store the information.

An other idea (my husband - mechanical engineer - just came up with): start transaction; var result = deleteRecord(); rollback transaction. Now, result contains the value I was looking for :-)

I’d appreciate a Servoy documentation on how to insert/delete records. An all over example, explaining the whole operation. Maybe even with or without auto save on. And maybe with or without constraints in the database (I know now, we are a minority using logic in the database). And maybe with or without dialogs for creating records. Examples like: ‘onRecordInsert is an event which will be triggered when a record is about to be inserted.’ are not very useful to get an idea about the whole process.

Regards