📜 ⬆️ ⬇️

Windows Azure: Blob and Table complement each other

Cloud computing is taking up their positions more and more. More and more people are aware of this fact and are already taking steps to transfer their applications to the “cloud”. It happened with our project, the customer said that he wanted to "soar in the clouds." Because the application was developed on Silverlight, then there was no doubt about the choice of Cloud, and it was decided to use Windows Azure.

Among other tasks in the transition to the "cloud" arose the task of structured storage of application templates. Windows Azure provides several storage capabilities within Windows Azure Storage Services:Queue is clearly not suitable for the current task, so it remains to choose between Blob and Table. We understand further.

At first glance, the Table fits perfectly, but it is only at first glance. We can perform primitive queries and get only those lines that interest us, we can organize a hierarchy of objects, placing in the properties of the record Guid another record. As knowledge in this area deepens, it turns out that each record cannot contain more than 255 fields (which is not critical for us), cannot be more than 1 MB in size (which currently suits us, but during the evolution of the system it can be sideways) and, finally, the size of each property cannot exceed 64 KB, but we cannot put up with this anymore, since at this stage there is already a need to store text up to 300 KB.

And what about the Blob? Blob-s allow storing records with a ridiculous 200 GB size limit for the current task, allows you to structure data by placing it in different containers and using virtual folders, and each Blob can be accompanied by metadata with a total size of 8 KB. It would seem uniquely Blob-s? And no again! We cannot sample Blob-s, no (in any case, we did not find it) the mechanism to search in accordance with any query. You ask: “But what about metadata? After all, you can post information about the structure! ”And you’re almost right, you can, you can get metadata without a Blob content and even a LINQ request to make a selection, but you’ll have to do this after receiving all the metadata of all Blobs in the container. And with a large number of elements it will be a costly operation.
')
So, using Windows Azure you can not solve our problem? Sure you may! And we found a way, maybe it is not perfect, but we are completely satisfied. It was decided to store the data themselves in Blob-ah, and information about the data structure in tables. In this way, we compensate for the disadvantages and use the advantages by using these two technologies in combination.

And finally, some code that will illustrate everything written above. To begin with we will make a class wrapper which will allow to address more simply to Table Storage.
public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  1. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  2. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  3. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  4. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  5. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  6. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  7. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  8. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  9. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  10. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  11. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  12. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  13. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  14. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  15. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  16. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  17. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  18. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  19. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  20. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  21. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  22. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  23. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  24. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  25. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  26. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  27. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  28. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  29. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  30. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  31. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
  32. public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .
public class DynamicTableServiceContext<T> : TableServiceContext where T : TableServiceEntity { private CloudStorageAccount storageAccount; private string tableName; public DynamicTableServiceContext(CloudStorageAccount storageAccount, string tableName) : base (storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials) { this .storageAccount = storageAccount; this .tableName = tableName; var tableStorage = new CloudTableClient(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials); tableStorage.CreateTableIfNotExist(tableName); } public void Add(T entityToAdd) { AddObject(tableName, entityToAdd); SaveChanges(); } public void Update(T entityToUpdate) { UpdateObject(entityToUpdate); SaveChanges(); } public void Delete(T entityToDelete) { DeleteObject(entityToDelete); SaveChanges(); } public IQueryable<T> Load() { return CreateQuery<T>(tableName); } } * This source code was highlighted with Source Code Highlighter .

Next, create the entity entries:
  1. public enum ElementType
  2. {
  3. Obj = 1,
  4. ObjCategory = 2
  5. }
  6. public class BaseObjTableEntity: TableServiceEntity
  7. {
  8. public virtual int Type { get ; set ; }
  9. public string Name { get ; set ; }
  10. }
  11. public class ObjTableEntity: BaseObjTableEntity
  12. {
  13. public string Description { get ; set ; }
  14. public string CategoryId { get ; set ; }
  15. public override int Type
  16. {
  17. get { return ( int ) ElementType.Obj; }
  18. set {}
  19. }
  20. }
  21. public class ObjCategoryTableEntity: BaseObjTableEntity
  22. {
  23. public override int Type
  24. {
  25. get { return ( int ) ElementType.ObjCategory; }
  26. set {}
  27. }
  28. }
* This source code was highlighted with Source Code Highlighter .

In our task, it is necessary to store objects for each user by categories, so it was decided to store objects and categories of objects in one table (and this possibility provides us with Azure Table Storage). In order to distinguish records in a table, objects have a field that stores information about the type of object. For convenience, this is done in the form of enum ElementType. Base class for BaseObjTableEntity entries and classes for categories and objects respectively ObjCategoryTableEntity and ObjTableEntity.

The abstract class TableServiceEntity contains 3 properties: PartitionKey, RowKey, and Timestamp. The first two are used as a composite key, records with the same PartitionKey will always be located within the same server, so it was decided to transfer the user ID to this property. The RowKey in the category is the Guid of the category, and the RowKey of the object is the Guid, which is the name of the Blob. Accordingly, the objects themselves are stored in Blob-ah, to work with them we create a simple class:
  1. public class ObjBlob
  2. {
  3. public string Content { get ; set ; }
  4. public string Name { get ; set ; }
  5. }
