3

This is all on a Salesforce Community.

I have a situation where a user is uploading a file and it's temporarily assigned to their user record. Once they submit the form and it creates a custom object record, I need to re-assign those files to the new custom object record. This is not part of a trigger but a controller behind a custom lightning component.

Here's the code that's doing the work:

List<ContentDocumentLink> oldLinks = [select Id, ContentDocumentId, LinkedEntityId, ShareType from ContentDocumentLink where LinkedEntityId=:userId and ContentDocumentId=:ids];
List<ContentDocumentLink> newLinks = new List<ContentDocumentLink>();

for (ContentDocumentLink old : oldLinks) {
    newlinks.add(new ContentDocumentLink(ContentDocumentId=old.ContentDocumentId, LinkedEntityId=wrapper.objProject.Id, ShareType=old.ShareType));
}

delete oldLinks;
insert newLinks;

The resulting error is:

System.DmlException: Delete failed. First exception on row 0 with id 06Aq0000002COEuEAO; first error: FIELD_INTEGRITY_EXCEPTION, field integrity exception: []

I've now tried to bust this down to a super basic level to just:

List<ContentDocumentLink> toDelete = [select Id from ContentDocumentLink where Id='06Aq0000002COEuEAO'];

delete toDelete;

But I receive the same error. What I can't determine is why this is an issue. That is the only link that exists for that document.

Anyone have any ideas?

3 Answers 3

6

enter image description here

As you can see above, when you upload a file to any record like account New Test Account, it will always create 2 links - 1st for the user TestUser with share type I (which cannot be deleted) and 2nd for the record itself with share type V. Henceforth when you share the file with new objects, it will create new links of share type V. You cannot delete the primary link which is created for the owner user of file. This is standard file upload flow.

So, in your case you can just create new link and you should not try to delete the link for user.

2
  • 1
    Thank you so much. That was the problem. I searched high and low and never saw anything about not being able to delete records with sharetype I. I'm sure it's buried somewhere, but this piece of information entirely fixed this problem for me. Now I just create the share type of V and move on with it. Again, thanks.
    – Tony Evans
    Commented Aug 22, 2019 at 2:58
  • @salesforce-sas I noticed that SF deletes the "I" DocLink record that points to the user and created a new "I" DocLink record that points to a Library if I add a document to a Library after uploading without any associations. It seems like I can't delete the Library DocLink even after creating a new "I" DocLink that points to my user. Is this expected behavior?
    – fdc
    Commented Mar 26, 2021 at 16:58
1

When a file is uploaded by User U on a record R

  • A ContentVersion is created
  • A parent ContentDocument is created to the ContentVersion

And, with the ContentDocument serving as one end of the junction object ContentDocumentLink; two ContentDocumentLinks are created

  • LinkedEntityId = U's Id and ShareType = I
  • LinkedEntityId = record R's Id and ShareType = V

If you want to effectively change the ContentDocumentLink from User U to User V

  • Do not attempt to delete the ContentDocumentLink associated with U- you get either

    • FieldIntegrityException, even if using a running user with ModifyAllData permissions.
    • UNKNOWN_EXCEPTION (seen in Apex debug logs, even if using a running user with ModifyAllData permissions.)

Instead, simply change the ContentDocument.OwnerId to user V's Id. Salesforce will implicitly:

  • delete the ContentDocumentLink between User U and the ContentDocument and
  • add a new ContentDocumentLink with LinkedEntityId = user V's Id and ShareType = I

In table form, this is what happens

Initial file upload by User U

ContentDocument

Id                   OwnerId
------------------   --------------
069XXXX              user U's Id

ContentDocumentLinks

ContentDocumentId    LinkedEntityId    ShareType
------------------   --------------    ---------
069XXXX              user U's Id          I
069XXXX              record R's Id        V

  

Change (DML) the ContentDocument.OwnerId to user V

ContentDocument

Id                   OwnerId
------------------   --------------
069XXXX              user V's Id

ContentDocumentLinks - happens automatically, no explicit DML required

ContentDocumentId    LinkedEntityId    ShareType
------------------   --------------    ---------
069XXXX              user V's Id           I
069XXXX              record R's Id         V
0

Deleting old links will leave you with an orphaned document, which might be a problem in a Community. There's nothing wrong with a document having multiple links, so you may want to insert newlinks and then delete oldlinks. And if you have problems with that, you might try moving the deletion into a future context. I don't know if that would help, but it's what I would try.

So to restate myself: First insert newlinks so you get the document properly associated, and then delete the old links.

1
  • 1
    I agree that it doesn't hurt, but I'm always pretty keen on not creating more than I need so I was trying to delete the old ones. Also, I tried to insert them first, but was getting an error there too that it already existed. My root issue was what @salesforce-sas mentioned above, i was trying to create a new record with sharing type I because that's what I was seeing. I should have just tried to create a record with a different sharing type, but I think I was just stuck and couldn't get there. Thanks for the help.
    – Tony Evans
    Commented Aug 22, 2019 at 3:03

You must log in to answer this question.

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