public void SingleEntityReplace()
        {
            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 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 SingleEntityDelete()
        {
            CloudTableClient    tableClient = GenerateCloudTableClient();
            TableServiceContext ctx         = tableClient.GetTableServiceContext();

            // Insert Entity
            ComplexEntity insertEntity = new ComplexEntity("insert test", "foo");

            ctx.AddObject(currentTable.Name, insertEntity);
            ctx.SaveChangesWithRetries();

            // Retrieve Entity

            ComplexEntity retrievedEntity = (from ent in ctx.CreateQuery <ComplexEntity>(currentTable.Name)
                                             where ent.PartitionKey == insertEntity.PartitionKey &&
                                             ent.RowKey == insertEntity.RowKey
                                             select ent).AsTableServiceQuery(ctx).Execute().FirstOrDefault();

            Assert.IsNotNull(retrievedEntity);
            ctx.DeleteObject(retrievedEntity);
            ctx.SaveChangesWithRetries();

            try
            {
                // Retrieve Entity
                retrievedEntity = (from ent in ctx.CreateQuery <ComplexEntity>(currentTable.Name)
                                   where ent.PartitionKey == insertEntity.PartitionKey &&
                                   ent.RowKey == insertEntity.RowKey
                                   select ent).AsTableServiceQuery(ctx).Execute().FirstOrDefault();
                Assert.Fail();
            }
            catch (StorageException ex)
            {
                Assert.AreEqual(ex.RequestInformation.HttpStatusCode, (int)HttpStatusCode.NotFound);
            }
        }
Example #3
0
        private void DoBatchInsert(TablePayloadFormat format)
        {
            CloudTableClient    tableClient = GenerateCloudTableClient();
            TableServiceContext ctx         = tableClient.GetTableServiceContext();

            SetPayloadFormatOnDataServiceContext(ctx, format, tableClient);

            // Insert Entities
            SortedDictionary <string, ComplexEntity> entities = new SortedDictionary <string, ComplexEntity>();

            for (int i = 0; i < 100; i++)
            {
                ComplexEntity insertEntity = new ComplexEntity("insert test" + format.ToString(), "foo" + format.ToString() + i);
                entities.Add(insertEntity.RowKey, insertEntity);
                ctx.AddObject(currentTable.Name, insertEntity);
            }

            DataServiceResponse response = ctx.SaveChangesWithRetries(SaveChangesOptions.Batch);

            Assert.AreEqual((int)HttpStatusCode.Accepted, response.BatchStatusCode);

            // Retrieve Entities
            List <ComplexEntity> retrievedEntities = (from ent in ctx.CreateQuery <ComplexEntity>(currentTable.Name)
                                                      where ent.PartitionKey == entities.First().Value.PartitionKey
                                                      select ent).AsTableServiceQuery(ctx).Execute().ToList();

            Assert.AreEqual(entities.Count, retrievedEntities.Count);

            foreach (ComplexEntity retrievedEntity in retrievedEntities)
            {
                ComplexEntity.AssertEquality(entities[retrievedEntity.RowKey], retrievedEntity);
                entities.Remove(retrievedEntity.RowKey);
            }

            Assert.AreEqual(0, entities.Count);
        }
Example #4
0
        private void DoSingleEntityInsertEntityOver1MB(TablePayloadFormat format)
        {
            CloudTableClient    tableClient = GenerateCloudTableClient();
            TableServiceContext ctx         = tableClient.GetTableServiceContext();

            SetPayloadFormatOnDataServiceContext(ctx, format, tableClient);

            // Insert Entity
            ComplexEntity insertEntity = new ComplexEntity("insert test", "foo");

            insertEntity.Binary = new byte[1024 * 1024];
            ctx.AddObject(currentTable.Name, insertEntity);
            OperationContext opContext = new OperationContext();

            try
            {
                ctx.SaveChangesWithRetries(SaveChangesOptions.None, null, opContext);
                Assert.Fail();
            }
            catch (StorageException)
            {
                TestHelper.ValidateResponse(opContext, 1, (int)HttpStatusCode.BadRequest, new string[] { "EntityTooLarge" }, "The entity is larger than the maximum allowed size (1MB).");
            }
        }
Example #5
0
        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 SingleEntityInsertDeleteFail()
        {
            CloudTableClient    tableClient = GenerateCloudTableClient();
            TableServiceContext ctx         = tableClient.GetTableServiceContext();

            // Delete Entity that does not exits
            ComplexEntity deleteEntity = new ComplexEntity("insert test", "foo");

            ctx.AttachTo(currentTable.Name, deleteEntity, "*");
            ctx.DeleteObject(deleteEntity);
            OperationContext opContext = new OperationContext();

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


            ctx = tableClient.GetTableServiceContext();
            TableServiceContext ctx2 = tableClient.GetTableServiceContext();

            // Insert Entity
            ComplexEntity insertEntity = new ComplexEntity("insert test", "foo");

            ctx.AddObject(currentTable.Name, insertEntity);
            ctx.SaveChangesWithRetries();

            // Update Entity
            ComplexEntity retrievedEntity = (from ent in ctx2.CreateQuery <ComplexEntity>(currentTable.Name)
                                             where ent.PartitionKey == insertEntity.PartitionKey &&
                                             ent.RowKey == insertEntity.RowKey
                                             select ent).AsTableServiceQuery(ctx2).Execute().FirstOrDefault();

            retrievedEntity.String = "updated value";

            ctx2.UpdateObject(retrievedEntity);
            ctx2.SaveChangesWithRetries();

            // Now delete old reference with stale etag and validate exception
            ctx.DeleteObject(insertEntity);

            opContext = new OperationContext();
            try
            {
                ctx.SaveChangesWithRetries(SaveChangesOptions.None, 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." });
            }
        }