public async Task UpdateCustomer(CustomerModel customer, CancellationToken cancellation)
        {
            ValidateNoDuplicateLocationKeys(customer.Key, customer.Locations);
            //save the new customer record into the default shard
            var customerPrms = new ParameterCollection()
                               .CreateInputParameters <CustomerModel>(customer, _logger);
            var shardBatch = new ShardBatch <short, List <short> >()
                             .Add(customer.Contacts, "temp_contacts")
                             .Add(customer.Locations, "temp_locations")
                             .Add(Queries.CustomerSave, customerPrms, "contactshardid");
            var shards = await _shardSet[customer.Key].Write.RunAsync(shardBatch, cancellation);

            // if there are any foreign shards, save those records into their respective shard.
            var foreignShards = ShardKey.ShardListForeign(customer.Key.ShardId, customer.Contacts);

            if (foreignShards.Count > 0)
            {
                var contactPrms = new ParameterCollection()
                                  .AddPgSmallintInputParameter("customershardid", customer.Key.ShardId)
                                  .AddPgIntegerInputParameter("customerid", customer.Key.RecordId);
                var setBatch = new ShardSetBatch <short>()
                               .Add(customer.Contacts, "temp_contacts")
                               .Add(Queries.ContactCustomersCreate, contactPrms);
                await _shardSet.Write.RunAsync(setBatch, foreignShards, cancellation);
            }
        }
        public async Task <ShardKey> CreateCustomer(CustomerInputModel customer, CancellationToken cancellation)
        {
            AssignLocationIdSequence(customer.Locations);
            //save the new customer record into the default shard
            var customerPrms = new ParameterCollection()
                               .CreateInputParameters <CustomerInputModel>(customer, _logger)
                               .AddPgSmallintInputParameter("shardid", _shardSet.DefaultShard.ShardId);
            var shardBatch = new ShardBatch <short, ShardKey <short, int> >()
                             .Add(customer.Contacts, "temp_contacts", new MapToPgSmallintAttribute("contactshardid"), new MapToPgIntegerAttribute("contactid"))
                             .Add(customer.Locations, "temp_locations")
                             .Add(Queries.CustomerCreate, customerPrms, DataOrigins.Customer, "newcustomerid");
            var custKey = await _shardSet.DefaultShard.Write.RunAsync(shardBatch, cancellation);

            try
            {   // if there are any foreign shards, save those records into their respective shard.
                var foreignShards = ShardKey.ShardListForeign(custKey.ShardId, customer.Contacts);
                if (foreignShards.Count > 0)
                {
                    var contactPrms = new ParameterCollection()
                                      .AddPgSmallintInputParameter("customershardid", custKey.ShardId)
                                      .AddPgIntegerInputParameter("customerid", custKey.RecordId);
                    var setBatch = new ShardSetBatch <short>()
                                   .Add(customer.Contacts, "temp_contacts", new MapToPgSmallintAttribute("contactshardid"), new MapToPgIntegerAttribute("contactid"))
                                   .Add(Queries.ContactCustomersCreate, contactPrms);
                    await _shardSet.Write.RunAsync(setBatch, foreignShards, cancellation);
                }
                return(custKey);
            }
            catch
            {
                // revert
                await DeleteCustomer(custKey, default(CancellationToken));

                throw;
            }
        }