@@ -5,21 +5,22 @@ namespace Microsoft.AspNet.OutputCache.CosmosDBTableAsyncOutputCacheProvider {
55 using System ;
66 using System . Collections . Specialized ;
77 using System . Configuration ;
8+ using System . Runtime . Caching ;
89 using System . Threading . Tasks ;
910 using System . Web ;
10- using Microsoft . Azure . CosmosDB . Table ;
11- using Microsoft . Azure . Storage ;
11+ using Azure ;
12+ using Azure . Data . Tables ;
1213 using Resource ;
1314
1415 class CosmosDBTableOutputCacheRepository : ITableOutputCacheRepository {
1516 private const string TableNameKey = "tableName" ;
1617 private const string ConnectionStringKey = "connectionStringName" ;
1718 private const string FixedPartitionKey = "P" ;
1819
19- private CloudTable _table ;
20- private string _connectionString ;
21- private string _tableName ;
22- private object _lock = new object ( ) ;
20+ private TableClient _tableClient ;
21+ private readonly string _connectionString ;
22+ private readonly string _tableName ;
23+ private readonly object _lock = new object ( ) ;
2324
2425 public CosmosDBTableOutputCacheRepository ( NameValueCollection providerConfig , NameValueCollection appSettings ) {
2526 var connectionStringName = providerConfig [ ConnectionStringKey ] ;
@@ -39,9 +40,7 @@ public CosmosDBTableOutputCacheRepository(NameValueCollection providerConfig, Na
3940 }
4041
4142 public object Add ( string key , object entry , DateTime utcExpiry ) {
42- var retrieveOp = TableOperationHelper . Retrieve ( key ) ;
43- var retrieveResult = _table . Execute ( retrieveOp ) ;
44- var existingCacheEntry = retrieveResult . Result as CacheEntity ;
43+ CacheEntity existingCacheEntry = Get ( key ) as CacheEntity ;
4544
4645 if ( existingCacheEntry != null && existingCacheEntry . UtcExpiry > DateTime . UtcNow ) {
4746 return existingCacheEntry . CacheItem ;
@@ -54,9 +53,7 @@ public object Add(string key, object entry, DateTime utcExpiry) {
5453 public async Task < object > AddAsync ( string key , object entry , DateTime utcExpiry ) {
5554 // If there is already a value in the cache for the specified key, the provider must return that value if not expired
5655 // and must not store the data passed by using the Add method parameters.
57- var retrieveOp = TableOperationHelper . Retrieve ( key ) ;
58- var retrieveResult = await _table . ExecuteAsync ( retrieveOp ) ;
59- var existingCacheEntry = retrieveResult . Result as CacheEntity ;
56+ CacheEntity existingCacheEntry = await GetAsync ( key ) as CacheEntity ;
6057
6158 if ( existingCacheEntry != null && existingCacheEntry . UtcExpiry > DateTime . UtcNow ) {
6259 return existingCacheEntry . CacheItem ;
@@ -67,88 +64,85 @@ public async Task<object> AddAsync(string key, object entry, DateTime utcExpiry)
6764 }
6865
6966 public object Get ( string key ) {
70- var retrieveOp = TableOperationHelper . Retrieve ( key ) ;
71- var retrieveResult = _table . Execute ( retrieveOp ) ;
72- var existingCacheEntry = retrieveResult . Result as CacheEntity ;
73-
74- if ( existingCacheEntry != null && existingCacheEntry . UtcExpiry < DateTime . UtcNow ) {
75- Remove ( key ) ;
76- return null ;
77- } else {
78- return existingCacheEntry ? . CacheItem ;
67+ try
68+ {
69+ CacheEntity existingCacheEntry = _tableClient . GetEntity < CacheEntity > ( CacheEntity . GeneratePartitionKey ( key ) , CacheEntity . SanitizeKey ( key ) ) ;
70+
71+ if ( existingCacheEntry != null && existingCacheEntry . UtcExpiry < DateTime . UtcNow ) {
72+ Remove ( key ) ;
73+ return null ;
74+ } else {
75+ return existingCacheEntry ? . CacheItem ;
76+ }
7977 }
78+ catch ( RequestFailedException rfe ) when ( rfe . Status == 404 ) { /* Entity not found */ }
79+ return null ;
8080 }
8181
8282 public async Task < object > GetAsync ( string key ) {
83- // Outputcache module will always first call GetAsync
84- // so only calling EnsureTableInitializedAsync here is good enough
85- await EnsureTableInitializedAsync ( ) ;
8683
87- var retrieveOp = TableOperationHelper . Retrieve ( key ) ;
88- var retrieveResult = await _table . ExecuteAsync ( retrieveOp ) ;
89- var existingCacheEntry = retrieveResult . Result as CacheEntity ;
84+ try
85+ {
86+ // Outputcache module will always first call GetAsync
87+ // so only calling EnsureTableInitializedAsync here is good enough
88+ await EnsureTableInitializedAsync ( ) ;
9089
91- if ( existingCacheEntry != null && existingCacheEntry . UtcExpiry < DateTime . UtcNow ) {
92- await RemoveAsync ( key ) ;
93- return null ;
94- } else {
95- return existingCacheEntry ? . CacheItem ;
90+ CacheEntity existingCacheEntry = await _tableClient . GetEntityAsync < CacheEntity > ( CacheEntity . GeneratePartitionKey ( key ) , CacheEntity . SanitizeKey ( key ) ) ;
91+
92+ if ( existingCacheEntry != null && existingCacheEntry . UtcExpiry < DateTime . UtcNow ) {
93+ await RemoveAsync ( key ) ;
94+ return null ;
95+ } else {
96+ return existingCacheEntry ? . CacheItem ;
97+ }
9698 }
99+ catch ( RequestFailedException rfe ) when ( rfe . Status == 404 ) { /* Entity not found */ }
100+ return null ;
97101 }
98102
99103 public void Remove ( string key ) {
100- var removeOp = TableOperationHelper . Delete ( key ) ;
101- _table . Execute ( removeOp ) ;
104+ _tableClient . DeleteEntity ( CacheEntity . GeneratePartitionKey ( key ) , CacheEntity . SanitizeKey ( key ) , ETag . All ) ;
102105 }
103106
104107 public async Task RemoveAsync ( string key ) {
105- var removeOp = TableOperationHelper . Delete ( key ) ;
106- await _table . ExecuteAsync ( removeOp ) ;
108+ await _tableClient . DeleteEntityAsync ( CacheEntity . GeneratePartitionKey ( key ) , CacheEntity . SanitizeKey ( key ) , ETag . All ) ;
107109 }
108110
109111 public void Set ( string key , object entry , DateTime utcExpiry ) {
110- var insertOp = TableOperationHelper . InsertOrReplace ( key , entry , utcExpiry ) ;
111- _table . Execute ( insertOp ) ;
112+ _tableClient . UpsertEntity < CacheEntity > ( new CacheEntity ( key , entry , utcExpiry ) ) ;
112113 }
113114
114115 public async Task SetAsync ( string key , object entry , DateTime utcExpiry ) {
115116 //Check if the key is already in database
116117 //If there is already a value in the cache for the specified key, the Set method will update it.
117118 //Otherwise it will insert the entry.
118- var insertOp = TableOperationHelper . InsertOrReplace ( key , entry , utcExpiry ) ;
119- await _table . ExecuteAsync ( insertOp ) ;
119+ await _tableClient . UpsertEntityAsync < CacheEntity > ( new CacheEntity ( key , entry , utcExpiry ) ) ;
120120 }
121121
122122 private async Task EnsureTableInitializedAsync ( ) {
123- if ( _table != null ) {
123+ if ( _tableClient != null ) {
124124 return ;
125125 }
126126
127127 try {
128128 lock ( _lock ) {
129- if ( _table != null ) {
129+ if ( _tableClient != null ) {
130130 return ;
131131 }
132132
133- var storageAccount = CreateStorageAccount ( ) ;
134- var tableClient = storageAccount . CreateCloudTableClient ( ) ;
135- _table = tableClient . GetTableReference ( _tableName ) ;
133+ try {
134+ _tableClient = new TableClient ( _connectionString , _tableName ) ;
135+ } catch ( FormatException ) {
136+ throw new HttpException ( SR . Invalid_storage_account_information ) ;
137+ } catch ( ArgumentException ) {
138+ throw new HttpException ( SR . Invalid_storage_account_information ) ;
139+ }
136140 }
137141
138- // The sync version API causes deadlock when using CosmosDB table.
139- await _table . CreateIfNotExistsAsync ( ) ;
140- } catch ( StorageException ex ) {
141- throw new HttpException ( SR . Fail_to_create_table , ex ) ;
142- }
143- }
142+ await _tableClient . CreateIfNotExistsAsync ( ) ;
144143
145- private CloudStorageAccount CreateStorageAccount ( ) {
146- try {
147- return CloudStorageAccount . Parse ( _connectionString ) ;
148- } catch ( FormatException ) {
149- throw new HttpException ( SR . Invalid_storage_account_information ) ;
150- } catch ( ArgumentException ) {
151- throw new HttpException ( SR . Invalid_storage_account_information ) ;
144+ } catch ( RequestFailedException ex ) {
145+ throw new HttpException ( SR . Fail_to_create_table , ex ) ;
152146 }
153147 }
154148 }
0 commit comments