diff --git a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj
index 498849102a..7190117fa2 100644
--- a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj
@@ -17,6 +17,7 @@
+
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
index 57497fd2b0..a503a30acc 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -936,10 +936,10 @@
-
+
diff --git a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.csproj
index 19e1e5c7b6..0b43452f7f 100644
--- a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.csproj
@@ -16,6 +16,7 @@
+
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
index 2dd8d69b08..71b374dbe2 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
@@ -738,6 +738,7 @@
+
$(SystemTextEncodingsWebVersion)
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs
index 75b55847f7..adc8e4e809 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs
@@ -5,13 +5,13 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
-using System.Runtime.Caching;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Identity;
+using Microsoft.Extensions.Caching.Memory;
using Microsoft.Identity.Client;
using Microsoft.Identity.Client.Extensibility;
@@ -27,7 +27,7 @@ public sealed class ActiveDirectoryAuthenticationProvider : SqlAuthenticationPro
///
private static ConcurrentDictionary s_pcaMap
= new ConcurrentDictionary();
- private static readonly MemoryCache s_accountPwCache = new(nameof(ActiveDirectoryAuthenticationProvider));
+ private static readonly MemoryCache s_accountPwCache = new MemoryCache(new MemoryCacheOptions());
private static readonly int s_accountPwCacheTtlInHours = 2;
private static readonly string s_nativeClientRedirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient";
private static readonly string s_defaultScopeSuffix = "/.default";
@@ -270,11 +270,11 @@ previousPw is byte[] previousPwBytes &&
// We cache the password hash to ensure future connection requests include a validated password
// when we check for a cached MSAL account. Otherwise, a connection request with the same username
// against the same tenant could succeed with an invalid password when we re-use the cached token.
- if (!s_accountPwCache.Add(pwCacheKey, GetHash(parameters.Password), DateTime.UtcNow.AddHours(s_accountPwCacheTtlInHours)))
+ using (ICacheEntry entry = s_accountPwCache.CreateEntry(pwCacheKey))
{
- s_accountPwCache.Remove(pwCacheKey);
- s_accountPwCache.Add(pwCacheKey, GetHash(parameters.Password), DateTime.UtcNow.AddHours(s_accountPwCacheTtlInHours));
- }
+ entry.Value = GetHash(parameters.Password);
+ entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(s_accountPwCacheTtlInHours);
+ };
SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Active Directory Password auth mode. Expiry Time: {0}", result?.ExpiresOn);
}
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs
index 7b1b2bf2e4..3c51716828 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs
@@ -6,11 +6,11 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IdentityModel.Tokens.Jwt;
-using System.Runtime.Caching;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
+using Microsoft.Extensions.Caching.Memory;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Logging;
using Microsoft.IdentityModel.Protocols;
@@ -59,7 +59,7 @@ internal class AzureAttestationEnclaveProvider : EnclaveProviderBase
// such as https://sql.azure.attest.com/.well-known/openid-configuration
private const string AttestationUrlSuffix = @"/.well-known/openid-configuration";
- private static readonly MemoryCache OpenIdConnectConfigurationCache = new MemoryCache("OpenIdConnectConfigurationCache");
+ private static readonly MemoryCache OpenIdConnectConfigurationCache = new MemoryCache(new MemoryCacheOptions());
#endregion
#region Internal methods
@@ -332,7 +332,7 @@ private static string GetInnerMostExceptionMessage(Exception exception)
// It also caches that information for 1 day to avoid DDOS attacks.
private OpenIdConnectConfiguration GetOpenIdConfigForSigningKeys(string url, bool forceUpdate)
{
- OpenIdConnectConfiguration openIdConnectConfig = OpenIdConnectConfigurationCache[url] as OpenIdConnectConfiguration;
+ OpenIdConnectConfiguration openIdConnectConfig = OpenIdConnectConfigurationCache.Get(url);
if (forceUpdate || openIdConnectConfig == null)
{
// Compute the meta data endpoint
@@ -348,7 +348,11 @@ private OpenIdConnectConfiguration GetOpenIdConfigForSigningKeys(string url, boo
throw SQL.AttestationFailed(string.Format(Strings.GetAttestationTokenSigningKeysFailed, GetInnerMostExceptionMessage(exception)), exception);
}
- OpenIdConnectConfigurationCache.Add(url, openIdConnectConfig, DateTime.UtcNow.AddDays(1));
+ MemoryCacheEntryOptions options = new MemoryCacheEntryOptions
+ {
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(1)
+ };
+ OpenIdConnectConfigurationCache.Set(url, openIdConnectConfig, options);
}
return openIdConnectConfig;
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveProviderBase.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveProviderBase.cs
index b8a52b9e4b..b666819dde 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveProviderBase.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveProviderBase.cs
@@ -3,9 +3,9 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Runtime.Caching;
using System.Security.Cryptography;
using System.Threading;
+using Microsoft.Extensions.Caching.Memory;
// Enclave session locking model
// 1. For doing the enclave attestation, driver makes either 1, 2 or 3 API calls(in order)
@@ -84,7 +84,7 @@ internal abstract class EnclaveProviderBase : SqlColumnEncryptionEnclaveProvider
private static readonly Object lockUpdateSessionLock = new Object();
// It is used to save the attestation url and nonce value across API calls
- protected static readonly MemoryCache ThreadRetryCache = new MemoryCache("ThreadRetryCache");
+ protected static readonly MemoryCache ThreadRetryCache = new MemoryCache(new MemoryCacheOptions());
#endregion
#region protected methods
@@ -102,7 +102,7 @@ protected void GetEnclaveSessionHelper(EnclaveSessionParameters enclaveSessionPa
// In case if on some thread we are running SQL workload which don't require attestation, then in those cases we don't want same thread to wait for event to be signaled.
// hence skipping it
- string retryThreadID = ThreadRetryCache[Thread.CurrentThread.ManagedThreadId.ToString()] as string;
+ string retryThreadID = ThreadRetryCache.Get(Thread.CurrentThread.ManagedThreadId.ToString());
if (!string.IsNullOrEmpty(retryThreadID))
{
sameThreadRetry = true;
@@ -167,7 +167,11 @@ protected void GetEnclaveSessionHelper(EnclaveSessionParameters enclaveSessionPa
retryThreadID = Thread.CurrentThread.ManagedThreadId.ToString();
}
- ThreadRetryCache.Set(Thread.CurrentThread.ManagedThreadId.ToString(), retryThreadID, DateTime.UtcNow.AddMinutes(ThreadRetryCacheTimeoutInMinutes));
+ MemoryCacheEntryOptions options = new MemoryCacheEntryOptions
+ {
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(ThreadRetryCacheTimeoutInMinutes)
+ };
+ ThreadRetryCache.Set(Thread.CurrentThread.ManagedThreadId.ToString(), retryThreadID, options);
}
}
}
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveSessionCache.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveSessionCache.cs
index 2cc34eeeb5..5673395e11 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveSessionCache.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveSessionCache.cs
@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Runtime.Caching;
+using Microsoft.Extensions.Caching.Memory;
using System.Threading;
namespace Microsoft.Data.SqlClient
@@ -11,7 +11,7 @@ namespace Microsoft.Data.SqlClient
// Maintains a cache of SqlEnclaveSession instances
internal class EnclaveSessionCache
{
- private readonly MemoryCache enclaveMemoryCache = new MemoryCache("EnclaveMemoryCache");
+ private readonly MemoryCache enclaveMemoryCache = new MemoryCache(new MemoryCacheOptions());
private readonly object enclaveCacheLock = new object();
// Nonce for each message sent by the client to the server to prevent replay attacks by the server,
@@ -25,7 +25,7 @@ internal class EnclaveSessionCache
internal SqlEnclaveSession GetEnclaveSession(EnclaveSessionParameters enclaveSessionParameters, out long counter)
{
string cacheKey = GenerateCacheKey(enclaveSessionParameters);
- SqlEnclaveSession enclaveSession = enclaveMemoryCache[cacheKey] as SqlEnclaveSession;
+ SqlEnclaveSession enclaveSession = enclaveMemoryCache.Get(cacheKey);
counter = Interlocked.Increment(ref _counter);
return enclaveSession;
}
@@ -41,8 +41,12 @@ internal void InvalidateSession(EnclaveSessionParameters enclaveSessionParameter
if (enclaveSession != null && enclaveSession.SessionId == enclaveSessionToInvalidate.SessionId)
{
- SqlEnclaveSession enclaveSessionRemoved = enclaveMemoryCache.Remove(cacheKey) as SqlEnclaveSession;
- if (enclaveSessionRemoved == null)
+ enclaveMemoryCache.TryGetValue(cacheKey, out SqlEnclaveSession enclaveSessionToRemove);
+ if (enclaveSessionToRemove != null)
+ {
+ enclaveMemoryCache.Remove(cacheKey);
+ }
+ else
{
throw new InvalidOperationException(Strings.EnclaveSessionInvalidationFailed);
}
@@ -58,7 +62,11 @@ internal SqlEnclaveSession CreateSession(EnclaveSessionParameters enclaveSession
lock (enclaveCacheLock)
{
enclaveSession = new SqlEnclaveSession(sharedSecret, sessionId);
- enclaveMemoryCache.Add(cacheKey, enclaveSession, DateTime.UtcNow.AddHours(enclaveCacheTimeOutInHours));
+ MemoryCacheEntryOptions options = new MemoryCacheEntryOptions
+ {
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(enclaveCacheTimeOutInHours)
+ };
+ enclaveMemoryCache.Set(cacheKey, enclaveSession, options);
counter = Interlocked.Increment(ref _counter);
}
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SignatureVerificationCache.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SignatureVerificationCache.cs
index c181637c4b..e54e88f23e 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SignatureVerificationCache.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SignatureVerificationCache.cs
@@ -3,9 +3,9 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Runtime.Caching;
using System.Text;
using System.Threading;
+using Microsoft.Extensions.Caching.Memory;
namespace Microsoft.Data.SqlClient
{
@@ -35,7 +35,7 @@ internal class ColumnMasterKeyMetadataSignatureVerificationCache
private ColumnMasterKeyMetadataSignatureVerificationCache()
{
- _cache = new MemoryCache(_className);
+ _cache = new MemoryCache(new MemoryCacheOptions());
_inTrim = 0;
}
@@ -46,17 +46,15 @@ private ColumnMasterKeyMetadataSignatureVerificationCache()
/// Key Path for CMK
/// boolean indicating whether the key can be sent to enclave
/// Signature for the CMK metadata
- /// null if the data is not found in cache otherwise returns true/false indicating signature verification success/failure
- internal bool? GetSignatureVerificationResult(string keyStoreName, string masterKeyPath, bool allowEnclaveComputations, byte[] signature)
+ internal bool GetSignatureVerificationResult(string keyStoreName, string masterKeyPath, bool allowEnclaveComputations, byte[] signature)
{
-
ValidateStringArgumentNotNullOrEmpty(masterKeyPath, _masterkeypathArgumentName, _getSignatureVerificationResultMethodName);
ValidateStringArgumentNotNullOrEmpty(keyStoreName, _keyStoreNameArgumentName, _getSignatureVerificationResultMethodName);
ValidateSignatureNotNullOrEmpty(signature, _getSignatureVerificationResultMethodName);
string cacheLookupKey = GetCacheLookupKey(masterKeyPath, allowEnclaveComputations, signature, keyStoreName);
- return _cache.Get(cacheLookupKey) as bool?;
+ return _cache.TryGetValue(cacheLookupKey, out bool value);
}
///
@@ -69,7 +67,6 @@ private ColumnMasterKeyMetadataSignatureVerificationCache()
/// result indicating signature verification success/failure
internal void AddSignatureVerificationResult(string keyStoreName, string masterKeyPath, bool allowEnclaveComputations, byte[] signature, bool result)
{
-
ValidateStringArgumentNotNullOrEmpty(masterKeyPath, _masterkeypathArgumentName, _addSignatureVerificationResultMethodName);
ValidateStringArgumentNotNullOrEmpty(keyStoreName, _keyStoreNameArgumentName, _addSignatureVerificationResultMethodName);
ValidateSignatureNotNullOrEmpty(signature, _addSignatureVerificationResultMethodName);
@@ -79,7 +76,11 @@ internal void AddSignatureVerificationResult(string keyStoreName, string masterK
TrimCacheIfNeeded();
// By default evict after 10 days.
- _cache.Set(cacheLookupKey, result, DateTimeOffset.UtcNow.AddDays(10));
+ MemoryCacheEntryOptions options = new MemoryCacheEntryOptions
+ {
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(10)
+ };
+ _cache.Set(cacheLookupKey, result, options);
}
private void ValidateSignatureNotNullOrEmpty(byte[] signature, string methodName)
@@ -115,15 +116,17 @@ private void ValidateStringArgumentNotNullOrEmpty(string stringArgValue, string
private void TrimCacheIfNeeded()
{
// If the size of the cache exceeds the threshold, set that we are in trimming and trim the cache accordingly.
- long currentCacheSize = _cache.GetCount();
+ long currentCacheSize = _cache.Count;
if ((currentCacheSize > _cacheSize + _cacheTrimThreshold) && (0 == Interlocked.CompareExchange(ref _inTrim, 1, 0)))
{
try
{
- _cache.Trim((int)(((double)(currentCacheSize - _cacheSize) / (double)currentCacheSize) * 100));
+ // Example: 2301 - 2000 = 301; 301 / 2301 = 0.1308 * 100 = 13% compacting
+ _cache.Compact((((double)(currentCacheSize - _cacheSize) / (double)currentCacheSize) * 100));
}
finally
{
+ // Reset _inTrim flag
Interlocked.CompareExchange(ref _inTrim, 0, 1);
}
}
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlQueryMetadataCache.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlQueryMetadataCache.cs
index 5475eb5a0c..964e46aca3 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlQueryMetadataCache.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlQueryMetadataCache.cs
@@ -7,9 +7,9 @@
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
-using System.Runtime.Caching;
using System.Text;
using System.Threading;
+using Microsoft.Extensions.Caching.Memory;
namespace Microsoft.Data.SqlClient
{
@@ -34,7 +34,7 @@ sealed internal class SqlQueryMetadataCache
private SqlQueryMetadataCache()
{
- _cache = new MemoryCache("SqlQueryMetadataCache");
+ _cache = new MemoryCache(new MemoryCacheOptions());
}
internal static SqlQueryMetadataCache GetInstance()
@@ -61,7 +61,7 @@ internal bool GetQueryMetadataIfExists(SqlCommand sqlCommand)
return false;
}
- Dictionary cipherMetadataDictionary = _cache.Get(cacheLookupKey) as Dictionary;
+ Dictionary cipherMetadataDictionary = _cache.Get>(cacheLookupKey);
// If we had a cache miss just return false.
if (cipherMetadataDictionary is null)
@@ -144,7 +144,7 @@ internal bool GetQueryMetadataIfExists(SqlCommand sqlCommand)
}
ConcurrentDictionary enclaveKeys =
- _cache.Get(enclaveLookupKey) as ConcurrentDictionary;
+ _cache.Get>(enclaveLookupKey);
if (enclaveKeys is not null)
{
sqlCommand.keysToBeSentToEnclave = CreateCopyOfEnclaveKeys(enclaveKeys);
@@ -215,7 +215,7 @@ internal void AddQueryMetadata(SqlCommand sqlCommand, bool ignoreQueriesWithRetu
}
// If the size of the cache exceeds the threshold, set that we are in trimming and trim the cache accordingly.
- long currentCacheSize = _cache.GetCount();
+ long currentCacheSize = _cache.Count;
if ((currentCacheSize > CacheSize + CacheTrimThreshold) && (0 == Interlocked.CompareExchange(ref _inTrim, 1, 0)))
{
try
@@ -226,7 +226,7 @@ internal void AddQueryMetadata(SqlCommand sqlCommand, bool ignoreQueriesWithRetu
Thread.Sleep(TimeSpan.FromSeconds(10));
}
#endif
- _cache.Trim((int)(((double)(currentCacheSize - CacheSize) / (double)currentCacheSize) * 100));
+ _cache.Compact((int)(((double)(currentCacheSize - CacheSize) / (double)currentCacheSize) * 100));
}
finally
{
@@ -235,11 +235,15 @@ internal void AddQueryMetadata(SqlCommand sqlCommand, bool ignoreQueriesWithRetu
}
// By default evict after 10 hours.
- _cache.Set(cacheLookupKey, cipherMetadataDictionary, DateTimeOffset.UtcNow.AddHours(10));
+ MemoryCacheEntryOptions options = new MemoryCacheEntryOptions
+ {
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(10)
+ };
+ _cache.Set>(cacheLookupKey, cipherMetadataDictionary, options);
if (sqlCommand.requiresEnclaveComputations)
{
ConcurrentDictionary keysToBeCached = CreateCopyOfEnclaveKeys(sqlCommand.keysToBeSentToEnclave);
- _cache.Set(enclaveLookupKey, keysToBeCached, DateTimeOffset.UtcNow.AddHours(10));
+ _cache.Set>(enclaveLookupKey, keysToBeCached, options);
}
}
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlSecurityUtility.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlSecurityUtility.cs
index d9fea6b211..01d2d1bc61 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlSecurityUtility.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlSecurityUtility.cs
@@ -374,8 +374,8 @@ internal static void VerifyColumnMasterKeySignature(string keyStoreName, string
}
else
{
- bool? signatureVerificationResult = ColumnMasterKeyMetadataSignatureVerificationCache.GetSignatureVerificationResult(keyStoreName, keyPath, isEnclaveEnabled, CMKSignature);
- if (signatureVerificationResult is null)
+ bool signatureVerificationResult = ColumnMasterKeyMetadataSignatureVerificationCache.GetSignatureVerificationResult(keyStoreName, keyPath, isEnclaveEnabled, CMKSignature);
+ if (signatureVerificationResult == false)
{
// We will simply bubble up the exception from VerifyColumnMasterKeyMetadata function.
isValidSignature = provider.VerifyColumnMasterKeyMetadata(keyPath, isEnclaveEnabled,
@@ -385,7 +385,7 @@ internal static void VerifyColumnMasterKeySignature(string keyStoreName, string
}
else
{
- isValidSignature = signatureVerificationResult.Value;
+ isValidSignature = signatureVerificationResult;
}
}
}
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlSymmetricKeyCache.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlSymmetricKeyCache.cs
index 663116ed59..fb9ea2997d 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlSymmetricKeyCache.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlSymmetricKeyCache.cs
@@ -4,8 +4,8 @@
using System;
using System.Diagnostics;
-using System.Runtime.Caching;
using System.Text;
+using Microsoft.Extensions.Caching.Memory;
namespace Microsoft.Data.SqlClient
{
@@ -20,7 +20,7 @@ sealed internal class SqlSymmetricKeyCache
private SqlSymmetricKeyCache()
{
- _cache = new MemoryCache("ColumnEncryptionKeyCache");
+ _cache = new MemoryCache(new MemoryCacheOptions());
}
internal static SqlSymmetricKeyCache GetInstance()
@@ -53,7 +53,8 @@ internal SqlClientSymmetricKey GetKey(SqlEncryptionKeyInfo keyInfo, SqlConnectio
#endif //DEBUG
// Lookup the key in cache
- if (!(_cache.Get(cacheLookupKey) is SqlClientSymmetricKey encryptionKey))
+ SqlClientSymmetricKey encryptionKey;
+ if (!(_cache.TryGetValue(cacheLookupKey, out encryptionKey)))
{
Debug.Assert(SqlConnection.ColumnEncryptionTrustedMasterKeyPaths is not null, @"SqlConnection.ColumnEncryptionTrustedMasterKeyPaths should not be null");
@@ -90,8 +91,11 @@ internal SqlClientSymmetricKey GetKey(SqlEncryptionKeyInfo keyInfo, SqlConnectio
{
// In case multiple threads reach here at the same time, the first one wins.
// The allocated memory will be reclaimed by Garbage Collector.
- DateTimeOffset expirationTime = DateTimeOffset.UtcNow.Add(SqlConnection.ColumnEncryptionKeyCacheTtl);
- _cache.Add(cacheLookupKey, encryptionKey, expirationTime);
+ MemoryCacheEntryOptions options = new MemoryCacheEntryOptions
+ {
+ AbsoluteExpirationRelativeToNow = SqlConnection.ColumnEncryptionKeyCacheTtl
+ };
+ _cache.Set(cacheLookupKey, encryptionKey, options);
}
}
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs
index cfbe531e82..ab327aa689 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs
@@ -3,10 +3,10 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Runtime.Caching;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
+using Microsoft.Extensions.Caching.Memory;
namespace Microsoft.Data.SqlClient
{
@@ -14,7 +14,7 @@ internal abstract class VirtualizationBasedSecurityEnclaveProviderBase : Enclave
{
#region Members
- private static readonly MemoryCache rootSigningCertificateCache = new MemoryCache("RootSigningCertificateCache");
+ private static readonly MemoryCache rootSigningCertificateCache = new MemoryCache(new MemoryCacheOptions());
#endregion
@@ -192,7 +192,7 @@ private void VerifyAttestationInfo(string attestationUrl, HealthReport healthRep
private X509Certificate2Collection GetSigningCertificate(string attestationUrl, bool forceUpdate)
{
attestationUrl = GetAttestationUrl(attestationUrl);
- X509Certificate2Collection signingCertificates = (X509Certificate2Collection)rootSigningCertificateCache[attestationUrl];
+ X509Certificate2Collection signingCertificates = rootSigningCertificateCache.Get(attestationUrl);
if (forceUpdate || signingCertificates == null || AnyCertificatesExpired(signingCertificates))
{
byte[] data = MakeRequest(attestationUrl);
@@ -207,10 +207,14 @@ private X509Certificate2Collection GetSigningCertificate(string attestationUrl,
throw SQL.AttestationFailed(string.Format(Strings.GetAttestationSigningCertificateFailedInvalidCertificate, attestationUrl), exception);
}
- rootSigningCertificateCache.Add(attestationUrl, certificateCollection, DateTime.Now.AddDays(1));
+ MemoryCacheEntryOptions options = new MemoryCacheEntryOptions
+ {
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(1)
+ };
+ rootSigningCertificateCache.Set(attestationUrl, certificateCollection, options);
}
- return (X509Certificate2Collection)rootSigningCertificateCache[attestationUrl];
+ return rootSigningCertificateCache.Get(attestationUrl);
}
// Return the endpoint for given attestation url
diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj
index b5ac559337..15249ba3cd 100644
--- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj
+++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj
@@ -123,10 +123,10 @@
-
- PreserveNewest
- %(Filename)%(Extension)
-
+
+ PreserveNewest
+ %(Filename)%(Extension)
+
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ConversionTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ConversionTests.cs
index d0b1bfd076..8e62ee95fc 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ConversionTests.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ConversionTests.cs
@@ -1449,5 +1449,4 @@ public IEnumerator
@@ -340,7 +341,6 @@
-
@@ -348,10 +348,10 @@
-
- PreserveNewest
- %(Filename)%(Extension)
-
+
+ PreserveNewest
+ %(Filename)%(Extension)
+
diff --git a/tools/specs/Microsoft.Data.SqlClient.nuspec b/tools/specs/Microsoft.Data.SqlClient.nuspec
index b1666d4459..1e4f5e5a09 100644
--- a/tools/specs/Microsoft.Data.SqlClient.nuspec
+++ b/tools/specs/Microsoft.Data.SqlClient.nuspec
@@ -46,7 +46,7 @@ When using NuGet 3.x this package requires at least version 3.4.
-
+
@@ -56,7 +56,7 @@ When using NuGet 3.x this package requires at least version 3.4.
-
+