예제 #1
0
        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);
        }