public async Task <IEnumerable <BatchInfoResult> > SubmitTimeSheets(IEnumerable <entities.TimeSheet> timeSheets) { const int batchSize = 100; var jobInfo = await _forceClient.CreateJobAsync("BP_Weekly_Timesheet__c", BulkConstants.OperationType.Insert); var tsBatchList = Batch_TimeSheets(timeSheets, batchSize); var batchInfoResultList = new List <BatchInfoResult>(); foreach (var tsBatch in tsBatchList) { var batch = new SObjectList <SObject>(); foreach (var ts in tsBatch) { var rec = new SObject { { "Name", $"Week of {ts.StartDate.ToString("yyyy-MM-dd")}" }, { "Submitted_By__c", $"{ts.UserId}" }, { "start_date__c", $"{ts.StartDate.ToString("yyyy-MM-dd")}" } }; batch.Add(rec); } batchInfoResultList.Add(await _forceClient.CreateJobBatchAsync(jobInfo, batch)); } var jonInfoResult = await _forceClient.CloseJobAsync(jobInfo); // Closing job prevents any more batches from being added. return(batchInfoResultList); }
private async Task <IEnumerable <entities.UserTimeClock> > BatchAndSubmit_UserTimeClocks(Salesforce.Common.Models.Xml.JobInfoResult jobInfo, IEnumerable <UserTimeClock> userTimeClocks) { const int batchSize = 100; var utcBatchList = Batch_UserTimeClocks(userTimeClocks, batchSize); var batchInfoResultList = new List <BatchInfoResult>(); var startDate = userTimeClocks.FirstOrDefault().StartDate; foreach (var utcBatch in utcBatchList) { // map bhive usertimeclock records to sales force time sheet activity records var tsaBatch = new SObjectList <SObject>(); foreach (var utc in utcBatch) { tsaBatch.Add(MapToSalesForceTimeSheetActivityRecord(utc)); } // submit batch here var batchInfoResult = await _forceClient.CreateJobBatchAsync(jobInfo, tsaBatch); batchInfoResultList.Add(batchInfoResult); // Set SalesForce job id and batch id in user time clock record foreach (var utc in utcBatch) { utc.JobId = jobInfo.Id; utc.BatchId = batchInfoResult.Id; } SaveSubmittedBatchToBlobStorage(startDate, batchInfoResult.Id, tsaBatch); } // Closing job prevents any more batches from being added and // allows faster reading of submission results. await _forceClient.CloseJobAsync(jobInfo); var batchResultsList = await Get_BatchSubmissionResults(batchInfoResultList); userTimeClocks = setTimeSheetActivityIdsFromSalesForce(batchResultsList, userTimeClocks); return(userTimeClocks); }
private void SaveSubmittedBatchToBlobStorage(DateTime startDate, string batchId, SObjectList <SObject> batch) { const string containerName = "sftimesheet-submissions"; var jsonBuilder = new JsonBuilder <SObject>(); var json = jsonBuilder.JsonifyWithLineFeed(batch); var gzippedStream = CompressionHelper.CompressToStream(Encoding.UTF8.GetBytes(json)); var key = $"{startDate.ToString("yyyy-MM-dd")}/batch-{batchId}.gzip"; BlobStorageHelper.Instance.UploadGZipStream(containerName, key, gzippedStream); }
public async Task FullRunThrough() { // Make a strongly typed Account list var stAccountsBatch = new SObjectList <Account> { new Account { Name = "TestStAccount1" }, new Account { Name = "TestStAccount2" }, new Account { Name = "TestStAccount3" } }; // insert the accounts var results1 = await _client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Insert, new List <SObjectList <Account> > { stAccountsBatch }); // (one SObjectList<T> per batch, the example above uses one batch) Assert.IsTrue(results1 != null, "[results1] empty result object"); Assert.AreEqual(results1.Count, 1, "[results1] wrong number of results"); Assert.AreEqual(results1[0].Items.Count, 3, "[results1] wrong number of result records"); Assert.IsTrue(results1[0].Items[0].Created); Assert.IsTrue(results1[0].Items[0].Success); Assert.IsTrue(results1[0].Items[1].Created); Assert.IsTrue(results1[0].Items[1].Success); Assert.IsTrue(results1[0].Items[2].Created); Assert.IsTrue(results1[0].Items[2].Success); // Make a dynamic typed Account list var dtAccountsBatch = new SObjectList <SObject> { new SObject { { "Name", "TestDtAccount1" } }, new SObject { { "Name", "TestDtAccount2" } }, new SObject { { "Name", "TestDtAccount3" } } }; // insert the accounts var results2 = await _client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Insert, new List <SObjectList <SObject> > { dtAccountsBatch }); Assert.IsTrue(results2 != null, "[results2] empty result object"); Assert.AreEqual(results2.Count, 1, "[results2] wrong number of results"); Assert.AreEqual(results2[0].Items.Count, 3, "[results2] wrong number of result records"); Assert.IsTrue(results2[0].Items[0].Created); Assert.IsTrue(results2[0].Items[0].Success); Assert.IsTrue(results2[0].Items[1].Created); Assert.IsTrue(results2[0].Items[1].Success); Assert.IsTrue(results2[0].Items[2].Created); Assert.IsTrue(results2[0].Items[2].Success); // get the id of the first account created in the first batch var id = results2[0].Items[0].Id; dtAccountsBatch = new SObjectList <SObject> { new SObject { { "Id", id }, { "Name", "TestDtAccount1Renamed" } } }; // update the first accounts name (dont really need bulk for this, just an example) var results3 = await _client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Update, new List <SObjectList <SObject> > { dtAccountsBatch }); Assert.IsTrue(results3 != null); Assert.AreEqual(results3.Count, 1); Assert.AreEqual(results3[0].Items.Count, 1); Assert.AreEqual(results3[0].Items[0].Id, id); Assert.IsFalse(results3[0].Items[0].Created); Assert.IsTrue(results3[0].Items[0].Success); // create an Id list for the original strongly typed accounts created var idBatch = new SObjectList <SObject>(); idBatch.AddRange(results1[0].Items.Select(result => new SObject { { "Id", result.Id } })); // delete all the strongly typed accounts var results4 = await _client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Delete, new List <SObjectList <SObject> > { idBatch }); Assert.IsTrue(results4 != null, "[results4] empty result object"); Assert.AreEqual(results4.Count, 1, "[results4] wrong number of results"); Assert.AreEqual(results4[0].Items.Count, 3, "[results4] wrong number of result records"); Assert.IsFalse(results4[0].Items[0].Created); Assert.IsTrue(results4[0].Items[0].Success); }
public async Task UpsertTests() { // Requires a new field on Contact "Unique_Email__c" with External Id set. if (_testUpsert) { var dtContactsBatch1 = new SObjectList <SObject> { new SObject { { "FirstName", "TestDtContact1" }, { "LastName", "TestDtContact1" }, { "MailingCity", "London" }, { "Email", "*****@*****.**" }, { "Unique_Email__c", "*****@*****.**" } }, new SObject { { "FirstName", "TestDtContact2" }, { "LastName", "TestDtContact2" }, { "MailingCity", "London" }, { "Email", "*****@*****.**" }, { "Unique_Email__c", "*****@*****.**" } } }; var resultsUpsert1 = await _client.RunJobAndPollAsync("Contact", "Unique_Email__c", BulkConstants.OperationType.Upsert, new List <SObjectList <SObject> > { dtContactsBatch1 }); Assert.IsTrue(resultsUpsert1 != null); Assert.AreEqual(resultsUpsert1.Count, 1); Assert.AreEqual(resultsUpsert1[0].Items.Count, 2); Assert.IsTrue(resultsUpsert1[0].Items[0].Created); Assert.IsTrue(resultsUpsert1[0].Items[0].Success); Assert.IsTrue(resultsUpsert1[0].Items[1].Created); Assert.IsTrue(resultsUpsert1[0].Items[1].Success); var dtContactsBatch2 = new SObjectList <SObject> { new SObject { { "FirstName", "TestDtContact2" }, { "LastName", "TestDtContact2" }, { "MailingCity", "York" }, { "Email", "*****@*****.**" }, { "Unique_Email__c", "*****@*****.**" } }, new SObject { { "FirstName", "TestDtContact3" }, { "LastName", "TestDtContact3" }, { "MailingCity", "York" }, { "Email", "*****@*****.**" }, { "Unique_Email__c", "*****@*****.**" } } }; var resultsUpsert2 = await _client.RunJobAndPollAsync("Contact", "Unique_Email__c", BulkConstants.OperationType.Upsert, new List <SObjectList <SObject> > { dtContactsBatch2 }); Assert.IsTrue(resultsUpsert2 != null); Assert.AreEqual(resultsUpsert2.Count, 1); Assert.AreEqual(resultsUpsert2[0].Items.Count, 2); Assert.IsFalse(resultsUpsert2[0].Items[0].Created); Assert.IsTrue(resultsUpsert2[0].Items[0].Success); Assert.IsTrue(resultsUpsert2[0].Items[1].Created); Assert.IsTrue(resultsUpsert2[0].Items[1].Success); // create an Id list for the original strongly typed accounts created var idBatch = new SObjectList <SObject>(); idBatch.AddRange(resultsUpsert1[0].Items.Select(result => new SObject { { "Id", result.Id } })); idBatch.Add(new SObject { { "Id", resultsUpsert2[0].Items[1].Id } }); var resultsDelete = await _client.RunJobAndPollAsync("Contact", BulkConstants.OperationType.Delete, new List <SObjectList <SObject> > { idBatch }); Assert.IsTrue(resultsDelete != null, "[results4] empty result object"); Assert.AreEqual(resultsDelete.Count, 1, "[results4] wrong number of results"); Assert.AreEqual(resultsDelete[0].Items.Count, 3, "[results4] wrong number of result records"); } else { Assert.Inconclusive("Upsert Tests Skipped."); } }
public async Task UpsertAccountTests() { var dtContactsBatch1 = new SObjectList <SObject> { new SObject { { "Name", "Upsert 1" } }, new SObject { { "Name", "Upsert 2" } } }; var resultsUpsert1 = await _client.RunJobAndPollAsync("Campaign", "Name", BulkConstants.OperationType.Upsert, new List <SObjectList <SObject> > { dtContactsBatch1 }); Assert.IsTrue(resultsUpsert1 != null); Assert.AreEqual(resultsUpsert1.Count, 1); Assert.AreEqual(resultsUpsert1[0].Items.Count, 2); // TODO: This fails on successive runs against an org; update so that we delete these after running the test // Assert.IsTrue(resultsUpsert1[0].Items[0].Created); Assert.IsTrue(resultsUpsert1[0].Items[0].Success); // Assert.IsTrue(resultsUpsert1[0].Items[1].Created); Assert.IsTrue(resultsUpsert1[0].Items[1].Success); var dtContactsBatch2 = new SObjectList <SObject> { new SObject { { "Name", "Upsert 2" }, { "Description", "Updated via Upsert" } }, new SObject { { "Name", "Upsert 3" } } }; var resultsUpsert2 = await _client.RunJobAndPollAsync("Campaign", "Name", BulkConstants.OperationType.Upsert, new List <SObjectList <SObject> > { dtContactsBatch2 }); Assert.IsTrue(resultsUpsert2 != null); Assert.AreEqual(resultsUpsert2.Count, 1); Assert.AreEqual(resultsUpsert2[0].Items.Count, 2); // Assert.IsFalse(resultsUpsert2[0].Items[0].Created); Assert.IsTrue(resultsUpsert2[0].Items[0].Success); // Assert.IsTrue(resultsUpsert2[0].Items[1].Created); Assert.IsTrue(resultsUpsert2[0].Items[1].Success); // create an Id list for the original strongly typed accounts created var idBatch = new SObjectList <SObject>(); idBatch.AddRange(resultsUpsert1[0].Items.Select(result => new SObject { { "Id", result.Id } })); idBatch.Add(new SObject { { "Id", resultsUpsert2[0].Items[1].Id } }); var resultsDelete = await _client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Delete, new List <SObjectList <SObject> > { idBatch }); Assert.IsTrue(resultsDelete != null, "[results4] empty result object"); Assert.AreEqual(resultsDelete.Count, 1, "[results4] wrong number of results"); Assert.AreEqual(resultsDelete[0].Items.Count, 3, "[results4] wrong number of result records"); }
private static async Task RunSample() { var auth = new AuthenticationClient(); // Authenticate with Salesforce Console.WriteLine("Authenticating with Salesforce"); var url = IsSandboxUser.Equals("true", StringComparison.CurrentCultureIgnoreCase) ? "https://test.salesforce.com/services/oauth2/token" : "https://login.salesforce.com/services/oauth2/token"; await auth.UsernamePasswordAsync(ConsumerKey, ConsumerSecret, Username, Password, url); Console.WriteLine("Connected to Salesforce"); // Get a bulk client var client = new ForceClient(auth.InstanceUrl, auth.AccessToken, auth.ApiVersion); // create a job var jobInfo = await client.CreateJobAsync("Account", BulkConstants.OperationType.Insert); Console.WriteLine("Created a Job"); // Make a dynamic typed Account list var dtAccountsBatch1 = new SObjectList <SObject> { new SObject { { "Name", "TestDtAccount1" } }, new SObject { { "Name", "TestDtAccount2" } }, new SObject { { "MADEUPFIELD", "MADEUPVALUE" } }, new SObject { { "Name", "TestDtAccount3" } } }; // Make a dynamic typed Account list var dtAccountsBatch2 = new SObjectList <SObject> { new SObject { { "Name", "TestDtAccount4" } }, new SObject { { "Name", "TestDtAccount5" } }, new SObject { { "Name", "TestDtAccount6" } } }; // Make a dynamic typed Account list var dtAccountsBatch3 = new SObjectList <SObject> { new SObject { { "MADEUPFIELD", "MADEUPVALUE" } }, new SObject { { "Name", "TestDtAccount7" } }, new SObject { { "Name", "TestDtAccount8" } }, new SObject { { "Name", "TestDtAccount9" } } }; // create the batches var batchInfoList = new List <BatchInfoResult> { await client.CreateJobBatchAsync(jobInfo, dtAccountsBatch1), await client.CreateJobBatchAsync(jobInfo, dtAccountsBatch2), await client.CreateJobBatchAsync(jobInfo, dtAccountsBatch3) }; Console.WriteLine("Created Three Batches"); // poll var pollStart = 1.0f; const float pollIncrease = 2.0f; var completeList = new List <BatchInfoResult>(); while (batchInfoList.Count > 0) { var removeList = new List <BatchInfoResult>(); foreach (var batchInfo in batchInfoList) { var newBatchInfo = await client.PollBatchAsync(batchInfo); if (newBatchInfo.State.Equals(BulkConstants.BatchState.Completed.Value()) || newBatchInfo.State.Equals(BulkConstants.BatchState.Failed.Value()) || newBatchInfo.State.Equals(BulkConstants.BatchState.NotProcessed.Value())) { completeList.Add(newBatchInfo); removeList.Add(batchInfo); } } foreach (var removeInfo in removeList) { batchInfoList.Remove(removeInfo); } await Task.Delay((int)pollStart); pollStart *= pollIncrease; } // get results var results = new List <BatchResultList>(); foreach (var completeBatch in completeList) { results.Add(await client.GetBatchResultAsync(completeBatch)); } Console.WriteLine("All Batches Complete, \"var results\" contains the result objects (Each is a list containing a result for each record):"); foreach (var result in results.SelectMany(resultList => resultList.Items)) { Console.WriteLine("Id:{0}, Created:{1}, Success:{2}, Errors:{3}", result.Id, result.Created, result.Success, result.Errors != null); if (result.Errors != null) { Console.WriteLine("\tErrors:"); var resultErrors = result.Errors; foreach (var field in resultErrors.Fields) { Console.WriteLine("\tField:{0}", field); } Console.WriteLine("\t{0}", resultErrors.Message); Console.WriteLine("\t{0}", resultErrors.StatusCode); } } }
private static async Task RunSample() { var auth = new AuthenticationClient(); // Authenticate with Salesforce Console.WriteLine("Authenticating with Salesforce"); var url = IsSandboxUser.Equals("true", StringComparison.CurrentCultureIgnoreCase) ? "https://test.salesforce.com/services/oauth2/token" : "https://login.salesforce.com/services/oauth2/token"; await auth.UsernamePasswordAsync(ConsumerKey, ConsumerSecret, Username, Password, url); Console.WriteLine("Connected to Salesforce"); // Get a bulk client var client = new ForceClient(auth.InstanceUrl, auth.AccessToken, auth.ApiVersion); // Make a strongly typed Account list var stAccountsBatch = new SObjectList<Account> { new Account {Name = "TestStAccount1"}, new Account {Name = "TestStAccount2"}, new Account {Name = "TestStAccount3"} }; // insert the accounts var results1 = await client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Insert, new List<SObjectList<Account>>{stAccountsBatch}); // (one SObjectList<T> per batch, the example above uses one batch) Console.WriteLine("Strongly typed accounts created"); // Make a dynamic typed Account list var dtAccountsBatch = new SObjectList<SObject> { new SObject{{"Name", "TestDtAccount1"}}, new SObject{{"Name", "TestDtAccount2"}}, new SObject{{"Name", "TestDtAccount3"}} }; // insert the accounts var results2 = await client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Insert, new List<SObjectList<SObject>>{dtAccountsBatch}); Console.WriteLine("Dynamically typed accounts created"); // get the id of the first account created in the first batch var id = results2[0][0].Id; dtAccountsBatch = new SObjectList<SObject> { new SObject { {"Id", id}, {"Name", "TestDtAccount1Renamed"} } }; // update the first accounts name (dont really need bulk for this, just an example) var results3 = await client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Update, new List<SObjectList<SObject>>{dtAccountsBatch}); Console.WriteLine("Account with ID {0} updated", id); // create an Id list for the original strongly typed accounts created var idBatch = new SObjectList<SObject>(); idBatch.AddRange(results1[0].Select(result => new SObject {{"Id", result.Id}})); // delete all the strongly typed accounts var results4 = await client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Delete, new List<SObjectList<SObject>>{idBatch}); Console.WriteLine("Accounts deleted"); }
public async void FullRunThrough() { // Make a strongly typed Account list var stAccountsBatch = new SObjectList<Account> { new Account {Name = "TestStAccount1"}, new Account {Name = "TestStAccount2"}, new Account {Name = "TestStAccount3"} }; // insert the accounts var results1 = await _client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Insert, new List<SObjectList<Account>> { stAccountsBatch }); // (one SObjectList<T> per batch, the example above uses one batch) Assert.IsTrue(results1 != null, "[results1] empty result object"); Assert.AreEqual(results1.Count, 1, "[results1] wrong number of results"); Assert.AreEqual(results1[0].Items.Count, 3, "[results1] wrong number of result records"); Assert.IsTrue(results1[0].Items[0].Created); Assert.IsTrue(results1[0].Items[0].Success); Assert.IsTrue(results1[0].Items[1].Created); Assert.IsTrue(results1[0].Items[1].Success); Assert.IsTrue(results1[0].Items[2].Created); Assert.IsTrue(results1[0].Items[2].Success); // Make a dynamic typed Account list var dtAccountsBatch = new SObjectList<SObject> { new SObject{{"Name", "TestDtAccount1"}}, new SObject{{"Name", "TestDtAccount2"}}, new SObject{{"Name", "TestDtAccount3"}} }; // insert the accounts var results2 = await _client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Insert, new List<SObjectList<SObject>> { dtAccountsBatch }); Assert.IsTrue(results2 != null, "[results2] empty result object"); Assert.AreEqual(results2.Count, 1, "[results2] wrong number of results"); Assert.AreEqual(results2[0].Items.Count, 3, "[results2] wrong number of result records"); Assert.IsTrue(results2[0].Items[0].Created); Assert.IsTrue(results2[0].Items[0].Success); Assert.IsTrue(results2[0].Items[1].Created); Assert.IsTrue(results2[0].Items[1].Success); Assert.IsTrue(results2[0].Items[2].Created); Assert.IsTrue(results2[0].Items[2].Success); // get the id of the first account created in the first batch var id = results2[0].Items[0].Id; dtAccountsBatch = new SObjectList<SObject> { new SObject { {"Id", id}, {"Name", "TestDtAccount1Renamed"} } }; // update the first accounts name (dont really need bulk for this, just an example) var results3 = await _client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Update, new List<SObjectList<SObject>> { dtAccountsBatch }); Assert.IsTrue(results3 != null); Assert.AreEqual(results3.Count, 1); Assert.AreEqual(results3[0].Items.Count, 1); Assert.AreEqual(results3[0].Items[0].Id, id); Assert.IsFalse(results3[0].Items[0].Created); Assert.IsTrue(results3[0].Items[0].Success); // create an Id list for the original strongly typed accounts created var idBatch = new SObjectList<SObject>(); idBatch.AddRange(results1[0].Items.Select(result => new SObject { { "Id", result.Id } })); // delete all the strongly typed accounts var results4 = await _client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Delete, new List<SObjectList<SObject>> { idBatch }); Assert.IsTrue(results4 != null, "[results4] empty result object"); Assert.AreEqual(results4.Count, 1, "[results4] wrong number of results"); Assert.AreEqual(results4[0].Items.Count, 3, "[results4] wrong number of result records"); Assert.IsFalse(results4[0].Items[0].Created); Assert.IsTrue(results4[0].Items[0].Success); }
private static async Task RunSample() { var auth = new AuthenticationClient(); // Authenticate with Salesforce Console.WriteLine("Authenticating with Salesforce"); var url = IsSandboxUser.Equals("true", StringComparison.CurrentCultureIgnoreCase) ? "https://test.salesforce.com/services/oauth2/token" : "https://login.salesforce.com/services/oauth2/token"; await auth.UsernamePasswordAsync(ConsumerKey, ConsumerSecret, Username, Password, url); Console.WriteLine("Connected to Salesforce"); // Get a bulk client var client = new ForceClient(auth.InstanceUrl, auth.AccessToken, auth.ApiVersion); // Make a strongly typed Account list var stAccountsBatch = new SObjectList <Account> { new Account { Name = "TestStAccount1" }, new Account { Name = "TestStAccount2" }, new Account { Name = "TestStAccount3" } }; // insert the accounts var results1 = await client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Insert, new List <SObjectList <Account> > { stAccountsBatch }); // (one SObjectList<T> per batch, the example above uses one batch) Console.WriteLine("Strongly typed accounts created"); // Make a dynamic typed Account list var dtAccountsBatch = new SObjectList <SObject> { new SObject { { "Name", "TestDtAccount1" } }, new SObject { { "Name", "TestDtAccount2" } }, new SObject { { "Name", "TestDtAccount3" } } }; // insert the accounts var results2 = await client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Insert, new List <SObjectList <SObject> > { dtAccountsBatch }); Console.WriteLine("Dynamically typed accounts created"); // get the id of the first account created in the first batch var id = results2[0][0].Id; dtAccountsBatch = new SObjectList <SObject> { new SObject { { "Id", id }, { "Name", "TestDtAccount1Renamed" } } }; // update the first accounts name (dont really need bulk for this, just an example) var results3 = await client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Update, new List <SObjectList <SObject> > { dtAccountsBatch }); Console.WriteLine("Account with ID {0} updated", id); // create an Id list for the original strongly typed accounts created var idBatch = new SObjectList <SObject>(); idBatch.AddRange(results1[0].Select(result => new SObject { { "Id", result.Id } })); // delete all the strongly typed accounts var results4 = await client.RunJobAndPollAsync("Account", BulkConstants.OperationType.Delete, new List <SObjectList <SObject> > { idBatch }); Console.WriteLine("Accounts deleted"); }
private static async Task RunSample() { var auth = new AuthenticationClient(); // Authenticate with Salesforce Console.WriteLine("Authenticating with Salesforce"); var url = IsSandboxUser.Equals("true", StringComparison.CurrentCultureIgnoreCase) ? "https://test.salesforce.com/services/oauth2/token" : "https://login.salesforce.com/services/oauth2/token"; await auth.UsernamePasswordAsync(ConsumerKey, ConsumerSecret, Username, Password, url); Console.WriteLine("Connected to Salesforce"); // Get a bulk client var client = new ForceClient(auth.InstanceUrl, auth.AccessToken, auth.ApiVersion); // create a job var jobInfo = await client.CreateJobAsync("Account", BulkConstants.OperationType.Insert); Console.WriteLine("Created a Job"); // Make a dynamic typed Account list var dtAccountsBatch1 = new SObjectList<SObject> { new SObject{{"Name", "TestDtAccount1"}}, new SObject{{"Name", "TestDtAccount2"}}, new SObject{{"MADEUPFIELD", "MADEUPVALUE"}}, new SObject{{"Name", "TestDtAccount3"}} }; // Make a dynamic typed Account list var dtAccountsBatch2 = new SObjectList<SObject> { new SObject{{"Name", "TestDtAccount4"}}, new SObject{{"Name", "TestDtAccount5"}}, new SObject{{"Name", "TestDtAccount6"}} }; // Make a dynamic typed Account list var dtAccountsBatch3 = new SObjectList<SObject> { new SObject{{"MADEUPFIELD", "MADEUPVALUE"}}, new SObject{{"Name", "TestDtAccount7"}}, new SObject{{"Name", "TestDtAccount8"}}, new SObject{{"Name", "TestDtAccount9"}} }; // create the batches var batchInfoList = new List<BatchInfoResult> { await client.CreateJobBatchAsync(jobInfo, dtAccountsBatch1), await client.CreateJobBatchAsync(jobInfo, dtAccountsBatch2), await client.CreateJobBatchAsync(jobInfo, dtAccountsBatch3) }; Console.WriteLine("Created Three Batches"); // poll var pollStart = 1.0f; const float pollIncrease = 2.0f; var completeList = new List<BatchInfoResult>(); while (batchInfoList.Count > 0) { var removeList = new List<BatchInfoResult>(); foreach (var batchInfo in batchInfoList) { var newBatchInfo = await client.PollBatchAsync(batchInfo); if (newBatchInfo.State.Equals(BulkConstants.BatchState.Completed.Value()) || newBatchInfo.State.Equals(BulkConstants.BatchState.Failed.Value()) || newBatchInfo.State.Equals(BulkConstants.BatchState.NotProcessed.Value())) { completeList.Add(newBatchInfo); removeList.Add(batchInfo); } } foreach (var removeInfo in removeList) { batchInfoList.Remove(removeInfo); } await Task.Delay((int) pollStart); pollStart *= pollIncrease; } // get results var results = new List<BatchResultList>(); foreach (var completeBatch in completeList) { results.Add(await client.GetBatchResultAsync(completeBatch)); } Console.WriteLine("All Batches Complete, \"var results\" contains the result objects (Each is a list containing a result for each record):"); foreach (var result in results.SelectMany(resultList => resultList.Items)) { Console.WriteLine("Id:{0}, Created:{1}, Success:{2}, Errors:{3}", result.Id, result.Created, result.Success, result.Errors != null); if (result.Errors != null) { Console.WriteLine("\tErrors:"); var resultErrors = result.Errors; foreach (var field in resultErrors.Fields) { Console.WriteLine("\tField:{0}", field); } Console.WriteLine("\t{0}", resultErrors.Message); Console.WriteLine("\t{0}", resultErrors.StatusCode); } } }