Line data Source code
1 : #region Copyright
2 : // // -----------------------------------------------------------------------
3 : // // <copyright company="Chinchilla Software Limited">
4 : // // Copyright Chinchilla Software Limited. All rights reserved.
5 : // // </copyright>
6 : // // -----------------------------------------------------------------------
7 : #endregion
8 :
9 : using System;
10 : using System.Collections.Generic;
11 : using cdmdotnet.Logging;
12 : using Cqrs.Azure.BlobStorage;
13 : using Cqrs.Azure.BlobStorage.DataStores;
14 : using Cqrs.Entities;
15 : using Microsoft.WindowsAzure.Storage;
16 : using Microsoft.WindowsAzure.Storage.Table;
17 :
18 : namespace Cqrs.Azure.Storage.DataStores
19 : {
20 : /// <summary>
21 : /// A <see cref="BlobStorage.DataStores.TableStorageDataStore{TData}"/> that uses Azure Storage for storage.
22 : /// </summary>
23 : /// <typeparam name="TData">The <see cref="Type"/> of <see cref="TableEntity"/> Azure Table Storage will contain.</typeparam>
24 : public class TableStorageDataStore<TData>
25 : : BlobStorage.DataStores.TableStorageDataStore<TData>
26 : where TData : Entity
27 1 : {
28 : /// <summary>
29 : /// Initializes a new instance of the <see cref="BlobStorage"/> class using the specified container.
30 : /// </summary>
31 1 : public TableStorageDataStore(ILogger logger, ITableStorageDataStoreConnectionStringFactory tableStorageDataStoreConnectionStringFactory)
32 : : base(logger, tableStorageDataStoreConnectionStringFactory)
33 : {
34 : }
35 :
36 : #region Overrides of TableStorageStore<TData>
37 :
38 : /// <summary>
39 : /// Creates a new instance of <see cref="DynamicTableEntity"/> populating it with the provided <paramref name="data"/>
40 : /// </summary>
41 : /// <param name="data">The data to store in <see cref="DynamicTableEntity.Properties"/>.</param>
42 1 : protected override ITableEntity CreateTableEntity(TData data)
43 : {
44 : var tableEntity = new EntityTableEntity<TData>(data);
45 : //Flatten object of type TData and convert it to EntityProperty Dictionary
46 : #pragma warning disable 0436
47 : Dictionary<string, EntityProperty> flattenedProperties = EntityPropertyConverter.Flatten(data, new OperationContext());
48 : #pragma warning restore 0436
49 : // Create a DynamicTableEntity and set its PK and RK
50 : DynamicTableEntity dynamicTableEntity = new DynamicTableEntity(tableEntity.PartitionKey, tableEntity.RowKey)
51 : {
52 : Properties = flattenedProperties
53 : };
54 :
55 : return dynamicTableEntity;
56 : }
57 :
58 : /// <summary>
59 : /// Gets a <see cref="TableOperation"/> that calls <see cref="TableOperation.Retrieve{DynamicTableEntity}(string,string,System.Collections.Generic.List{string})"/>
60 : /// read for updating.
61 : /// </summary>
62 : /// <param name="data">The data containing the <see cref="IEntity.Rsn"/> property populated.</param>
63 1 : protected override TableOperation GetUpdatableTableEntity(TData data)
64 : {
65 : return TableOperation.Retrieve<DynamicTableEntity>(data.GetType().FullName, data.Rsn.ToString("N"));
66 : }
67 :
68 : #endregion
69 :
70 : #region Overrides of TableStorageStore<EntityTableEntity<TData>,TData>
71 :
72 : /// <summary>
73 : /// Extracts <see cref="TableResult.Result"/> of the provided <paramref name="retrievedResult"/>
74 : /// If <see cref="TableResult.Result"/> is NOT a <see cref="DynamicTableEntity"/> <see cref="TableStorageStore{TData,TCollectionItemData}.ReplaceValues"/> is called.
75 : /// Otherwise <see cref="TableResult.Result"/> is a <see cref="DynamicTableEntity"/>
76 : /// and <see cref="DynamicTableEntity.Properties"/> are replaced with values from <paramref name="data"/>.
77 : /// </summary>
78 : /// <param name="retrievedResult">The existing data to update.</param>
79 : /// <param name="data">The new data to store.</param>
80 1 : protected override ITableEntity ReplaceValues(TableResult retrievedResult, EntityTableEntity<TData> data)
81 : {
82 : ITableEntity tableEntity = (ITableEntity)retrievedResult.Result;
83 : // Events aren't updated
84 : var dynamicTableEntity = tableEntity as DynamicTableEntity;
85 : if (dynamicTableEntity == null)
86 : {
87 : base.ReplaceValues(retrievedResult, data);
88 : return tableEntity;
89 : }
90 :
91 : //Flatten object of type TData and convert it to EntityProperty Dictionary
92 : #pragma warning disable 0436
93 : Dictionary<string, EntityProperty> flattenedProperties = EntityPropertyConverter.Flatten(data.Entity, new OperationContext());
94 : #pragma warning restore 0436
95 : dynamicTableEntity.Properties = flattenedProperties;
96 :
97 : return dynamicTableEntity;
98 : }
99 :
100 : /// <summary>
101 : /// Retrieves the data from Azure Storage
102 : /// If the data is NOT a <see cref="DynamicTableEntity"/> <see cref="TableStorageStore{TData,TCollectionItemData}.GetByKeyAndRow"/> is called.
103 : /// Otherwise <see cref="TableResult.Result"/> is a <see cref="DynamicTableEntity"/>
104 : /// and <see cref="DynamicTableEntity.Properties"/> is converted back to <see cref="EntityTableEntity{TData}"/>.
105 : /// </summary>
106 1 : public override EntityTableEntity<TData> GetByKeyAndRow(Guid rsn)
107 : {
108 : TableOperation searchQuery = TableOperation.Retrieve<DynamicTableEntity>(typeof(TData).FullName, rsn.ToString("N"));
109 :
110 : TableResult searchResult = ReadableSource.Execute(searchQuery);
111 :
112 : var dynamicTableEntity = searchResult.Result as DynamicTableEntity;
113 : if (dynamicTableEntity == null)
114 : return base.GetByKeyAndRow(rsn);
115 :
116 : //Convert the DynamicTableEntity back to original complex object.
117 : #pragma warning disable 0436
118 : TData result = EntityPropertyConverter.ConvertBack<TData>(dynamicTableEntity.Properties, new OperationContext());
119 : #pragma warning restore 0436
120 : return new EntityTableEntity<TData>(result);
121 : }
122 :
123 : /// <summary>
124 : /// Retrieves the data from Azure Storage using <see cref="TableStorageStore{TData,TCollectionItemData}.Collection"/>.
125 : /// </summary>
126 1 : public override IEnumerable<EntityTableEntity<TData>> GetByKey()
127 : {
128 : // Create the table query.
129 : var rangeQuery = Collection.Where
130 : (
131 : TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, StorageStore<object, object>.GetSafeStorageKey(typeof(TData).FullName))
132 : );
133 :
134 : IEnumerable<EntityTableEntity<TData>> results = ReadableSource.ExecuteQuery(rangeQuery);
135 :
136 : return results;
137 : }
138 :
139 : #endregion
140 :
141 : /// <summary>
142 : /// Update the provided <paramref name="data"/> in the data store and persist the change.
143 : /// </summary>
144 1 : public override void Update(TData data)
145 : {
146 : DynamicTableEntity dynamicTableEntity = CreateTableEntity(data) as DynamicTableEntity;
147 : if (dynamicTableEntity == null)
148 : {
149 : base.Update(data);
150 : return;
151 : }
152 : //Convert the DynamicTableEntity back to original complex object.
153 : #pragma warning disable 0436
154 : TData result = EntityPropertyConverter.ConvertBack<TData>(dynamicTableEntity.Properties, new OperationContext());
155 : #pragma warning restore 0436
156 : Update(new EntityTableEntity<TData>(result));
157 : }
158 : }
159 : }
|