@@ -5,21 +5,22 @@ namespace Microsoft.AspNet.OutputCache.CosmosDBTableAsyncOutputCacheProvider {
5
5
using System ;
6
6
using System . Collections . Specialized ;
7
7
using System . Configuration ;
8
+ using System . Runtime . Caching ;
8
9
using System . Threading . Tasks ;
9
10
using System . Web ;
10
- using Microsoft . Azure . CosmosDB . Table ;
11
- using Microsoft . Azure . Storage ;
11
+ using Azure ;
12
+ using Azure . Data . Tables ;
12
13
using Resource ;
13
14
14
15
class CosmosDBTableOutputCacheRepository : ITableOutputCacheRepository {
15
16
private const string TableNameKey = "tableName" ;
16
17
private const string ConnectionStringKey = "connectionStringName" ;
17
18
private const string FixedPartitionKey = "P" ;
18
19
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 ( ) ;
23
24
24
25
public CosmosDBTableOutputCacheRepository ( NameValueCollection providerConfig , NameValueCollection appSettings ) {
25
26
var connectionStringName = providerConfig [ ConnectionStringKey ] ;
@@ -39,9 +40,7 @@ public CosmosDBTableOutputCacheRepository(NameValueCollection providerConfig, Na
39
40
}
40
41
41
42
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 ;
45
44
46
45
if ( existingCacheEntry != null && existingCacheEntry . UtcExpiry > DateTime . UtcNow ) {
47
46
return existingCacheEntry . CacheItem ;
@@ -54,9 +53,7 @@ public object Add(string key, object entry, DateTime utcExpiry) {
54
53
public async Task < object > AddAsync ( string key , object entry , DateTime utcExpiry ) {
55
54
// If there is already a value in the cache for the specified key, the provider must return that value if not expired
56
55
// 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 ;
60
57
61
58
if ( existingCacheEntry != null && existingCacheEntry . UtcExpiry > DateTime . UtcNow ) {
62
59
return existingCacheEntry . CacheItem ;
@@ -67,88 +64,85 @@ public async Task<object> AddAsync(string key, object entry, DateTime utcExpiry)
67
64
}
68
65
69
66
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
+ }
79
77
}
78
+ catch ( RequestFailedException rfe ) when ( rfe . Status == 404 ) { /* Entity not found */ }
79
+ return null ;
80
80
}
81
81
82
82
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 ( ) ;
86
83
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 ( ) ;
90
89
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
+ }
96
98
}
99
+ catch ( RequestFailedException rfe ) when ( rfe . Status == 404 ) { /* Entity not found */ }
100
+ return null ;
97
101
}
98
102
99
103
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 ) ;
102
105
}
103
106
104
107
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 ) ;
107
109
}
108
110
109
111
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 ) ) ;
112
113
}
113
114
114
115
public async Task SetAsync ( string key , object entry , DateTime utcExpiry ) {
115
116
//Check if the key is already in database
116
117
//If there is already a value in the cache for the specified key, the Set method will update it.
117
118
//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 ) ) ;
120
120
}
121
121
122
122
private async Task EnsureTableInitializedAsync ( ) {
123
- if ( _table != null ) {
123
+ if ( _tableClient != null ) {
124
124
return ;
125
125
}
126
126
127
127
try {
128
128
lock ( _lock ) {
129
- if ( _table != null ) {
129
+ if ( _tableClient != null ) {
130
130
return ;
131
131
}
132
132
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
+ }
136
140
}
137
141
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 ( ) ;
144
143
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 ) ;
152
146
}
153
147
}
154
148
}
0 commit comments