Oh, what a journey this was. Googling, reading, BCS this, BCS that, you can do it, you can’t do it, then a somewhat vague article that almost explained it (but not quite of course). As you may or may not know, updating the manager field in user profile is a pain. You cannot map it to anything other than BCS through the built-in mechanisms. This is because of the complicated person type in SharePoint (which by default is mostly not to be messed with).
After much travail I came out the other side of the tunnel with a working solution to update the user profile manager field programmatically from SQL. This snippet loops through my SQL table, checks for the user in user profile. If the user exists then it will check to ensure the manager exists. If both check out then the update statement executes. The results are gathered as a log and emailed as html.
I created a SQL table that had the user to update and the manager to update for that user. I placed the SQL table on the same server as my sharepoint db so I could utilize the accounts that were already created there.
I ended up putting my code snippet inside of the Execute event on a custom SharePoint timer job. For info on creating custom timer jobs, you can consult this article.
Here’s my using statements above the namespace on the timer job:
using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Net.Mail; using System.Text; using System.Web; using Microsoft.SharePoint; using Microsoft.SharePoint.Administration; using Microsoft.Office.Server; using Microsoft.Office.Server.UserProfiles;
Once you have a timer job just insert this snippet into your execute event.
string message = ""; int counter = 0; // get a reference to the current site collection's content database SPWebApplication webApplication = this.Parent as SPWebApplication; SPContentDatabase contentDb = webApplication.ContentDatabases[contentDbId]; // proceed if you have a valid content database id using (SPSite site = new SPSite(contentDb.Sites[0].ID)) { // proceed if you have a valid site service context based on the site using (new SPServiceContextScope(SPServiceContext.GetContext(site))) { // create a reusable user profile user container UserProfileManager upm = new UserProfileManager(); // sql string using (var connection = new SqlConnection("Data Source=SERVERNAME;Initial Catalog=YOUR_DB;User Id=DOMAIN\\userWithSQLAccess;Password=userWithSQLAccessPwd;Integrated Security=SSPI;")) { // perform the following transactions with the following SQL command using (var command = connection.CreateCommand()) { // query used in the database that populates the users whom we want to update their manager with command.CommandText = "SELECT [AccountName], [ManagerAcctName] FROM [YOUR_DB].[dbo].[YOUR_TABLE]"; // open the connection and start the reader connection.Open(); using (var reader = command.ExecuteReader()) { // retrieve and assign values from SQL to object variables var indexOfColumn1 = reader.GetOrdinal("AccountName"); var indexOfColumn2 = reader.GetOrdinal("ManagerAcctName"); // perform while there are row results from the query above while (reader.Read()) { // assign reader object values to object variables var value1 = reader.GetValue(indexOfColumn1); var value2 = reader.GetValue(indexOfColumn2); // create strings and assigned converted string values of object variables string sAccount = String.Empty; string sManager = String.Empty; string sManagerAcctName = String.Empty; string oldManager = String.Empty; sAccount = value1.ToString(); sManagerAcctName = value2.ToString(); // check to see that the user profile exists for an account if (upm.UserExists(sAccount)) { // create a reusable user profile for checking SQL per row UserProfile u = upm.GetUserProfile(sAccount); // check for the presense of an old manager if (String.IsNullOrEmpty(u["Manager"].Value.ToString())) { // if the manager doesn't exist clear the value oldManager = ""; } else { // if the manager exists the place it there to log it oldManager = u["Manager"].Value.ToString(); } // verify that the manager exists if (sManager != null) { // create and assign the string value of the manager value from SQL string mAccount = sManagerAcctName.ToString(); // verify that there is a user profile value for the manager field given from SQL if (upm.UserExists(mAccount)) { // Assign the manager value from SQL to the user profile manager field u["Manager"].Value = mAccount; // commit the user profile save u.Commit(); // check to see if there was an old manager field populated if (string.IsNullOrEmpty(oldManager)) { // log that user had no prior manager but will now after this update message = message + sAccount + " had no previous manager but is now updated " + " to " + mAccount + "<br />"; } else { // log that the user had a prior manager but is now updated to a new one from this process message = message + sAccount + " manager was updated from " + oldManager + " to " + mAccount + "<br />"; } // keep count counter = counter + 1; } else { // if you are here than the manager value from SQL is not a valid user profile user = SKIP } } else { // if you are here then there is not a manager value in the SQL data = SKIP } } else { // if you are here than the row on the SQL data was not a valid user profile user = SKIP } } } // close the SQL connection when done connection.Close(); // attempt to send the email message try { // definet the mail client that will send the message SmtpClient client = new SmtpClient(); client.Port = 25; client.Host = "exchangeserver.yourdomain.com"; // get and assign the to field of the email message string toemail = ""; toemail = "yoursharepointadmin@yourdomain.com"; // build the mail message for the mail client to send MailMessage mm = new MailMessage(); mm.From = new MailAddress("donotreply@yourdomain.com"); mm.To.Add(new MailAddress(toemail)); // put the rest of email together mm.Subject = "AD Manager To UPS Timer Job - " + counter.ToString() + " records processed"; mm.Body = message; mm.IsBodyHtml = true; // send the message client.Send(mm); } catch { // handle error if you want } } } } }