diff --git a/src/CommonLibrariesForNET/IAuthenticationClient.cs b/src/CommonLibrariesForNET/IAuthenticationClient.cs index 4dd0ee40..0ddd10c1 100644 --- a/src/CommonLibrariesForNET/IAuthenticationClient.cs +++ b/src/CommonLibrariesForNET/IAuthenticationClient.cs @@ -10,12 +10,13 @@ public interface IAuthenticationClient : IDisposable string AccessToken { get; set; } string Id { get; set; } string ApiVersion { get; set; } - + Task UsernamePasswordAsync(string clientId, string clientSecret, string username, string password); Task UsernamePasswordAsync(string clientId, string clientSecret, string username, string password, string tokenRequestEndpointUrl); Task WebServerAsync(string clientId, string clientSecret, string redirectUri, string code); Task WebServerAsync(string clientId, string clientSecret, string redirectUri, string code, string tokenRequestEndpointUrl); Task TokenRefreshAsync(string clientId, string refreshToken, string clientSecret = ""); Task TokenRefreshAsync(string clientId, string refreshToken, string clientSecret, string tokenRequestEndpointUrl); + Task GetLatestVersionAsync(); } } diff --git a/src/CommonLibrariesForNET/Models/Xml/JobInfo.cs b/src/CommonLibrariesForNET/Models/Xml/JobInfo.cs index b9d5c317..ab0ee985 100644 --- a/src/CommonLibrariesForNET/Models/Xml/JobInfo.cs +++ b/src/CommonLibrariesForNET/Models/Xml/JobInfo.cs @@ -12,6 +12,8 @@ public class JobInfo [XmlElement(ElementName = "object")] public string Object { get; set; } + [XmlElement(ElementName = "concurrencyMode")] + public string ConcurrencyMode { get; set; } [XmlElement(ElementName = "externalIdFieldName")] public string ExternalIdFieldName { get; set; } diff --git a/src/CommonLibrariesForNET/Models/Xml/JobInfoResult.cs b/src/CommonLibrariesForNET/Models/Xml/JobInfoResult.cs index dcb75d23..a459383f 100644 --- a/src/CommonLibrariesForNET/Models/Xml/JobInfoResult.cs +++ b/src/CommonLibrariesForNET/Models/Xml/JobInfoResult.cs @@ -23,9 +23,6 @@ public class JobInfoResult : JobInfo [XmlElement(ElementName = "state")] public string State { get; set; } - [XmlElement(ElementName = "concurrencyMode")] - public string ConcurrencyMode { get; set; } - [XmlElement(ElementName = "numberBatchesQueued")] public int NumberBatchesQueued { get; set; } diff --git a/src/ForceToolkitForNET/BulkConstants.cs b/src/ForceToolkitForNET/BulkConstants.cs index 47607c4f..64a5d558 100644 --- a/src/ForceToolkitForNET/BulkConstants.cs +++ b/src/ForceToolkitForNET/BulkConstants.cs @@ -23,6 +23,24 @@ public string Value() } } + public sealed class ConcurrencyMode + { + public static readonly ConcurrencyMode Parallel = new ConcurrencyMode("Parallel"); + public static readonly ConcurrencyMode Serial = new ConcurrencyMode("Serial"); + + private readonly string _value; + + private ConcurrencyMode(string value) + { + _value = value; + } + + public string Value() + { + return _value; + } + } + public sealed class BatchState { public static readonly BatchState Queued = new BatchState("Queued"); diff --git a/src/ForceToolkitForNET/ForceClient.cs b/src/ForceToolkitForNET/ForceClient.cs index b30135cf..ab1e1ae3 100644 --- a/src/ForceToolkitForNET/ForceClient.cs +++ b/src/ForceToolkitForNET/ForceClient.cs @@ -20,7 +20,7 @@ public class ForceClient : IForceClient, IDisposable protected readonly XmlHttpClient _xmlHttpClient; protected readonly JsonHttpClient _jsonHttpClient; - public ISelectListResolver SelectListResolver { get; set; } + public ISelectListResolver SelectListResolver { get; set; } public ForceClient(string instanceUrl, string accessToken, string apiVersion) : this(instanceUrl, accessToken, apiVersion, new HttpClient(), new HttpClient()) @@ -37,7 +37,7 @@ public ForceClient(string instanceUrl, string accessToken, string apiVersion, Ht _jsonHttpClient = new JsonHttpClient(instanceUrl, apiVersion, accessToken, httpClientForJson, callerWillDisposeHttpClients); _xmlHttpClient = new XmlHttpClient(instanceUrl, apiVersion, accessToken, httpClientForXml, callerWillDisposeHttpClients); - + SelectListResolver = new DataMemberSelectListResolver(); } @@ -272,11 +272,11 @@ public async Task GetFieldsCommaSeparatedListAsync(string objectName) List objectDescription = new List(); foreach (ExpandoObject field in fields as IEnumerable) { - objectDescription.Add((field).FirstOrDefault(x => x.Key == "name").Value.ToString()); + objectDescription.Add((field).FirstOrDefault(x => x.Key == "name").Value.ToString()); } return string.Join(", ", objectDescription); } - + public Task ExecuteAnonymousAsync(string apex) { if (string.IsNullOrEmpty(apex)) throw new ArgumentNullException("apex"); @@ -286,19 +286,19 @@ public Task ExecuteAnonymousAsync(string apex) // BULK METHODS public async Task> RunJobAsync(string objectName, BulkConstants.OperationType operationType, - IEnumerable> recordsLists) + IEnumerable> recordsLists, BulkConstants.ConcurrencyMode concurrencyMode = null) { - return await RunJobAsync(objectName, null, operationType, recordsLists); + return await RunJobAsync(objectName, null, operationType, recordsLists, concurrencyMode); } public async Task> RunJobAsync(string objectName, string externalIdFieldName, - BulkConstants.OperationType operationType, IEnumerable> recordsLists) + BulkConstants.OperationType operationType, IEnumerable> recordsLists, BulkConstants.ConcurrencyMode concurrencyMode = null) { if (recordsLists == null) throw new ArgumentNullException("recordsLists"); if (operationType == BulkConstants.OperationType.Upsert && string.IsNullOrEmpty(externalIdFieldName)) throw new ArgumentNullException(nameof(externalIdFieldName)); - var jobInfoResult = await CreateJobAsync(objectName, externalIdFieldName, operationType); + var jobInfoResult = await CreateJobAsync(objectName, externalIdFieldName, operationType, concurrencyMode); var batchResults = new List(); foreach (var recordList in recordsLists) { @@ -309,18 +309,18 @@ public async Task> RunJobAsync(string objectName, strin } public async Task> RunJobAndPollAsync(string objectName, BulkConstants.OperationType operationType, - IEnumerable> recordsLists) + IEnumerable> recordsLists, BulkConstants.ConcurrencyMode concurrencyMode = null) { - return await RunJobAndPollAsync(objectName, null, operationType, recordsLists); + return await RunJobAndPollAsync(objectName, null, operationType, recordsLists, concurrencyMode); } public async Task> RunJobAndPollAsync(string objectName, string externalIdFieldName, BulkConstants.OperationType operationType, - IEnumerable> recordsLists) + IEnumerable> recordsLists, BulkConstants.ConcurrencyMode concurrencyMode = null) { const float pollingStart = 1000; const float pollingIncrease = 2.0f; - var batchInfoResults = await RunJobAsync(objectName, externalIdFieldName, operationType, recordsLists); + var batchInfoResults = await RunJobAsync(objectName, externalIdFieldName, operationType, recordsLists, concurrencyMode); var currentPoll = pollingStart; var finishedBatchInfoResults = new List(); @@ -356,23 +356,26 @@ public async Task> RunJobAndPollAsync(string objectName return batchResults; } - public async Task CreateJobAsync(string objectName, BulkConstants.OperationType operationType) + public async Task CreateJobAsync(string objectName, BulkConstants.OperationType operationType, BulkConstants.ConcurrencyMode concurrencyMode = null) { - return await CreateJobAsync(objectName, null, operationType); + return await CreateJobAsync(objectName, null, operationType, concurrencyMode); } - public async Task CreateJobAsync(string objectName, string externalIdFieldName, BulkConstants.OperationType operationType) + public async Task CreateJobAsync(string objectName, string externalIdFieldName, BulkConstants.OperationType operationType, BulkConstants.ConcurrencyMode concurrencyMode = null) { if (string.IsNullOrEmpty(objectName)) throw new ArgumentNullException(nameof(objectName)); if (operationType == BulkConstants.OperationType.Upsert && string.IsNullOrEmpty(externalIdFieldName)) throw new ArgumentNullException(nameof(externalIdFieldName)); + if (concurrencyMode == null) concurrencyMode = BulkConstants.ConcurrencyMode.Parallel; + var jobInfo = new JobInfo { ContentType = "XML", Object = objectName, ExternalIdFieldName = externalIdFieldName, - Operation = operationType.Value() + Operation = operationType.Value(), + ConcurrencyMode = concurrencyMode.Value() }; return await _xmlHttpClient.HttpPostAsync(jobInfo, "/services/async/{0}/job"); diff --git a/src/ForceToolkitForNET/IForceClient.cs b/src/ForceToolkitForNET/IForceClient.cs index aa53de42..31f374cf 100644 --- a/src/ForceToolkitForNET/IForceClient.cs +++ b/src/ForceToolkitForNET/IForceClient.cs @@ -15,7 +15,7 @@ public interface IForceClient : IDisposable Task> QueryAllAsync(string query); Task QueryByIdAsync(string objectName, string recordId); Task QueryAllFieldsByIdAsync(string objectName, string recordId); - Task QueryAllFieldsByExternalIdAsync(string objectName, string externalIdFieldName, string externalId); + Task QueryAllFieldsByExternalIdAsync(string objectName, string externalIdFieldName, string externalId); Task ExecuteRestApiAsync(string apiName); Task ExecuteRestApiAsync(string apiName, object inputObject); Task CreateAsync(string objectName, object record); @@ -37,12 +37,14 @@ public interface IForceClient : IDisposable Task UserInfo(string url); Task GetBlobAsync(String objectName, String objectId, String fieldName); Task GetFieldsCommaSeparatedListAsync(string objectName); - Task ExecuteAnonymousAsync(string apex); + Task ExecuteAnonymousAsync(string apex); // BULK - Task> RunJobAsync(string objectName, BulkConstants.OperationType operationType, IEnumerable> recordsLists); - Task> RunJobAndPollAsync(string objectName, BulkConstants.OperationType operationType, IEnumerable> recordsLists); - Task CreateJobAsync(string objectName, BulkConstants.OperationType operationType); + Task> RunJobAsync(string objectName, BulkConstants.OperationType operationType,IEnumerable> recordsLists, BulkConstants.ConcurrencyMode concurrencyMode = null); + Task> RunJobAsync(string objectName, string externalIdFieldName, BulkConstants.OperationType operationType, IEnumerable> recordsLists, BulkConstants.ConcurrencyMode concurrencyMode = null); + Task> RunJobAndPollAsync(string objectName, BulkConstants.OperationType operationType, IEnumerable> recordsLists, BulkConstants.ConcurrencyMode concurrencyMode = null); + Task> RunJobAndPollAsync(string objectName, string externalIdFieldName, BulkConstants.OperationType operationType, IEnumerable> recordsLists, BulkConstants.ConcurrencyMode concurrencyMode = null); + Task CreateJobAsync(string objectName, BulkConstants.OperationType operationType, BulkConstants.ConcurrencyMode concurrencyMode = null); Task CreateJobBatchAsync(JobInfoResult jobInfo, ISObjectList recordsObject); Task CreateJobBatchAsync(string jobId, ISObjectList recordsObject); Task CloseJobAsync(JobInfoResult jobInfo);