Пример #1
0
        public void FullCycle()
        {
            // First create the controller for the system context
            using (var controller = DbController.Create(Config)) {
                Console.Out.WriteLine("A new system controller was created at path {0}", controller.Config.BasePath());

                // Then create the database 'testdb'
                using (var dbSystem = controller.CreateDatabase(testDbName, testDbAdmin, testDbPass)) {
                    Console.Out.WriteLine("The database {0} was created at the path {1}",
                                          dbSystem.Config.DatabaseName(),
                                          dbSystem.Config.DatabaseFullPath());

                    Assert.IsTrue(dbSystem.Database.Exists, "The database was created but was not not physically found.");

                    // now open am ADO.NET connection to write data to the database
                    using (var connection = dbSystem.GetConnection(testDbAdmin, testDbPass)) {
                        Assert.IsTrue(connection.State == ConnectionState.Open, "The connection is not open");

                        using (var transaction = connection.BeginTransaction()) {
                            // Create the table 'people'
                            var command = connection.CreateCommand();
                            command.CommandText = "CREATE TABLE people (first_name VARCHAR(255), last_name VARCHAR(255), age INT)";
                            command.ExecuteNonQuery();

                            Console.Out.WriteLine("The table 'people' was created in the database");

                            // insert an entry into the table
                            command             = connection.CreateCommand();
                            command.CommandText = "INSERT INTO people (first_name, last_name, age) VALUES ('Antonello', 'Provenzano', 33)";
                            command.ExecuteNonQuery();

                            Console.Out.WriteLine("An entry was inserted into the table 'people'.");

                            // assert the entry exists within this context
                            command             = connection.CreateCommand();
                            command.CommandText = "SELECT COUNT(*) FROM people";

                            var count = (BigNumber)command.ExecuteScalar();
                            Assert.AreEqual(1, count.ToInt32(), "The number of entries in the table is not coherent.");

                            transaction.Commit();
                        }
                    }
                }
            }

            // The previous system context was disposed, any reference to the databases within the
            // context has been released. So create another system controller
            using (var controller = DbController.Create(Config)) {
                // Check the database physically exists in the system
                Assert.IsTrue(controller.DatabaseExists(testDbName), "The database {0} was not physically found at the path {1}", testDbName, Config.BasePath());
            }

            // Open another system context that is isolated from the previous ones.
            using (var controller = DbController.Create(Config)) {
                // Open an existing database within the system context. If the database doesn't exist
                // this will throw an exception.
                using (var dbSystem = controller.StartDatabase(testDbName)) {
                    // Open a connection to the database
                    using (var connection = dbSystem.GetConnection(testDbAdmin, testDbPass)) {
                        // Assert the connection state is open
                        Assert.IsTrue(connection.State == ConnectionState.Open, "The connection is not open");

                        // Check the 'people' table and count the items. If the table doesn't physically
                        // exist this will throw an exception
                        var command = connection.CreateCommand();
                        command.CommandText = "SELECT COUNT(*) FROM people";

                        // Assert there is exactly one element in the table
                        var count = (BigNumber)command.ExecuteScalar();
                        Assert.AreEqual(1, count.ToInt32(), "An incorrect number of items was found in the table.");

                        // Now select the entry in the table
                        command             = connection.CreateCommand();
                        command.CommandText = "SELECT * FROM people";

                        // Assert the data structure is coherent with the one created in
                        // the previous passage
                        var reader = command.ExecuteReader();
                        Assert.AreEqual(3, reader.FieldCount, "An incorrect number of fields was found in the table.");
                        Assert.AreEqual(0, reader.GetOrdinal("first_name"), "The first field in the table is not 'first_name'");
                        Assert.AreEqual(1, reader.GetOrdinal("last_name"), "The second field in the table is not 'last_name'");
                        Assert.AreEqual(2, reader.GetOrdinal("age"), "The third field in the table is not 'age'");

                        // Assert at least one entry can be read
                        Assert.IsTrue(reader.Read(), "It was not possible to read from the result");

                        // Assert the entry read is exactly the one created in the previous stage
                        Assert.AreEqual("Antonello", reader.GetString(0), "The value of 'first_name' is not 'Antonello'");
                        Assert.AreEqual("Provenzano", reader.GetString(1), "The value of 'last_name' is not 'Provenzano'");
                        Assert.AreEqual(33, reader.GetInt32(2), "The value of 'age' is not 33");
                    }
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Creates a new database with the given name and with initial
        /// configurations.
        /// </summary>
        /// <param name="config">The configurations specific for the dataabse
        /// to create. These will be merged with existing context configurations.</param>
        /// <param name="name">The name of the database to create.</param>
        /// <param name="adminUser">The name of the administrator for the database,</param>
        /// <param name="adminPass">The password used to identify the administrator.</param>
        /// <returns>
        /// Returns a <see cref="DbSystem"/> instance used to access the database created.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// If the <paramref name="name"/> of the database is <b>null</b>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// If a database with the given <paramref name="name"/> already exists.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// If an error occurred while initializing the database.
        /// </exception>
        public DbSystem CreateDatabase(IDbConfig config, string name, string adminUser, string adminPass)
        {
            if (name == null)
                throw new ArgumentNullException("name");

            if (config == null)
                config = DbConfig.Default;

            if (DatabaseExists(config, name))
                throw new ArgumentException("A database '" + name + "' already exists.");

            config.Parent = Config;

            StorageType storageType = GetStorageType(config);

            if (storageType == StorageType.File) {
                // we ensure that the BasePath points to where we want it to point
                string path = Path.Combine(config.BasePath(), name);
                if (Directory.Exists(path))
                    throw new ApplicationException("Database path '" + name + "' already exists: try opening");

                Directory.CreateDirectory(path);

                config.SetValue(ConfigKeys.DatabasePath, name);

                string configFile = Path.Combine(path, DefaultConfigFileName);
                //TODO: support multiple formats?
                config.Save(configFile);
            }

            IDatabase database = CreateDatabase(config, name);

            try {
                database.Create(adminUser, adminPass);
                database.Init();

                var callback = new DatabaseShutdownCallback(this, database);
                database.Context.OnShutdown += (callback.Execute);
            } catch (Exception e) {
                database.Context.Logger.Error(this, "Database create failed");
                database.Context.Logger.Error(this, e);
                throw new InvalidOperationException(e.Message, e);
            }
            // Return the DbSystem object for the newly created database.
            databases[name] = database;
            return new DbSystem(this, name, config, database);
        }
Пример #3
0
        public bool DeleteDatabase(IDbConfig config, string name, string adminName, string adminPass)
        {
            if (String.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");

            if (config == null)
                config = DbConfig.Default;

            if (!DatabaseExists(config, name))
                return false;

            config.Parent = Config;

            IDatabase database = GetDatabase(name);
            if (database == null)
                return false;

            // TODO: query the db to see if the user is the admin

            try {
                //TODO: close all connections to the database

                try {
                    if (database.IsInitialized)
                    database.Shutdown();
                } finally {
                    database.Dispose();

                    if (databases.ContainsKey(name))
                        databases.Remove(name);
                }
            } catch (Exception ex) {
                Logger.Error(ex);
            }

            StorageType storageType = GetStorageType(config);

            if (storageType == StorageType.File) {
                // we ensure that the BasePath points to where we want it to point
                string path = Path.Combine(config.BasePath(), name);
                if (!Directory.Exists(path))
                    return false;

                Directory.Delete(path, true);
            }

            return true;
        }
Пример #4
0
        /// <summary>
        /// Creates a new instance of <see cref="DbController"/> to the
        /// given path on the underlying filesystem.
        /// </summary>
        /// <param name="config">The initial configurations that will
        /// be applied to the subsequent databases within the context.</param>
        /// <remarks>
        /// If the given path doesn't point to any valid database context
        /// this will generate it by creating a configuration file which
        /// will encapsulate all the default configurations and those
        /// provided in this method.
        /// </remarks>
        /// <returns>
        /// Returns an instance of <see cref="DbController"/> which points
        /// to the given path.
        /// </returns>
        public static DbController Create(IDbConfig config)
        {
            StorageType storageType = GetStorageType(config);

            if (config == null)
                config = DbConfig.Default;

            IDbConfig mainConfig;

            if (storageType == StorageType.File) {
                string path = config.BasePath() ?? Environment.CurrentDirectory;

                string configFile = Path.GetFileName(path);

                // we only allow the file extension .conf
                string ext = Path.GetExtension(configFile);
                if (String.Compare(ext, FileExtension, StringComparison.OrdinalIgnoreCase) == 0) {
                    path = Path.GetDirectoryName(path);
                } else {
                    configFile = DefaultConfigFileName;
                }

                // if the directory doesn't exist we will create one...
                if (path != null && !Directory.Exists(path))
                    Directory.CreateDirectory(path);

                mainConfig = GetConfig(config, path, configFile);
                mainConfig.BasePath(path);
            } else {
                mainConfig = config;
            }

            var controller = new DbController(mainConfig);

            if (storageType == StorageType.File) {
                // done with the main configuration... now look for the databases...
                string path = config.BasePath();
                string[] subDirs = Directory.GetDirectories(path);
                foreach (string dir in subDirs) {
                    IDbConfig dbConfig = GetConfig(mainConfig, dir, null);
                    if (dbConfig == null)
                        continue;

                    var dbPath = dir.Substring(dir.LastIndexOf(Path.DirectorySeparatorChar) + 1);
                    string name = dbConfig.DatabaseName();
                    if (name == null)
                        name = dbPath;

                    dbConfig.DatabasePath(dbPath);

                    if (controller.IsDatabaseRegistered(name))
                        throw new InvalidOperationException("The database '" + name + "' was already registered.");

                    IDatabase database = CreateDatabase(dbConfig, name);
                    controller.databases[name] = database;

                    if (database.Exists) {
                        var callback = new DatabaseShutdownCallback(controller, database);
                        database.Context.OnShutdown += (callback.Execute);
                    }
                }
            }

            return controller;
        }