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