I recently experienced an issue whereby I lost a whole heap of data from the user profile service. The UPS was the data source (custom property), and not available in active directory nor anywhere else. The circumstances leading to the data loss is a separate story, but needless to say it was relatively straight forward to recover the data and re-enter it against the user profiles.
Data Recovery
Luckily I had a relatively recent copy of the Profile database, and the first thing to do was restore this against my test environment. After a quick inspection there were three key tables:
- UserProfile – stores information about the user
- PropertyList – list of all the properties, including custom ones
- UserProfileValue – where the actual data is stored
In this case, the custom property was called DeskNumber. I’ve formatted the SELECT statement for use in importing the data:
USE [Restore_ProfileDB] --NB there is a deliberate typo in the next line, replace "@" with "a"...sorry, seems to be a wordpress bug... SELECT '"' + up.NTName + '" = "' + c@st(upv.PropertyVal AS v@rchar(20))+ '";' FROM UserProfile up INNER JOIN UserProfileValue upv ON upv.recordid = up.RecordID INNER JOIN PropertyList pl ON pl.PropertyID = upv.PropertyID WHERE pl.PropertyName LIKE '%DeskNumber%' AND upv.PropertyVal IS NOT NULL |
Did I mention that you would only do this exercise on a test environment? 🙂
Here are some sample results:
Data Import
As we should not use SQL to populate the data, PowerShell comes to our rescue. The results from SQL constructs the data in key-value pairs for use in a hash table. Simple copy and paste the results from SQL into the script to populate $userData.
Then run the script, taking care of using the correct:
- MySite location
- User profile property
- Set of users
Add-PSSnapin Microsoft.SharePoint.Powershell $userData = @{ "domain\aas" = "18.61"; "domain\gle" = "M.24"; #...(repeat for each user) "domain\sch" = "M.25"; } $mySiteHostSite = Get-SPSite "http://mysites" $mySiteHostWeb = $mySiteHostSite.OpenWeb() $context = Get-SPServiceContext $mySiteHostSite $profileManager = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context) foreach ($d in $userData.Keys) { $up = $profileManager.GetUserProfile($d) $up["DeskNumber"].value = $userData[$d] $up.Commit() } |
This worked great for the custom properties for which we needed to recover. It’s pretty dumb, it doesn’t cater for disabled/deleted accounts so may throw the odd error or two on those. I could have gone for a completely integrated script that did the SQL query too, but this was a once-off exercise and it was quicker to just copy and paste the data over.
Special thanks to Phil Childs @ Get-SPScripts.com, and his script for uploading profile pictures to SharePoint using PowerShell which I loosely used as my guide for putting the latter half together.