-2
public class DocumentFileDeletionScheduler implements Schedulable {
    
    public void execute(SchedulableContext SC) {
        deleteOldFiles();
    }
    
    public void deleteOldFiles() {
        List<Document__c> documentsToDelete = new List<Document__c>();
        List<ContentDocumentLink> linksToDelete = new List<ContentDocumentLink>();
        List<ContentVersion> versionsToDelete = new List<ContentVersion>();
        
        for (Document__c doc : [SELECT Id FROM Document__c WHERE Nscale_Upload_Status__c = 'Success']) {
            // Get the ContentDocumentLink records for this document
            List<ContentDocumentLink> links = [SELECT Id, ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = :doc.Id];
            
            // Get the ContentDocument records for the ContentDocumentLinks
            List<ContentDocument> documents = [SELECT Id, CreatedDate FROM ContentDocument WHERE Id IN :links AND CreatedDate < LAST_N_DAYS:15];
            
            
            // Get the ContentVersion records for the ContentDocuments
            for (ContentDocument document : documents) {
                List<ContentVersion> versions = [SELECT Id FROM ContentVersion WHERE ContentDocumentId = :document.Id];
                versionsToDelete.addAll(versions);
            }
            
            linksToDelete.addAll(links);
            documentsToDelete.add(doc);
        }
        
        if (!versionsToDelete.isEmpty()) {
            delete versionsToDelete;
            System.debug('Deleted ' + versionsToDelete.size() + ' old file versions.');
        }
        
        if (!linksToDelete.isEmpty()) {
            delete linksToDelete;
            System.debug('Deleted ' + linksToDelete.size() + ' old file links.');
        }
        
        if (!documentsToDelete.isEmpty()) {
            delete documentsToDelete;
            System.debug('Deleted ' + documentsToDelete.size() + ' documents.');
        }
    }
}

Here is my code. But I don't really how to solve them. Can you guys help me with this?

So the first error is this: Invalid bind expression type of ContentDocumentLink for Id field of SObject ContentDocument The second: DML operation Delete not allowed on List I know now there is no delete for contentversion

1 Answer 1

1

EDIT : explanation of the dataModel.

Documents in salesforce are special. The actual document (binary) is located in a file server that is not the salesforce database.

in order to map this, salesforce has a ContentDocument, a ContentVersion and a ContentDocument link. ContentDocument being a parent (master-Detail) of both contentDocumentLink AND ContentVersion

The contentVersion is actually a "pointer" to the actual file in the fileServer of salesforce

Thus when you delete a ContentDocument all the contentVersion are deleted along the way as this is a master Detail relationship. Salesforce then applies the changes on the fileServer of Salesforce in an async way but you don't need to worry about it.

Also ContentDocumentLink are a junction object (double master detail). Thus deleting any of your linkedEntity or the contentDocument will automatically delete the contentDocumentLink. Indeed, deleting a parent in this context deletes the child and thus the contentDocument link.

-> easy win on your side

The binding error comes from the fact that you have a List<ContentDocument> and actually using it as if it was a List<Id>

// Get the ContentDocumentLink records for this document
            List<ContentDocumentLink> links = [SELECT Id, ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = :doc.Id];

//---> HERE you have a list of ContentDocumentLinks, not a list of IDs
            
            // Get the ContentDocument records for the ContentDocumentLinks
            List<ContentDocument> documents = [SELECT Id, CreatedDate FROM ContentDocument WHERE Id IN :links AND CreatedDate < LAST_N_DAYS:15];
//--> Here you use links (thus List<ContentDocumentLink>)
            

to fix it you'll need to extract the ContentDocumentId from your list. thus something like :

// Get the ContentDocumentLink records for this document
            List<ContentDocumentLink> links = [SELECT Id, ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = :doc.Id];

Set<Id> cdlinkIds = new Set<Id>();
//Using a set as you may have twice the same Id, this will hadle duplicate automatically
for(ContentDocumentLink cdl : links )
{
  cdlinkIds.add(cdl.ContentDocumentId);
}

Finally regarding the delete error (while i will not dig into the root cause) applying what i explained above, deleting the ContentDocument, as it is a master detail relationship, this will delete the contentVersions automatically.

hence in your code you can perform a single delete operation instead of 3.

For completeness i will add that you have an issue in your code that needs to be addressed : you are making a queries inside loops hence you may hit governor limits and this needs to be looked into. You should consider bulkify your code.

2
  • from here : if (!versionsToDelete.isEmpty()) { delete versionsToDelete; System.debug('Deleted ' + versionsToDelete.size() + ' old file versions.'); }
    – Csabikaaaa
    Commented Apr 19, 2023 at 10:26
  • This is also because of the relationship in the datamodel. i'll edit the answer ;-)
    – Philippe
    Commented Apr 19, 2023 at 11:32

Not the answer you're looking for? Browse other questions tagged .