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 da5a2d1062..6a8e971a2c 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -370,6 +370,12 @@
Microsoft\Data\SqlClient\SqlDependencyListener.cs
+
+ Microsoft\Data\SqlClient\SqlDependencyUtils.cs
+
+
+ Microsoft\Data\SqlClient\SqlDependencyUtils.AppDomain.cs
+
Microsoft\Data\SqlClient\SqlEnclaveSession.cs
@@ -543,13 +549,15 @@
+
+ Microsoft\Data\SqlClient\SqlDependencyUtils.AssemblyLoadContext.cs
+
-
+
-
@@ -627,8 +635,6 @@
-
-
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 2580fab991..7cd8814adf 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
@@ -437,6 +437,9 @@
Microsoft\Data\SqlClient\SqlDependencyListener.cs
+
+ Microsoft\Data\SqlClient\SqlDependencyUtils.cs
+
Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.Crypto.cs
@@ -610,7 +613,6 @@
-
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDependencyUtils.AppDomain.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlDependencyUtils.AppDomain.cs
similarity index 100%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDependencyUtils.AppDomain.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlDependencyUtils.AppDomain.cs
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDependencyUtils.AssemblyLoadContext.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlDependencyUtils.AssemblyLoadContext.cs
similarity index 100%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDependencyUtils.AssemblyLoadContext.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlDependencyUtils.AssemblyLoadContext.cs
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDependencyUtils.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlDependencyUtils.cs
similarity index 96%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDependencyUtils.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlDependencyUtils.cs
index 15f2b573e2..404e27d788 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDependencyUtils.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlDependencyUtils.cs
@@ -18,15 +18,14 @@ internal partial class SqlDependencyPerAppDomainDispatcher : MarshalByRefObject
{
// Instance members
- internal static readonly SqlDependencyPerAppDomainDispatcher
- SingletonInstance = new SqlDependencyPerAppDomainDispatcher(); // singleton object
+ internal static readonly SqlDependencyPerAppDomainDispatcher SingletonInstance = new(); // singleton object
- internal object _instanceLock = new object();
+ internal object _instanceLock = new();
// Dependency ID -> Dependency hashtable. 1 -> 1 mapping.
// 1) Used for ASP.NET to map from ID to dependency.
// 2) Used to enumerate dependencies to invalidate based on server.
- private Dictionary _dependencyIdToDependencyHash;
+ private readonly Dictionary _dependencyIdToDependencyHash;
// holds dependencies list per notification and the command hash from which this notification was generated
// command hash is needed to remove its entry from _commandHashToNotificationId when the notification is removed
@@ -46,12 +45,12 @@ internal DependencyList(string commandHash)
// resource effect on SQL Server. The Guid identifier is sent to the server during notification enlistment,
// and returned during the notification event. Dependencies look up existing Guids, if one exists, to ensure
// they are re-using notification ids.
- private Dictionary _notificationIdToDependenciesHash;
+ private readonly Dictionary _notificationIdToDependenciesHash;
// CommandHash value -> notificationId associated with it: 1->1 mapping. This map is used to quickly find if we need to create
// new notification or hookup into existing one.
// CommandHash is built from connection string, command text and parameters
- private Dictionary _commandHashToNotificationId;
+ private readonly Dictionary _commandHashToNotificationId;
// TIMEOUT LOGIC DESCRIPTION
//
@@ -73,10 +72,10 @@ internal DependencyList(string commandHash)
private DateTime _nextTimeout;
// Timer to periodically check the dependencies in the table and see if anyone needs
// a timeout. We'll enable this only on demand.
- private Timer _timeoutTimer;
+ private readonly Timer _timeoutTimer;
- private static int _objectTypeCount; // EventSource counter
- internal int ObjectID { get; } = Interlocked.Increment(ref _objectTypeCount);
+ private static int s_objectTypeCount; // EventSource counter
+ internal int ObjectID { get; } = Interlocked.Increment(ref s_objectTypeCount);
private SqlDependencyPerAppDomainDispatcher()
{
@@ -86,7 +85,12 @@ private SqlDependencyPerAppDomainDispatcher()
_dependencyIdToDependencyHash = new Dictionary();
_notificationIdToDependenciesHash = new Dictionary();
_commandHashToNotificationId = new Dictionary();
+#if NETFRAMEWORK
+ _timeoutTimer = new Timer(new TimerCallback(TimeoutTimerCallback), null, Timeout.Infinite, Timeout.Infinite);
+ // If rude abort - we'll leak. This is acceptable for now.
+ AppDomain.CurrentDomain.DomainUnload += new EventHandler(UnloadEventHandler);
+#else
_timeoutTimer = ADP.UnsafeCreateTimer(
new TimerCallback(TimeoutTimerCallback),
null,
@@ -95,6 +99,7 @@ private SqlDependencyPerAppDomainDispatcher()
SubscribeToAppDomainUnload();
SubscribeToAssemblyLoadContextUnload();
+#endif // NETFRAMEWORK
}
finally
{
@@ -102,10 +107,11 @@ private SqlDependencyPerAppDomainDispatcher()
}
}
+#if NETCOREAPP || NETSTANDARD
partial void SubscribeToAppDomainUnload();
partial void SubscribeToAssemblyLoadContextUnload();
-
+#endif
private void UnloadEventHandler(object sender, EventArgs e)
{
long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent("SqlDependencyPerAppDomainDispatcher.UnloadEventHandler | DEP | Object Id {0}", ObjectID);
@@ -115,7 +121,7 @@ private void UnloadEventHandler(object sender, EventArgs e)
// stopping of all start calls in this AppDomain. For containers shared among various AppDomains,
// this will just be a ref-count subtract. For non-shared containers, we will close the container
// and clean-up.
- var dispatcher = SqlDependency.ProcessDispatcher;
+ SqlDependencyProcessDispatcher dispatcher = SqlDependency.ProcessDispatcher;
dispatcher?.QueueAppDomainUnloading(SqlDependency.AppDomainKey);
}
finally
@@ -171,8 +177,7 @@ internal string AddCommandEntry(string commandHash, SqlDependency dep)
{
// we have one or more SqlDependency instances with same command hash
- DependencyList dependencyList = null;
- if (!_notificationIdToDependenciesHash.TryGetValue(notificationId, out dependencyList))
+ if (!_notificationIdToDependenciesHash.TryGetValue(notificationId, out DependencyList dependencyList))
{
// this should not happen since _commandHashToNotificationId and _notificationIdToDependenciesHash are always
// updated together
@@ -203,7 +208,7 @@ internal string AddCommandEntry(string commandHash, SqlDependency dep)
Guid.NewGuid().ToString("D", System.Globalization.CultureInfo.InvariantCulture)
);
SqlClientEventSource.Log.TryNotificationTraceEvent(" Creating new Dependencies list for commandHash.");
- DependencyList dependencyList = new DependencyList(commandHash);
+ DependencyList dependencyList = new(commandHash);
dependencyList.Add(dep);
// map command hash to notification we just created to reuse it for the next client
@@ -289,7 +294,7 @@ internal void InvalidateServer(string server, SqlNotification sqlNotification)
long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" {0}, server: '{1}'", ObjectID, server);
try
{
- List dependencies = new List();
+ List dependencies = new();
lock (_instanceLock)
{ // Copy inside of lock, but invalidate outside of lock.
@@ -449,8 +454,8 @@ private void RemoveDependencyFromCommandToDependenciesHash(SqlDependency depende
{
lock (_instanceLock)
{
- List notificationIdsToRemove = new List();
- List commandHashesToRemove = new List();
+ List notificationIdsToRemove = new();
+ List commandHashesToRemove = new();
foreach (KeyValuePair entry in _notificationIdToDependenciesHash)
{