0

We recently upgraded from SharePoint 2013 to 2016 and one of the things we did was upgraded our Upgrade the User Profile service application using the method documented.

However after we went live, we now notice that a user's manager isn't properly updating from Active Directory whenever there were changes.

We've tried deleting and recreating the synchronization connection and we've verified the user and their manager has the same distinguished name and guid in Active Directory as are in the SharePoint profile database. The OUs are selected that these users are within for the connection and we've verified that the service account has the proper Replication Directory Changes access for the OUs being synchronized.

Looking at the ULS logs we found these errors for most all users synchronizing.

Violation of PRIMARY KEY constraint 'PK_DNLookup'. Cannot insert duplicate key in object 'upa.DNLookup'.

This has lead us down the path of other blog posts with PowerShell commands to list all of the profiles that aren't being imported

$upa = Get-spserviceapplication | ? {$_.typename -match "profile"}
Set-SPProfileServiceApplication $upa -GetNonImportedObjects $true | out-file c:\temp\NonImportedProfiles.txt

This lists nearly all accounts that we expect to import and update.

How do we get these profiles to properly synchronize and update the manager property?

0

After a lot of trial and error we found an unexpected method to fix profile synchronization without deleting the databases and starting over. I'm documenting this in case it helps others or we need to refer to it again.

For the manager property to update from a synchronization, both the profile being updated AND the manager profile must be considered as an imported profile. One this is resolved your profiles will stay up to date.

Make certain to do any of this in a test environment and backups in production, etc.

First ensure you disable the MySite Cleanup timer job to prevent actual deletion of any profiles or MySites.

Now you must mark all of the non-imported profiles for deletion with this PowerShell command

$upa = Get-spserviceapplication | ? {$_.typename -match "profile"}
Set-SPProfileServiceApplication $upa -PurgeNonImportedObjects $true

This won't do anything by itself and you must run a full crawl of your profiles. After the full crawl completes, all non-imported profiles will be marked for deletion.

You can confirm this by running a query on a backup of your SharePoint profile database to show all profiles marked for deletion.

select NTName, PreferredName, LastUpdate, LastUserUpdate, bDeleted
from upa.UserProfile_Full
where bDeleted = 1

Now run another full crawl of your profiles and when that finishes, your profiles should now be properly imported and no longer marked for deletion.

You should verify this by querying a backup of your SharePoint profile database before you enable the MySite Cleanup timer job again.

Additionally you should rerun this PowerShell command to confirm the accounts are now imported.

$upa = Get-spserviceapplication | ? {$_.typename -match "profile"}
Set-SPProfileServiceApplication $upa -GetNonImportedObjects $true | out-file c:\temp\NonImportedProfiles.txt

Now after this, you may have some references to managers in your profiles that will still prevent the Manager field from updating completely. To resolve this you can run the PowerShell script below to clear out any manager values and then do another full crawl. To run this script you will need to have Full Control under the Permissions section of the UPSA under Manage service applications.

You can run this script earlier in the process, but you will need to do 2 full crawls afterward due to a manager profile may not yet be considered as imported and will not update until the 2nd full crawl.


Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
[Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server")

$MySite = "https://mysite.example.com"

$site = Get-SPSite $MySite
$context = Get-SPServiceContext $site
$upm = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)
$profiles = $upm.GetEnumerator()

$total = $upm.count
$i = 0
foreach ($profile in $profiles)
{
    $i++

    Write-Host "Profile: $i / $total"

    $profile["Manager"].Value = ""
    $profile.Commit();
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.