Hi,
I have a native service on Azure and I'm using ATL for the DB connection.
I have created a connection manager which basically creates and caches a DB connection for each thread (every connection is kept for a specific amount of time before it is recycled).
I was wondering whether this is a good approach or if I should be caching CSession objects instead.
Here is part of my code, any comments welcome:
struct ThreadSessionInfo { CDataSource _data_source; chrono::system_clock::time_point _creation_time; std::thread::id _thread_id; AutoCOMInit<COINIT_APARTMENTTHREADED> _com_init_token; }; /// /// \brief Returns a DB session for the current execution thread /// CSession ConnectionManager::GetDBSession() { CDataSource ds; { unique_lock<mutex> lock(_connections_map_mtx); // Use the existing datasource for this thread if the refresh threshold hasn't been breached auto match = _connections_map.find(this_thread::get_id()); if (match != end(_connections_map)) { auto elapsed_period = chrono::system_clock::now() - match->second._creation_time; auto mins = chrono::duration_cast<chrono::minutes>(elapsed_period); if (mins.count() <= REFRESH_THRESHOLD_MINS) { ds = match->second._data_source; } else { // Remove the old ThreadSessionInfo obj so that CoUninitialize is called before // CoInitializeEx is called by the new ThreadSessionInfo obj _connections_map.erase(this_thread::get_id()); } } } // Otherwise initialize a new datasource in for the thread // COM is initialized for the thread as well if (!ds.m_spInit) { // CoInitializeEx is called here ThreadSessionInfo tsi; HRESULT hr = E_FAIL; for (int i = 0; i < DB_CONN_RETRY_ITERATIONS, !SUCCEEDED(hr); ++i) { // Try SQL Native Client 11 (Azure Server) first hr = tsi._data_source.OpenFromInitializationString(GetConnectionString(L"SQLNCLI11.1").c_str()); // Fall back to SQL Native Client 10 - Azure Server if required if (hr == REGDB_E_CLASSNOTREG) hr = tsi._data_source.OpenFromInitializationString(GetConnectionString(L"SQLNCLI10.1").c_str()); if (FAILED(hr)) this_thread::sleep_for(chrono::milliseconds(50)); } ATLENSURE_SUCCEEDED(hr); tsi._creation_time = chrono::system_clock::now(); tsi._thread_id = this_thread::get_id(); { unique_lock<mutex> lock(_connections_map_mtx); _connections_map[tsi._thread_id] = tsi; } ds = tsi._data_source; } CSession ret; ATLENSURE_SUCCEEDED(ret.Open(ds)); return ret; }
Thanks in advance,
Yiannis