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) {