* This source code was highlighted with Source Code Highlighter .

And finally, a class to work with all this:
  1. public class ObjAzureRepository
  2. {
  3. private const string ObjContainerName = "objlibrary";
  4. private const string ObjTableName = "ObjLibrary";
  5. private const string DefaultPartitionKey = "Default";
  6. private readonly string userID;
  7. public ObjAzureRepository ( string userId)
  8. {
  9. this .userID = userId;
  10. }
  11. private string azureStorageConnectionString;
  12. protected string AzureStorageConnectionString
  13. {
  14. get
  15. {
  16. if ( string .IsNullOrWhiteSpace (azureStorageConnectionString))
  17. {
  18. azureStorageConnectionString = WebConfigurationManager.ConnectionStrings ["AzureStorageConnectionString"]. ConnectionString;
  19. }
  20. return azureStorageConnectionString;
  21. }
  22. }
  23. private CloudStorageAccount azureStorageAccount;
  24. protected CloudStorageAccount AzureStorageAccount
  25. {
  26. get
  27. {
  28. return azureStorageAccount ?? (azureStorageAccount = CloudStorageAccount.Parse (AzureStorageConnectionString));
  29. }
  30. }
  31. private DynamicTableServiceContext <ObjCategoryTableEntity> categoryContext;
  32. private DynamicTableServiceContext <ObjCategoryTableEntity> CategoryContext
  33. {
  34. get
  35. {
  36. if (categoryContext == null )
  37. {
  38. categoryContext = new DynamicTableServiceContext <ObjCategoryTableEntity> (AzureStorageAccount, ObjTableName);
  39. }
  40. return categoryContext;
  41. }
  42. }
  43. private DynamicTableServiceContext <ObjTableEntity> ObjContext;
  44. private DynamicTableServiceContext <ObjTableEntity> ObjContext
  45. {
  46. get
  47. {
  48. if (ObjContext == null )
  49. {
  50. ObjContext = new DynamicTableServiceContext <ObjTableEntity> (AzureStorageAccount, ObjTableName);
  51. }
  52. return ObjContext;
  53. }
  54. }
  55. public list <ObjCategoryTableEntity> GetObjCategories ()
  56. {
  57. return CategoryContext.Load (). Where <ObjCategoryTableEntity> (e => e.PartitionKey == userID && e.Type == ( int ) ElementType.ObjCategory) .ToList ();
  58. }
  59. public list <ObjTableEntity> GetObjsByCategory (ObjCategoryTableEntity category)
  60. {
  61. return ObjContext.Load (). Where (s => s.PartitionKey == userID && s.CategoryId == category.RowKey && s.Type == ( int ) ElementType.Obj) .ToList ();
  62. }
  63. public ObjBlob GetObjById ( string id)
  64. {
  65. CloudBlobClient client = AzureStorageAccount.CreateCloudBlobClient ();
  66. CloudBlobContainer container = client.GetContainerReference (ObjContainerName);
  67. container.CreateIfNotExist ();
  68. CloudBlob Obj = container.GetBlobReference (id);
  69. return new ObjBlob () {Name = id, Content = Obj.DownloadText ()};
  70. }
  71. public void AddCategory (ObjCategoryTableEntity category)
  72. {
  73. CategoryContext.Add (category);
  74. }
  75. public void ChangeCategory (ObjCategoryTableEntity category)
  76. {
  77. CategoryContext.Update (category);
  78. }
  79. public void RemoveCategory (ObjCategoryTableEntity category)
  80. {
  81. CategoryContext.Delete (category);
  82. }
  83. public void AddObj (ObjTableEntity Obj, string ObjContent)
  84. {
  85. ObjContext.Add (Obj);
  86. CloudBlobClient client = AzureStorageAccount.CreateCloudBlobClient ();
  87. CloudBlobContainer container = client.GetContainerReference (ObjContainerName);
  88. container.CreateIfNotExist ();
  89. CloudBlob ObjBlob = container.GetBlobReference (Obj.RowKey);
  90. ObjBlob.UploadText (ObjContent);
  91. }
  92. public void ChangeObj (ObjTableEntity Obj)
  93. {
  94. ObjContext.Update (Obj);
  95. }
  96. public void RemoveObj (ObjTableEntity Obj)
  97. {
  98. ObjContext.Delete (Obj);
  99. }
  100. }
* This source code was highlighted with Source Code Highlighter .

Working with categories is very trivial, only the method of adding an AddObj object deserves special attention, where in addition to adding a record to the table, Blob is also added with the content of the object, and content can be obtained by its ID.

Thus, we use the advantages of both tables (the ability to sample records on the cloud side), and Blob-s (storage of an element of almost unlimited volume), while bypassing their disadvantages.

In principle, everything that I wanted to share, perhaps, it will seem obvious to someone and he has done it a hundred times already, but for some it will be a good and interesting material and another point in favor of the transition to the “cloud”.

Source: https://habr.com/ru/post/116026/


All Articles