public bool OpenConnection(string connectionString) { if (string.IsNullOrWhiteSpace(connectionString)) { Logger.Log(this, "Unable to connect to the SQL database: No connection specified.", LogLevel.Error); return(false); } internalState = ConnectionState.Connecting; connection = PostgreSQLTools.CreateDataConnection(connectionString); internalState = ConnectionState.Open; connection.OnClosing += (sender, args) => internalState = ConnectionState.Closed; connection.OnClosed += (sender, args) => internalState = ConnectionState.Closed; metadata = connection.GetTable <Metadata>(); try { var version = from entry in metadata where entry.Key == "version" select entry.Value; var count = version.Count(); if (count != 1) { Logger.Log(this, "Zero or multiple 'version' entries found in the Metadata table. The database connection will be dropped.", LogLevel.Error); HandleConnectionFailure(); return(false); } if (version.First() != Bot.DatabaseVersion) { Logger.Log(this, $"Bot and database version do not match (bot is at {Bot.DatabaseVersion}, database is at {version.First()}). The database will now be upgraded.", LogLevel.Info); if (!UpgradeDatabase(version.First())) { Logger.Log(this, "Upgrade failed. The database connection will be dropped.", LogLevel.Warning); HandleConnectionFailure(); return(false); } } } catch (NpgsqlException e) { if (e.Message.ToLower().Contains("metadata") && e.Message.ToLower().Contains("does not exist")) { Logger.Log(this, "Metadata table not found. A new tableset will be created.", LogLevel.Warning); try { DropTables(); CreateTables(); } catch (NpgsqlException f) { Logger.Log(this, $"Unable to create a new tableset: An exception occurred({f.GetType()}: {f.Message}). The database connection will be dropped.", LogLevel.Error); HandleConnectionFailure(); return(false); } AddMetadata(); Logger.Log(this, "Writing metadata...", LogLevel.Info); } else { Logger.Log(this, $"Unable to retrieve the database version: An exception occurred ({e.GetType()}: {e.Message}). The database connection will be dropped.", LogLevel.Error); HandleConnectionFailure(); return(false); } } //UserCredentials = connection.GetTable<UserCredential>(); Quotes = connection.GetTable <Quote>(); UserStatistics = connection.GetTable <UserStatistic>(); Emoticons = connection.GetTable <UsedEmoticon>(); KeyValuePairs = connection.GetTable <KeyValuePair>(); LinkedUrls = connection.GetTable <LinkedUrl>(); Users = connection.GetTable <User>(); Words = connection.GetTable <UsedWord>(); ChatLog = connection.GetTable <ChatLog>(); MiscData = connection.GetTable <MiscData>(); try { // These methods are actually not pure, because they'll throw an exception // if their backing database tables are not found. It's a bit of a hack, // but this is the easiest way to check whether those tables exist. // ReSharper disable ReturnValueOfPureMethodIsNotUsed //UserCredentials.FirstOrDefault(); Quotes.FirstOrDefault(); UserStatistics.FirstOrDefault(); Emoticons.FirstOrDefault(); KeyValuePairs.FirstOrDefault(); LinkedUrls.FirstOrDefault(); Users.FirstOrDefault(); Words.FirstOrDefault(); ChatLog.FirstOrDefault(); MiscData.FirstOrDefault(); // ReSharper restore ReturnValueOfPureMethodIsNotUsed } catch (Exception e) { Logger.Log(this, $"Database integrity check failed ({e.GetType().Name}: {e.Message})", LogLevel.Error); HandleConnectionFailure(); return(false); } return(true); }