/// <summary> /// Update the given records. /// </summary> /// <param name="data">The data to update.</param> public void Update(DataTable data) { if (data == null) { throw new ArgumentNullException("data"); } ValidateDataHasId(data); SalesForceAPI.Partner.sObject[] records = Convert(data, true); for (int i = 0; i < records.Length; i += 200) { SalesForceAPI.Partner.sObject[] buf = new SalesForceAPI.Partner.sObject[Math.Min(200, records.Length - i)]; Array.Copy(records, i, buf, 0, buf.Length); SalesForceAPI.Partner.updateResponse response = _client.PartnerClient.update(new SalesForceAPI.Partner.updateRequest( new SalesForceAPI.Partner.SessionHeader() { sessionId = _client.SessionId }, null, null, null, null, null, null, null, null, null, null, null, buf)); if (response.result != null) { foreach (SalesForceAPI.Partner.SaveResult entry in response.result) { if (!entry.success) { StringBuilder sb = new StringBuilder(); sb.AppendLine("Failed to save " + entry.id); if (entry.errors != null) { foreach (SalesForceAPI.Partner.Error err in entry.errors) { sb.AppendLine(err.message); } } throw new Exception(sb.ToString()); } } } } }
/// <summary> /// Convert the given data into a collection of SObjects. /// </summary> /// <param name="data">The data to convert.</param> /// <param name="excludeReadOnlyFields"> /// When true, any fields that are readonly will not be included in the converted /// results with the exception of the id field. /// </param> /// <returns>The SObjects built from the data table.</returns> private SalesForceAPI.Partner.sObject[] Convert(DataTable data, bool excludeReadOnlyFields) { List <SalesForceAPI.Partner.sObject> result = new List <SalesForceAPI.Partner.sObject>(); System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); if (data == null) { return(result.ToArray()); } foreach (DataRow row in data.Rows) { SalesForceAPI.Partner.sObject record = new SalesForceAPI.Partner.sObject(); record.type = data.TableName; List <System.Xml.XmlElement> any = new List <System.Xml.XmlElement>(); List <string> nullFields = new List <string>(); foreach (DataColumn column in data.Columns) { if (excludeReadOnlyFields && column.ReadOnly && String.Compare(column.ColumnName, "Id", 0) != 0) { continue; } System.Xml.XmlElement e = doc.CreateElement(column.ColumnName); if (row[column] != null && row[column].GetType() == typeof(DateTime)) { e.InnerText = ((DateTime)row[column]).ToString("s"); } else { e.InnerText = System.Convert.ToString(row[column]); } // don't put Id field in null list if (String.Compare(column.ColumnName, "Id", 0) == 0 && String.IsNullOrWhiteSpace(e.InnerText)) { continue; } if (e.InnerText == null || e.InnerText == String.Empty) { nullFields.Add(column.ColumnName); } else { any.Add(e); } } record.Any = any.ToArray(); record.fieldsToNull = nullFields.ToArray(); result.Add(record); } return(result.ToArray()); }
/// <summary> /// Converts the collection of SObjects into a data table. /// </summary> /// <param name="records">The records to convert. All of them need to be of the same type.</param> /// <param name="includeStructure">If true the table structure is set. i.e. readonly columns are set.</param> /// <returns>The data table which holds all of the records.</returns> private DataTable Convert(IEnumerable <SalesForceAPI.Partner.sObject> records, bool includeStructure) { if (records == null || records.Count() == 0) { return(new DataTable()); } // setup the table schema SalesForceAPI.Partner.sObject first = records.First(); SObjectType objectType = null; if (includeStructure) { objectType = DescribeObjectType(first.type); } DataTable dt = new DataTable(first.type); if (first.Any != null) { foreach (System.Xml.XmlElement e in first.Any) { if (e.HasAttributes && e.HasChildNodes) { for (int i = 2; i < e.ChildNodes.Count; i++) { string name = String.Format("{0}:{1}", e.LocalName, e.ChildNodes[i].LocalName); DataColumn column = dt.Columns.Add(name); column.ReadOnly = true; } } else { DataColumn column = dt.Columns.Add(e.LocalName); if (objectType != null) { SObjectFieldType field = objectType.Fields .Where(f => String.Compare(f.Name, column.ColumnName, true) == 0) .FirstOrDefault(); if (field != null) { column.ReadOnly = !field.Updateable; } } } } } // convert the rows foreach (SalesForceAPI.Partner.sObject record in records) { if (record == null) { throw new ArgumentException("records contains a null entry.", "records"); } DataRow row = dt.NewRow(); if (record.Any != null) { foreach (System.Xml.XmlElement e in record.Any) { if (e.HasAttributes && e.HasChildNodes) { for (int i = 2; i < e.ChildNodes.Count; i++) { string name = String.Format("{0}:{1}", e.LocalName, e.ChildNodes[i].LocalName); row[name] = e.ChildNodes[i].InnerText; } } else { if (record.fieldsToNull != null && record.fieldsToNull.Contains(e.LocalName)) { row[e.LocalName] = null; } else { row[e.LocalName] = e.InnerText; } } } } dt.Rows.Add(row); } dt.AcceptChanges(); return(dt); }
/// <summary> /// Insert the given records. /// </summary> /// <param name="data">The data to insert.</param> /// <remarks>The data passed in will be updated with the id of the newly inserted records.</remarks> public void Insert(DataTable data) { SalesForceAPI.Partner.sObject[] records = Convert(data, true); for (int i = 0; i < records.Length; i += 200) { SalesForceAPI.Partner.sObject[] buf = new SalesForceAPI.Partner.sObject[Math.Min(200, records.Length - i)]; Array.Copy(records, i, buf, 0, buf.Length); SalesForceAPI.Partner.createResponse response = _client.PartnerClient.create(new SalesForceAPI.Partner.createRequest( new SalesForceAPI.Partner.SessionHeader() { sessionId = _client.SessionId }, null, null, null, null, null, null, null, null, null, null, buf)); if (!data.Columns.Contains("Id")) { data.Columns.Add("Id"); } data.Columns["Id"].ReadOnly = false; try { if (response.result != null && response.result.Length == data.Rows.Count) { for (int j = 0; j < response.result.Length; j++) { if (!response.result[j].success) { StringBuilder sb = new StringBuilder(); sb.AppendLine("Failed to save " + response.result[j].id); if (response.result[j].errors != null) { foreach (SalesForceAPI.Partner.Error err in response.result[j].errors) { sb.AppendLine(err.message); } } throw new Exception(sb.ToString()); } else { data.Rows[j + i]["Id"] = response.result[j].id; } } } } finally { data.Columns["Id"].ReadOnly = true; } } }