///<summary>The following test calls setDb within a child thread. This will change the static database connection for all threads. The ///parent thread, or any other thread already alive, should not have their context changed.</summary> public void ODThread_SetDb_ChildContext() { Exception ex = null; string methodName = MethodBase.GetCurrentMethod().Name; string databaseName = POut.String(methodName).ToLower(); string odThreadGroupName = methodName + "_GroupName"; string databaseMain = LargeTableHelper.GetCurrentDatabase(); //should be pointing to a 'unittestXXX' database Assert.IsFalse(string.IsNullOrEmpty(databaseMain)); try { ODThread odThreadAffect = new ODThread((o) => { string databaseBefore = LargeTableHelper.GetCurrentDatabase(); //should be pointing to a 'unittestXXX' database Assert.AreEqual(databaseMain, databaseBefore); ODThread odThreadChangeDb = new ODThread(workerChild => { //The parent thread needs to call SetDb on a different database than the main thread is connected to. CreateDatabaseIfNeeded(databaseName); new DataConnection().SetDb("localhost", databaseName, "root", "", "", "", DatabaseType.MySql); VerifyCurrentDatabaseName(databaseName); }); odThreadChangeDb.AddExceptionHandler(e => ex = e); odThreadChangeDb.Name = MethodBase.GetCurrentMethod().Name + "_Child"; odThreadChangeDb.GroupName = odThreadGroupName; //This thread needs to only start the above thread and then make sure it is still connected to the unittestXXX database when complete. odThreadChangeDb.Start(); odThreadChangeDb.Join(Timeout.Infinite); //Manually join the parent to the main thread so that we know for certain that our child thread exists. VerifyCurrentDatabaseName(databaseMain); }); odThreadAffect.AddExceptionHandler(e => ex = e); odThreadAffect.Name = MethodBase.GetCurrentMethod().Name + "_ThreadAffected"; odThreadAffect.Start(); odThreadAffect.Join(Timeout.Infinite); //The main thread should still be on the original database after this. VerifyCurrentDatabaseName(databaseMain); //Verify that new thread is not affected by the call to SetDb() from the child thread above. //You should only SetDb() once per application instance. //After that, it does nothing to any thread (existing or subsequent) but the thread that calls it. ODThread odThreadChangeDb1 = new ODThread(workerChild => { VerifyCurrentDatabaseName(databaseMain); }); odThreadChangeDb1.AddExceptionHandler(e => ex = e); odThreadChangeDb1.Name = MethodBase.GetCurrentMethod().Name + "_Child"; odThreadChangeDb1.GroupName = odThreadGroupName; odThreadChangeDb1.Start(); odThreadChangeDb1.Join(Timeout.Infinite); //Manually join the parent to the main thread so that we know for certain that our child thread exists. } catch (Exception e) { ex = e; } finally { DropDatabase(databaseName); } Assert.IsNull(ex, ex?.Message); //Asserts do not bubble up as expected to the main thread so do a manual assert at the end of the day. }
///<summary>The ThreadStatic database context should be inherited by any child thread that is spawned.</summary> public void ODThread_SetDbT_ParentChildDatabaseContext() { Exception ex = null; string methodName = MethodBase.GetCurrentMethod().Name; string databaseName = POut.String(methodName).ToLower(); string odThreadGroupName = methodName + "_GroupName"; //The main thread needs to connect to a unique database that the child thread should NOT end up getting connected to. //Use a query to get our current database context because unit tests utilizes a connection string and we only care about DataConnection.Database string databaseMain = LargeTableHelper.GetCurrentDatabase(); //should be pointing to a 'unittestXXX' database Assert.IsFalse(string.IsNullOrEmpty(databaseMain)); try { ODThread odThreadParent = new ODThread(workerParent => { //The parent thread needs to connect to a database that the main thread is not connected to. CreateDatabaseIfNeeded(databaseName); new DataConnection().SetDbT("localhost", databaseName, "root", "", "", "", DatabaseType.MySql); VerifyCurrentDatabaseName(databaseName); //Now the parent should spawn a child thread which should default to the thread specific database connection from the parent. ODThread odThreadChild = new ODThread(workerChild => { //The child thread should default to the database context of its parent and NOT the database context from the main thread. VerifyCurrentDatabaseName(databaseName); }); odThreadChild.AddExceptionHandler(e => ex = e); odThreadChild.Name = MethodBase.GetCurrentMethod().Name + "_Child"; odThreadChild.GroupName = odThreadGroupName; odThreadChild.Start(); odThreadChild.Join(Timeout.Infinite); VerifyCurrentDatabaseName(databaseName); }); odThreadParent.AddExceptionHandler(e => ex = e); odThreadParent.Name = MethodBase.GetCurrentMethod().Name + "_Parent"; odThreadParent.GroupName = odThreadGroupName; odThreadParent.Start(); odThreadParent.Join(Timeout.Infinite); //Manually join the parent to the main thread so that we know for certain that our child thread exists. VerifyCurrentDatabaseName(databaseMain); } catch (Exception e) { ex = e; } finally { DropDatabase(databaseName); } Assert.IsNull(ex, ex?.Message); //Asserts do not bubble up as expected to the main thread so do a manual assert at the end of the day. }
private void VerifyCurrentDatabaseName(string expected) { Assert.AreEqual(expected, LargeTableHelper.GetCurrentDatabase()); }