public static void MyClassInitialize(TestContext testContext)
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            currentTable = tableClient.GetTableReference(GenerateRandomTableName());
            currentTable.CreateIfNotExists();

            // Populate Entities (This will add 1500 entities to a new table, enough to test continuations 
            TableServiceContext ctx = tableClient.GetTableServiceContext();
            
            for (int l = 0; l < totalTestEntities / 100; l++)
            {
                for (int m = 0; m < 100; m++)
                {
                    BaseEntity ent = new BaseEntity("partition" + l, m.ToString());
                    ent.Randomize();
                    ent.A = ent.RowKey;
                    ctx.AddObject(currentTable.Name, ent);
                }

                ctx.SaveChangesWithRetries(SaveChangesOptions.Batch);
            }
        }
        private void DoSingleEntityReplaceFail(TablePayloadFormat format)
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();
            TableServiceContext secondContext = tableClient.GetTableServiceContext();
            SetPayloadFormatOnDataServiceContext(ctx, format, tableClient);
            SetPayloadFormatOnDataServiceContext(secondContext, format, tableClient);

            // Insert Entity
            BaseEntity baseEntity = new BaseEntity("insert test", "foo" + format.ToString());
            baseEntity.Randomize();
            ctx.AddObject(currentTable.Name, baseEntity);
            ctx.SaveChangesWithRetries();
            string etag = ctx.Entities.First().ETag;
            baseEntity.A = "updated";
            ctx.UpdateObject(baseEntity);
            ctx.SaveChangesWithRetries();

            MergeEntity replaceEntity = new MergeEntity(baseEntity.PartitionKey, baseEntity.RowKey);
            replaceEntity.Randomize();
            secondContext.AttachTo(currentTable.Name, replaceEntity, etag);
            secondContext.UpdateObject(replaceEntity);
            OperationContext opContext = new OperationContext();

            try
            {
                secondContext.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate, null, opContext);
                Assert.Fail();
            }
            catch (StorageException)
            {
                TestHelper.ValidateResponse(opContext,
                       1,
                       (int)HttpStatusCode.PreconditionFailed,
                       new string[] { "UpdateConditionNotSatisfied", "ConditionNotMet" },
                       new string[] { "The update condition specified in the request was not satisfied.", "The condition specified using HTTP conditional header(s) is not met." });
            }

            ctx.DeleteObject(baseEntity);
            ctx.SaveChangesWithRetries();

            opContext = new OperationContext();

            // try merging with deleted entity
            try
            {
                secondContext.SaveChangesWithRetries(SaveChangesOptions.None, null, opContext);
                Assert.Fail();
            }
            catch (StorageException)
            {
                TestHelper.ValidateResponse(opContext, 1, (int)HttpStatusCode.NotFound, new string[] { "ResourceNotFound" }, "The specified resource does not exist.");
            }
        }
        private void DoSingleEntityReplace(TablePayloadFormat format)
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();
            TableServiceContext queryContext = tableClient.GetTableServiceContext();
            SetPayloadFormatOnDataServiceContext(ctx, format, tableClient);
            SetPayloadFormatOnDataServiceContext(queryContext, format, tableClient);

            // Insert Entity
            BaseEntity baseEntity = new BaseEntity("insert test", "foo" + format.ToString());
            baseEntity.Randomize();
            ctx.AddObject(currentTable.Name, baseEntity);
            ctx.SaveChangesWithRetries();
            string etag = ctx.Entities.First().ETag;
            ctx.Detach(baseEntity);

            MergeEntity replaceEntity = new MergeEntity(baseEntity.PartitionKey, baseEntity.RowKey);
            replaceEntity.Randomize();
            ctx.AttachTo(currentTable.Name, replaceEntity, etag);
            ctx.UpdateObject(replaceEntity);
            ctx.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate);

            // Retrieve Entity
            UnionEnitity retrievedEntity = (from ent in queryContext.CreateQuery<UnionEnitity>(currentTable.Name)
                                            where ent.PartitionKey == baseEntity.PartitionKey
                                            && ent.RowKey == baseEntity.RowKey
                                            select ent).AsTableServiceQuery(queryContext).Execute().FirstOrDefault();

            Assert.IsNotNull(retrievedEntity);
            Assert.AreEqual(null, retrievedEntity.A);
            Assert.AreEqual(null, retrievedEntity.B);
            Assert.AreEqual(null, retrievedEntity.C);
            Assert.AreEqual(replaceEntity.D, retrievedEntity.D);
            Assert.AreEqual(replaceEntity.E, retrievedEntity.E);
            Assert.AreEqual(replaceEntity.F, retrievedEntity.F);
        }
        public void SingleEntityInsertOrReplaceTask()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();
            TableServiceContext queryContext = tableClient.GetTableServiceContext();
            queryContext.MergeOption = MergeOption.NoTracking;

            // Insert Entity
            BaseEntity baseEntity = new BaseEntity("insert test", "foo");

            // Insert Or Merge with no pre-existing entity
            MergeEntity insertOrReplaceEntity = new MergeEntity(baseEntity.PartitionKey, baseEntity.RowKey);
            insertOrReplaceEntity.Randomize();
            ctx.AttachTo(currentTable.Name, insertOrReplaceEntity, null);
            ctx.UpdateObject(insertOrReplaceEntity);
            ctx.SaveChangesWithRetriesAsync(SaveChangesOptions.ReplaceOnUpdate).Wait();
            ctx.Detach(insertOrReplaceEntity);

            // Retrieve Entity & Verify Contents
            UnionEnitity retrievedEntity = (from ent in queryContext.CreateQuery<UnionEnitity>(currentTable.Name)
                                            where ent.PartitionKey == baseEntity.PartitionKey
                                            && ent.RowKey == baseEntity.RowKey
                                            select ent).AsTableServiceQuery(queryContext).Execute().FirstOrDefault();

            Assert.IsNotNull(retrievedEntity);
            Assert.AreEqual(null, retrievedEntity.A);
            Assert.AreEqual(null, retrievedEntity.B);
            Assert.AreEqual(null, retrievedEntity.C);
            Assert.AreEqual(insertOrReplaceEntity.D, retrievedEntity.D);
            Assert.AreEqual(insertOrReplaceEntity.E, retrievedEntity.E);
            Assert.AreEqual(insertOrReplaceEntity.F, retrievedEntity.F);

            BaseEntity replacedEntity = new BaseEntity("insert test", "foo");
            replacedEntity.Randomize();

            ctx.AttachTo(currentTable.Name, replacedEntity, null);
            ctx.UpdateObject(replacedEntity);
            ctx.SaveChangesWithRetriesAsync(SaveChangesOptions.ReplaceOnUpdate).Wait();

            // Retrieve Entity & Verify
            retrievedEntity = (from ent in queryContext.CreateQuery<UnionEnitity>(currentTable.Name)
                               where ent.PartitionKey == baseEntity.PartitionKey
                               && ent.RowKey == baseEntity.RowKey
                               select ent).AsTableServiceQuery(queryContext).Execute().FirstOrDefault();

            Assert.IsNotNull(retrievedEntity);
            Assert.AreEqual(replacedEntity.A, retrievedEntity.A);
            Assert.AreEqual(replacedEntity.B, retrievedEntity.B);
            Assert.AreEqual(replacedEntity.C, retrievedEntity.C);
            Assert.AreEqual(null, retrievedEntity.D);
            Assert.AreEqual(null, retrievedEntity.E);
            Assert.AreEqual(null, retrievedEntity.F);
        }
        public void TableServiceContextSaveChangeWithRetriesAPM()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();

            // Get data context.
            TableServiceContext context = tableClient.GetTableServiceContext();

            // Create the new entity.
            BaseEntity entity = new BaseEntity("Hello", "world.");

            using (AutoResetEvent waitHandle = new AutoResetEvent(false))
            {
                // Add the entity.
                context.AttachTo(this.currentTable.Name, entity);
                context.UpdateObject(entity);
                
                // Save changes to the service.
                IAsyncResult result = context.BeginSaveChangesWithRetries(ar => waitHandle.Set(), null);
                waitHandle.WaitOne();
                context.EndSaveChangesWithRetries(result);

                BaseEntity entity2 = new BaseEntity("Insert", "foo.");
                context.AttachTo(this.currentTable.Name, entity2);
                context.UpdateObject(entity2);

                // Test again with different parameters
                result = context.BeginSaveChangesWithRetries(SaveChangesOptions.None, ar => waitHandle.Set(), null);
                waitHandle.WaitOne();
                context.EndSaveChangesWithRetries(result);

                // Retrieve Entities & Verify
                BaseEntity retrievedEntity = (from ent in context.CreateQuery<BaseEntity>(currentTable.Name)
                                              where
                                                  ent.PartitionKey == entity2.PartitionKey
                                                  && ent.RowKey == entity2.RowKey
                                              select ent).AsTableServiceQuery(context).Execute().FirstOrDefault();

                Assert.IsNotNull(retrievedEntity);

                retrievedEntity = (from ent in context.CreateQuery<BaseEntity>(currentTable.Name)
                                              where
                                                  ent.PartitionKey == entity.PartitionKey
                                                  && ent.RowKey == entity.RowKey
                                              select ent).AsTableServiceQuery(context).Execute().FirstOrDefault();

                Assert.IsNotNull(retrievedEntity);
            }

            // Test Dispose
            context.Dispose();
        }
        private void DoSingleEntityInsertOrMerge(TablePayloadFormat format)
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();
            TableServiceContext queryContext = tableClient.GetTableServiceContext();
            SetPayloadFormatOnDataServiceContext(ctx, format, tableClient);
            SetPayloadFormatOnDataServiceContext(queryContext, format, tableClient);

            // Insert Entity
            BaseEntity baseEntity = new BaseEntity("insert test", "foo" + format.ToString());

            // Insert Or Merge with no pre-existing entity
            MergeEntity insertOrMergeEntity = new MergeEntity(baseEntity.PartitionKey, baseEntity.RowKey);
            insertOrMergeEntity.Randomize();
            ctx.AttachTo(currentTable.Name, insertOrMergeEntity, null);
            ctx.UpdateObject(insertOrMergeEntity);
            ctx.SaveChangesWithRetries();
            ctx.Detach(insertOrMergeEntity);

            // Retrieve Entity & Verify Contents
            UnionEnitity retrievedEntity = (from ent in queryContext.CreateQuery<UnionEnitity>(currentTable.Name)
                                            where ent.PartitionKey == baseEntity.PartitionKey
                                            && ent.RowKey == baseEntity.RowKey
                                            select ent).AsTableServiceQuery(ctx).Execute().FirstOrDefault();

            Assert.IsNotNull(retrievedEntity);
            Assert.AreEqual(insertOrMergeEntity.D, retrievedEntity.D);
            Assert.AreEqual(insertOrMergeEntity.E, retrievedEntity.E);
            Assert.AreEqual(insertOrMergeEntity.F, retrievedEntity.F);

            UnionEnitity mergedEntity = new UnionEnitity("insert test", "foo" + format.ToString());
            mergedEntity.Randomize();
            mergedEntity.D = insertOrMergeEntity.D;
            mergedEntity.E = insertOrMergeEntity.E;
            mergedEntity.F = insertOrMergeEntity.F;

            ctx.AttachTo(currentTable.Name, mergedEntity, null);
            ctx.UpdateObject(mergedEntity);
            ctx.SaveChangesWithRetries();
            ctx.Detach(mergedEntity);

            // Retrieve Entity & Verify
            retrievedEntity = (from ent in queryContext.CreateQuery<UnionEnitity>(currentTable.Name)
                               where ent.PartitionKey == baseEntity.PartitionKey
                               && ent.RowKey == baseEntity.RowKey
                               select ent).AsTableServiceQuery(queryContext).Execute().FirstOrDefault();

            Assert.IsNotNull(retrievedEntity);
            Assert.AreEqual(mergedEntity.A, retrievedEntity.A);
            Assert.AreEqual(mergedEntity.B, retrievedEntity.B);
            Assert.AreEqual(mergedEntity.C, retrievedEntity.C);
            Assert.AreEqual(mergedEntity.D, retrievedEntity.D);
            Assert.AreEqual(mergedEntity.E, retrievedEntity.E);
            Assert.AreEqual(mergedEntity.F, retrievedEntity.F);
        }
        public void TableServiceContextTimeoutDuringSaveChangesNonBatchAPM()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();

            for (int m = 0; m < 100; m++)
            {
                BaseEntity ent = new BaseEntity("testpartition", m.ToString());
                ent.Randomize();
                ent.A = ent.RowKey;
                ctx.AddObject(currentTable.Name, ent);
            }

            OperationContext opContext = new OperationContext();
            TableRequestOptions requestOptions = new TableRequestOptions() { MaximumExecutionTime = TimeSpan.FromSeconds(5) };

            using (HttpMangler proxy = new HttpMangler(false,
                new[] { DelayBehaviors.DelayAllRequestsIf(2000, XStoreSelectors.TableTraffic().IfHostNameContains(tableClient.Credentials.AccountName).SkipNSessions(10)) }))
            {
                try
                {
                    using (ManualResetEvent evt = new ManualResetEvent(false))
                    {
                        IAsyncResult result = ctx.BeginSaveChangesWithRetries(SaveChangesOptions.None, requestOptions, opContext,
                            (res) =>
                            {
                                result = res;
                                evt.Set();
                            }, null);

                        evt.WaitOne();

                        ctx.EndSaveChangesWithRetries(result);
                    }

                    ctx.SaveChangesWithRetries(SaveChangesOptions.None, requestOptions, opContext);
                }
                catch (StorageException ex)
                {
                    Assert.AreEqual(ex.RequestInformation.HttpStatusCode, (int)HttpStatusCode.RequestTimeout);
                    Assert.AreEqual("The client could not finish the operation within specified timeout.", ex.Message);
                    Assert.IsTrue(ex.InnerException is TimeoutException);
                }
            }
        }
        public void TableServiceContextConcurrencyAllowsOnlySingleOperationAtOnce()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext tableContext = tableClient.GetTableServiceContext();

            // insert entities to query against
            for (int i = 0; i < 5; i++)
            {
                for (int m = 0; m < 100; m++)
                {
                    BaseEntity ent = new BaseEntity("testpartition" + i, m.ToString());
                    ent.Randomize();
                    ent.A = ent.RowKey;
                    tableContext.AddObject(currentTable.Name, ent);
                }

                tableContext.SaveChangesWithRetries(SaveChangesOptions.Batch);
            }

            List<OperationContext> opContexts = new List<OperationContext>();
            object lockerObj = new object();
            DateTime start = DateTime.Now;

            int threadsRunning = 0;

            Exception lastEx = null;

            // Start 10 simultaneous threads to query entities associated with same context.
            for (int j = 0; j < 10; j++)
            {
                opContexts.Add(new OperationContext());
                Thread newThread = new Thread((arg) =>
                {
                    Interlocked.Increment(ref threadsRunning);
                    try
                    {
                        lock (lockerObj)
                        {
                            Monitor.Wait(lockerObj);
                        }

                        TableServiceQuery<BaseEntity> query = (from ent in tableContext.CreateQuery<BaseEntity>(currentTable.Name)
                                                               select ent).AsTableServiceQuery(tableContext);

                        Debug.WriteLine(String.Format("Thread {0} start operation @ {1}", Thread.CurrentThread.ManagedThreadId, (DateTime.Now - start).TotalMilliseconds));

                        try
                        {
                            query.Execute(null, arg as OperationContext).ToList();
                        }
                        catch (Exception)
                        {
                            // no op, expected to have some exceptions
                        }

                        Debug.WriteLine(String.Format("Thread {0} end operation @ {1}", Thread.CurrentThread.ManagedThreadId, (DateTime.Now - start).TotalMilliseconds));
                    }
                    catch (Exception ex)
                    {
                        lastEx = ex;
                    }
                    finally
                    {
                        Interlocked.Decrement(ref threadsRunning);
                    }
                });

                newThread.Start(opContexts[j]);
            }

            // Wait for all threads to start
            while (Interlocked.CompareExchange(ref threadsRunning, 10, 10) < 10)
            {
                Thread.Sleep(200);
            }

            // pulse all threads
            lock (lockerObj)
            {
                Monitor.PulseAll(lockerObj);
            }

            // Wait for all threads to complete
            while (Interlocked.CompareExchange(ref threadsRunning, -1, 0) > -1)
            {
                Thread.Sleep(200);
            }

            if (lastEx != null)
            {
                throw lastEx;
            }

            foreach (OperationContext opContext in opContexts)
            {
                if (opContext.LastResult == null || opContext.LastResult.StartTime == null || opContext.LastResult.EndTime == null)
                    continue;

                TestHelper.AssertNAttempts(opContext, 1);

                RequestResult currRes = opContext.LastResult;

                // Make sure this results start time does not occur in between any other results start & end time
                var overlappingResults = (from ctx in opContexts
                                          where ctx.LastResult != null && ctx.LastResult != currRes &&
                                          ctx.LastResult.StartTime != null && ctx.LastResult.EndTime != null &&
                                          ctx.LastResult.StartTime.Ticks < currRes.StartTime.Ticks &&
                                          ctx.LastResult.EndTime.Ticks > currRes.StartTime.Ticks
                                          select ctx.LastResult);

                Assert.AreEqual(overlappingResults.Count(), 0, "Detected overlapping query");
            }
        }
        public void TableServiceContextOperationContextEventsAPM()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();

            for (int m = 0; m < 10; m++)
            {
                BaseEntity ent = new BaseEntity("testpartition", m.ToString());
                ent.Randomize();
                ent.A = ent.RowKey;
                ctx.AddObject(currentTable.Name, ent);
            }

            List<string> sends = new List<string>();
            List<string> receives = new List<string>();

            OperationContext opContext = new OperationContext();
            opContext.SendingRequest += (sender, args) => sends.Add(args.RequestInformation.StartTime.Ticks.ToString());
            opContext.ResponseReceived += (sender, args) => receives.Add(args.RequestInformation.ServiceRequestID);

            using (ManualResetEvent evt = new ManualResetEvent(false))
            {
                ctx.BeginSaveChangesWithRetries(SaveChangesOptions.None, null, opContext,
                    (res) =>
                    {
                        ctx.EndSaveChangesWithRetries(res);
                        evt.Set();
                    }, null);
                evt.WaitOne();
            }

            TestHelper.AssertNAttempts(opContext, 10);

            Assert.AreEqual(sends.Count(), 10);
            Assert.AreEqual(receives.Count(), 10);
        }
        public void TableServiceContextRequestResultsAPM()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();

            for (int m = 0; m < 10; m++)
            {
                BaseEntity ent = new BaseEntity("testpartition", m.ToString());
                ent.Randomize();
                ent.A = ent.RowKey;
                ctx.AddObject(currentTable.Name, ent);
            }

            OperationContext opContext = new OperationContext();

            using (ManualResetEvent evt = new ManualResetEvent(false))
            {
                ctx.BeginSaveChangesWithRetries(SaveChangesOptions.None, null, opContext,
                    (res) =>
                    {
                        ctx.EndSaveChangesWithRetries(res);
                        evt.Set();
                    }, null);
                evt.WaitOne();
            }

            TestHelper.AssertNAttempts(opContext, 10);
        }
        public void TableServiceContextRequestResultsSync()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();

            for (int m = 0; m < 10; m++)
            {
                BaseEntity ent = new BaseEntity("testpartition", m.ToString());
                ent.Randomize();
                ent.A = ent.RowKey;
                ctx.AddObject(currentTable.Name, ent);
            }

            OperationContext opContext = new OperationContext();

            ctx.SaveChangesWithRetries(SaveChangesOptions.None, null, opContext);

            TestHelper.AssertNAttempts(opContext, 10);
        }
        /// <summary>
        /// Test a table operation on entities inside and outside the given range.
        /// </summary>
        /// <param name="tableName">The name of the table to test.</param>
        /// <param name="startPk">The start partition key range.</param>
        /// <param name="startRk">The start row key range.</param>
        /// <param name="endPk">The end partition key range.</param>
        /// <param name="endRk">The end row key range.</param>
        /// <param name="runOperationDelegate">A delegate with the table operation to test.</param>
        /// <param name="opName">The name of the operation being tested.</param>
        /// <param name="expectSuccess">Whether the operation should succeed on entities within the range.</param>
        private void TestOperationWithRange(
            string tableName,
            string startPk,
            string startRk,
            string endPk,
            string endRk,
            Action<BaseEntity> runOperationDelegate,
            string opName,
            bool expectSuccess,
            HttpStatusCode expectedStatusCode,
            bool isRangeQuery)
        {
            CloudTableClient referenceClient = GenerateCloudTableClient();
            TableServiceContext referenceContext = referenceClient.GetTableServiceContext();

            string partitionKey = startPk ?? endPk ?? "M";
            string rowKey = startRk ?? endRk ?? "S";

            // if we expect a success for creation - avoid inserting duplicate entities
            BaseEntity tableEntity = new BaseEntity(partitionKey, rowKey);
            if (expectedStatusCode == HttpStatusCode.Created)
            {
                referenceContext.AttachTo(tableName, tableEntity, "*");
                referenceContext.DeleteObject(tableEntity);
                try
                {
                    referenceContext.SaveChangesWithRetries();
                }
                catch (Exception)
                {
                }
            }
            else
            {
                // only for add we should not be adding the entity
                referenceContext.AttachTo(tableName, tableEntity);
                referenceContext.UpdateObject(tableEntity);
                referenceContext.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate);
            }

            if (expectSuccess)
            {
                runOperationDelegate(tableEntity);
            }
            else
            {
                TestHelper.ExpectedException(
                    () => runOperationDelegate(tableEntity),
                    string.Format("{0} without appropriate permission.", opName),
                    HttpStatusCode.NotFound);
            }

            if (startPk != null)
            {
                tableEntity.PartitionKey = "A";
                if (startPk.CompareTo(tableEntity.PartitionKey) <= 0)
                {
                    Assert.Inconclusive("Test error: partition key for this test must not be less than or equal to \"A\"");
                }

                TestHelper.ExpectedException(
                    () => runOperationDelegate(tableEntity),
                    string.Format("{0} before allowed partition key range", opName),
                    HttpStatusCode.NotFound);
                tableEntity.PartitionKey = partitionKey;
            }

            if (endPk != null)
            {
                tableEntity.PartitionKey = "Z";
                if (endPk.CompareTo(tableEntity.PartitionKey) >= 0)
                {
                    Assert.Inconclusive("Test error: partition key for this test must not be greater than or equal to \"Z\"");
                }

                TestHelper.ExpectedException(
                    () => runOperationDelegate(tableEntity),
                    string.Format("{0} after allowed partition key range", opName),
                    HttpStatusCode.NotFound);

                tableEntity.PartitionKey = partitionKey;
            }

            if (startRk != null)
            {
                if (isRangeQuery || startPk != null)
                {
                    tableEntity.PartitionKey = startPk;
                    tableEntity.RowKey = "A";
                    if (startRk.CompareTo(tableEntity.RowKey) <= 0)
                    {
                        Assert.Inconclusive("Test error: row key for this test must not be less than or equal to \"A\"");
                    }

                    TestHelper.ExpectedException(
                        () => runOperationDelegate(tableEntity),
                        string.Format("{0} before allowed row key range", opName),
                        HttpStatusCode.NotFound);

                    tableEntity.RowKey = rowKey;
                }
            }

            if (endRk != null)
            {
                if (isRangeQuery || endPk != null)
                {
                    tableEntity.PartitionKey = endPk;
                    tableEntity.RowKey = "Z";
                    if (endRk.CompareTo(tableEntity.RowKey) >= 0)
                    {
                        Assert.Inconclusive("Test error: row key for this test must not be greater than or equal to \"Z\"");
                    }

                    TestHelper.ExpectedException(
                        () => runOperationDelegate(tableEntity),
                        string.Format("{0} after allowed row key range", opName),
                        HttpStatusCode.NotFound);

                    tableEntity.RowKey = rowKey;
                }
            }
        }
        public void TableServiceContextOperationContextStartEndTimeAPM()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();

            DateTime start = DateTime.Now;
            for (int m = 0; m < 10; m++)
            {
                BaseEntity ent = new BaseEntity("testpartition", m.ToString());
                ent.Randomize();
                ent.A = ent.RowKey;
                ctx.AddObject(currentTable.Name, ent);
            }


            OperationContext opContext = new OperationContext();
            using (ManualResetEvent evt = new ManualResetEvent(false))
            {
                ctx.BeginSaveChangesWithRetries(SaveChangesOptions.None, null, opContext,
                    (res) =>
                    {
                        ctx.EndSaveChangesWithRetries(res);
                        evt.Set();
                    }, null);
                evt.WaitOne();
            }

            Assert.IsNotNull(opContext.StartTime, "StartTime not set");
            Assert.IsTrue(opContext.StartTime >= start, "StartTime not set correctly");
            Assert.IsNotNull(opContext.EndTime, "EndTime not set");
            Assert.IsTrue(opContext.EndTime <= DateTime.Now, "EndTime not set correctly");
        }
        public void SingleEntityMerge()
        {
            CloudTableClient tableClient = GenerateCloudTableClient();
            TableServiceContext ctx = tableClient.GetTableServiceContext();
            TableServiceContext queryContext = tableClient.GetTableServiceContext();

            // Insert Entity
            BaseEntity baseEntity = new BaseEntity("insert test", "foo");
            baseEntity.Randomize();
            ctx.AddObject(currentTable.Name, baseEntity);
            ctx.SaveChangesWithRetries();
            string etag = ctx.Entities.First().ETag;
            ctx.Detach(baseEntity);

            MergeEntity mergeEntity = new MergeEntity(baseEntity.PartitionKey, baseEntity.RowKey);
            mergeEntity.Randomize();
            ctx.AttachTo(currentTable.Name, mergeEntity, etag);
            ctx.UpdateObject(mergeEntity);
            ctx.SaveChangesWithRetries();

            // Retrieve Entity
            UnionEnitity retrievedEntity = (from ent in queryContext.CreateQuery<UnionEnitity>(currentTable.Name)
                                            where ent.PartitionKey == baseEntity.PartitionKey
                                            && ent.RowKey == baseEntity.RowKey
                                            select ent).AsTableServiceQuery(queryContext).Execute().FirstOrDefault();

            Assert.IsNotNull(retrievedEntity);
            Assert.AreEqual(baseEntity.A, retrievedEntity.A);
            Assert.AreEqual(baseEntity.B, retrievedEntity.B);
            Assert.AreEqual(baseEntity.C, retrievedEntity.C);
            Assert.AreEqual(mergeEntity.D, retrievedEntity.D);
            Assert.AreEqual(mergeEntity.E, retrievedEntity.E);
            Assert.AreEqual(mergeEntity.F, retrievedEntity.F);
        }