/// <summary> /// Inserts an entity only if a with the same PartitionKey and RowKey does not already exist. /// </summary> /// <param name="item"></param> public TableEntityProxy <T> Insert(T item) { var table = GetTable(); table.CreateIfNotExists(); var wrap = new TableEntityProxy <T>(item) { PartitionKey = PartitionKey(item), RowKey = RowKey(item) }; if (String.IsNullOrEmpty(wrap.PartitionKey)) { throw new ArgumentNullException("PartitionKey", "The partition key function resulted in a null partition key."); } if (String.IsNullOrEmpty(wrap.RowKey)) { throw new ArgumentNullException("RowKey", "The row key function resulted in a null row key."); } var insertOperation = TableOperation.Insert(wrap); table.Execute(insertOperation); return(wrap); }
/// <summary> /// Gets all sequence definitions available. /// </summary> /// <returns></returns> public IEnumerable <SequenceIdStore> GetSequenceIdStores() { var schemas = SchemaTableProxy.QueryPartitions("0", "zzzzz"); var sequences = SequenceTableProxy.QueryPartitions("0", "zzzzz") ?? new List <TableEntityProxy <DynamicTableEntity> >(); var stores = new List <SequenceIdStore>(); foreach (var schema in schemas) { var sequence = sequences.FirstOrDefault(x => String.Equals(schema.Entity.TableName, x.Entity[TableConstants.PartitionKey].StringValue, StringComparison.InvariantCultureIgnoreCase)); if (sequence == null) { sequence = new TableEntityProxy <DynamicTableEntity>(new DynamicTableEntity(schema.PartitionKey, schema.RowKey, "", new Dictionary <string, EntityProperty>())); sequence.Entity.Properties.Add(PropertyFinalCachedId, new EntityProperty(schema.Entity.SeedValue)); SequenceTableProxy.Insert(sequence.Entity); //this could throw if another thread created after SequenceTableProxy.QueryPartitions was called above. } stores.Add(new SequenceIdStore { FinalCachedId = sequence.Entity.Properties[PropertyFinalCachedId].StringValue, Schema = schema.Entity }); } return(stores); }
/// <summary> /// Updates an item on the server if it has not been updated since you last retrieved it. /// </summary> /// <param name="item"></param> /// <param name="eTag">The concurrency eTag supplied when you retrieved the item.</param> public TableEntityProxy <T> Update(T item, Func <T, String> eTag) { var table = GetTable(); if (!table.Exists()) { throw new InvalidOperationException(String.Format("Table '{0}' does not exist. Update not possible.", table.Name)); } var pKey = PartitionKey(item); var rKey = RowKey(item); var retrieveOperation = TableOperation.Retrieve <TableEntityProxy <T> >(pKey, rKey); var retrievedResult = table.Execute(retrieveOperation); if (retrievedResult.Result == null) { throw new InvalidOperationException("The item specified for update does not exist. Try an insert instead."); } var updateEntity = (TableEntityProxy <T>)retrievedResult.Result; if (updateEntity.ETag != eTag(item)) { throw new InvalidOperationException("The item was changed since you retrieved it."); } var wrap = new TableEntityProxy <T>(item) { //Putting ETag on this entity update allows it to replace the item in the table storage. PartitionKey = pKey, RowKey = rKey, ETag = updateEntity.ETag, Timestamp = updateEntity.Timestamp }; if (String.IsNullOrEmpty(wrap.PartitionKey)) { throw new ArgumentNullException("PartitionKey", "The partition key function resulted in a null partition key."); } if (String.IsNullOrEmpty(wrap.RowKey)) { throw new ArgumentNullException("RowKey", "The row key function resulted in a null row key."); } if (String.IsNullOrEmpty(updateEntity.ETag)) { throw new ArgumentNullException("ETag", "An Etag is required on an entity to perform an update."); } var updateOperation = TableOperation.Replace(wrap); table.Execute(updateOperation); return(wrap); }
/// <summary> /// Updates a wrapped item that was retrieved and edited. /// </summary> /// <param name="item"></param> public void Update(TableEntityProxy <T> item) { var table = GetTable(); if (!table.Exists()) { throw new InvalidOperationException(String.Format("Table '{0}' does not exist. Update not possible.", table.Name)); } var update = TableOperation.Replace(item); table.Execute(update); }
/// <summary> /// Deletes an item only if it has not changed since the item was retrieved. /// </summary> /// <param name="item">An item that must have the ETag supplied from a prior retrieval.</param> public void Delete(TableEntityProxy <T> item) { var table = GetTable(); if (!table.Exists()) { throw new InvalidOperationException(String.Format("Table '{0}' does not exist. Delete not possible.", table.Name)); } var deleteOperation = TableOperation.Delete(item); var result = table.Execute(deleteOperation); if (result.HttpStatusCode != 204) //204 = "No Content" = Successful delete per Azure docs { throw new InvalidOperationException(String.Format("Failed to delete {0}. Status Code {1}. {2}", table.Name, result.HttpStatusCode, result.Result)); } }
private TableEntityProxy <DynamicTableEntity> CreateSequenceFromSchema(string tableName) { var schema = SchemaTableProxy.Get(tableName.GetValidPartitionKey(), tableName.GetValidRowKey()); if (schema == null) { throw new ArgumentException(String.Format("Sequence '{0}' is not defined. Cannot get the latest reserved key value.", tableName)); } var sequence = new TableEntityProxy <DynamicTableEntity>(new DynamicTableEntity(schema.PartitionKey, schema.RowKey, "", new Dictionary <string, EntityProperty>())); sequence.Entity.Properties.Add(PropertyFinalCachedId, new EntityProperty(schema.Entity.SeedValue)); SequenceTableProxy.Insert(sequence.Entity); //Insert would throw if another thread created after SequenceTableProxy.Get was called above. Only one thread can create the sequence. // - a lock would not help, since the other thread may be in another role (web or worker) instance return(sequence); }
/// <summary> /// Inserts or Updates an entity whether it is on the server or not. Use this when you don't care about concurrency. /// </summary> /// <param name="item"></param> public TableEntityProxy <T> InsertOrUpdate(T item) { var table = GetTable(); table.CreateIfNotExists(); var pKey = PartitionKey(item); var rKey = RowKey(item); var wrap = new TableEntityProxy <T>(item) { PartitionKey = pKey, RowKey = rKey }; if (String.IsNullOrEmpty(wrap.PartitionKey)) { throw new ArgumentNullException("PartitionKey", "The partition key function resulted in a null partition key."); } if (String.IsNullOrEmpty(wrap.RowKey)) { throw new ArgumentNullException("RowKey", "The row key function resulted in a null row key."); } var retrieveOperation = TableOperation.Retrieve <TableEntityProxy <T> >(pKey, rKey); var retrievedResult = table.Execute(retrieveOperation); if (retrievedResult.Result == null) { var insertOrReplace = TableOperation.InsertOrReplace(wrap); table.Execute(insertOrReplace); return(wrap); } var updateEntity = (TableEntityProxy <T>)retrievedResult.Result; wrap.ETag = updateEntity.ETag; wrap.Timestamp = updateEntity.Timestamp; var updateOperation = TableOperation.InsertOrReplace(wrap); table.Execute(updateOperation); return(wrap); }
/// <summary> /// Insert up to 100 items as a batch. (Azure limit per batch). /// Batches of any larger size are broken into smaller batches. /// </summary> /// <param name="items"></param> public List <TableEntityProxy <T> > InsertBatch(IEnumerable <T> items) { var table = GetTable(); table.CreateIfNotExists(); var batchOperation = new TableBatchOperation(); var wrappedItems = new List <TableEntityProxy <T> >(); Int32 batchSize = 0; foreach (var item in items) { if (batchSize == 100) { //hit max batch size, break it into pieces. table.ExecuteBatch(batchOperation); batchSize = 0; batchOperation = new TableBatchOperation(); } var wrap = new TableEntityProxy <T>(item) { PartitionKey = PartitionKey(item), RowKey = RowKey(item) }; if (String.IsNullOrEmpty(wrap.PartitionKey)) { throw new ArgumentNullException("PartitionKey", "The partition key function resulted in a null partition key."); } if (String.IsNullOrEmpty(wrap.RowKey)) { throw new ArgumentNullException("RowKey", "The row key function resulted in a null row key."); } wrappedItems.Add(wrap); batchOperation.Insert(wrap); batchSize++; } if (batchSize > 0) { table.ExecuteBatch(batchOperation); } return(wrappedItems); }