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 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");
        }
        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.");
            }
        }
        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");
        }