mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-09-23 04:43:35 +08:00
Refactoring database components
Simplifying for more direct use-cases --HG-- branch : dev
This commit is contained in:
@@ -64,22 +64,6 @@ namespace Orchard.Tests.Data.Migrations {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void CanConnectShouldBeFalseWhenSqlServerIsInvalid() {
|
|
||||||
var manager = (IDatabaseMigrationManager)new DatabaseMigrationManager();
|
|
||||||
var coordinator = manager.CreateCoordinator("SqlServer", _tempDataFolder, "Data Source=.\\SQLEXPRESS;Initial Catalog=Hello");
|
|
||||||
Assert.That(coordinator.CanConnect(), Is.False);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void CanConnectShouldBeTrueWhenValidSqlServerMdfIsTargetted() {
|
|
||||||
var databasePath = Path.Combine(_tempDataFolder, "Orchard.mdf");
|
|
||||||
CreateSqlServerDatabase(databasePath);
|
|
||||||
|
|
||||||
var manager = (IDatabaseMigrationManager)new DatabaseMigrationManager();
|
|
||||||
var coordinator = manager.CreateCoordinator("SqlServer", _tempDataFolder, "Data Source=.\\SQLEXPRESS;AttachDbFileName=" + databasePath + ";Integrated Security=True;User Instance=True;");
|
|
||||||
Assert.That(coordinator.CanConnect(), Is.True);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void SQLiteSchemaShouldBeGeneratedAndUsable() {
|
public void SQLiteSchemaShouldBeGeneratedAndUsable() {
|
||||||
|
@@ -7,58 +7,34 @@ using FluentNHibernate.Cfg;
|
|||||||
using FluentNHibernate.Cfg.Db;
|
using FluentNHibernate.Cfg.Db;
|
||||||
using FluentNHibernate.Conventions.Helpers;
|
using FluentNHibernate.Conventions.Helpers;
|
||||||
using NHibernate;
|
using NHibernate;
|
||||||
|
using NHibernate.Cfg;
|
||||||
using NHibernate.Tool.hbm2ddl;
|
using NHibernate.Tool.hbm2ddl;
|
||||||
using Orchard.ContentManagement.Records;
|
using Orchard.ContentManagement.Records;
|
||||||
using Orchard.Data.Conventions;
|
using Orchard.Data.Conventions;
|
||||||
using Orchard.Environment;
|
using Orchard.Environment;
|
||||||
|
|
||||||
namespace Orchard.Data.Migrations {
|
namespace Orchard.Data.Migrations {
|
||||||
public abstract class DatabaseCoordinatorBase : IDatabaseCoordinator {
|
public abstract class AbstractSessionFactoryBuilder : ISessionFactoryBuilder {
|
||||||
protected abstract IPersistenceConfigurer GetPersistenceConfigurer();
|
protected abstract IPersistenceConfigurer GetPersistenceConfigurer();
|
||||||
|
|
||||||
public virtual bool CanConnect() {
|
public ISessionFactory BuildSessionFactory(SessionFactoryBuilderParameters parameters) {
|
||||||
try {
|
var database = GetPersistenceConfigurer();
|
||||||
|
var persistenceModel = CreatePersistenceModel(parameters.RecordDescriptors);
|
||||||
|
|
||||||
var sessionFactory = Fluently.Configure()
|
var sessionFactory = Fluently.Configure()
|
||||||
.Database(GetPersistenceConfigurer())
|
.Database(database)
|
||||||
|
.Mappings(m => m.AutoMappings.Add(persistenceModel))
|
||||||
|
.ExposeConfiguration(config => Initialization(parameters, config))
|
||||||
.BuildSessionFactory();
|
.BuildSessionFactory();
|
||||||
try {
|
|
||||||
// attempting to open a session validates a connection can be made
|
return sessionFactory;
|
||||||
var session = sessionFactory.OpenSession();
|
|
||||||
session.Close();
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
sessionFactory.Close();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void CreateDatabase() {
|
private static void Initialization(SessionFactoryBuilderParameters parameters, Configuration configuration) {
|
||||||
// creating a session factory appears to be sufficient for causing a database file to be created for inplace providers
|
if (parameters.UpdateSchema) {
|
||||||
var sessionFactory = Fluently.Configure()
|
var update = new SchemaUpdate(configuration);
|
||||||
.Database(GetPersistenceConfigurer())
|
update.Execute(false/*script*/, true /*doUpdate*/);
|
||||||
.BuildSessionFactory();
|
|
||||||
sessionFactory.Close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateSchema(IEnumerable<RecordDescriptor> recordDescriptors) {
|
|
||||||
var configuration = Fluently.Configure()
|
|
||||||
.Database(GetPersistenceConfigurer())
|
|
||||||
.Mappings(m => m.AutoMappings.Add(CreatePersistenceModel(recordDescriptors)))
|
|
||||||
.BuildConfiguration();
|
|
||||||
|
|
||||||
var updater = new SchemaUpdate(configuration);
|
|
||||||
updater.Execute(true /*script*/, true /*doUpdate*/);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ISessionFactory BuildSessionFactory(IEnumerable<RecordDescriptor> recordDescriptors) {
|
|
||||||
return Fluently.Configure()
|
|
||||||
.Database(GetPersistenceConfigurer())
|
|
||||||
.Mappings(m => m.AutoMappings.Add(CreatePersistenceModel(recordDescriptors)))
|
|
||||||
.BuildSessionFactory();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AutoPersistenceModel CreatePersistenceModel(IEnumerable<RecordDescriptor> recordDescriptors) {
|
public static AutoPersistenceModel CreatePersistenceModel(IEnumerable<RecordDescriptor> recordDescriptors) {
|
||||||
@@ -84,5 +60,6 @@ namespace Orchard.Data.Migrations {
|
|||||||
|
|
||||||
public IEnumerable<Type> GetTypes() { return _recordDescriptors.Select(descriptor => descriptor.Type); }
|
public IEnumerable<Type> GetTypes() { return _recordDescriptors.Select(descriptor => descriptor.Type); }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
11
src/Orchard/Data/Migrations/DatabaseManager.cs
Normal file
11
src/Orchard/Data/Migrations/DatabaseManager.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Orchard.Data.Migrations {
|
||||||
|
public class DatabaseManager : IDatabaseManager {
|
||||||
|
public ISessionFactoryBuilder CreateCoordinator(string provider, string dataFolder, string connectionString) {
|
||||||
|
if (string.Equals(provider, "SQLite", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
return new SQLiteSessionFactoryBuilder(dataFolder, connectionString);
|
||||||
|
return new SqlServerSessionFactoryBuilder(dataFolder, connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,11 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Orchard.Data.Migrations {
|
|
||||||
public class DatabaseMigrationManager : IDatabaseMigrationManager {
|
|
||||||
public IDatabaseCoordinator CreateCoordinator(string provider, string dataFolder, string connectionString) {
|
|
||||||
if (string.Equals(provider, "SQLite", StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
return new SQLiteDatabaseCoordinator(dataFolder, connectionString);
|
|
||||||
return new SqlServerDatabaseCoordinator(dataFolder, connectionString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,19 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using NHibernate;
|
|
||||||
using Orchard.Environment;
|
|
||||||
|
|
||||||
namespace Orchard.Data.Migrations {
|
|
||||||
public interface IDatabaseCoordinator {
|
|
||||||
bool CanConnect();
|
|
||||||
void CreateDatabase();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Should only be called in a development or evaluation environment. Automatic schema migration
|
|
||||||
/// not a really safe practice on production data sources.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="recordDescriptors">Set of known records to be applied</param>
|
|
||||||
void UpdateSchema(IEnumerable<RecordDescriptor> recordDescriptors);
|
|
||||||
|
|
||||||
ISessionFactory BuildSessionFactory(IEnumerable<RecordDescriptor> recordDescriptors);
|
|
||||||
}
|
|
||||||
}
|
|
12
src/Orchard/Data/Migrations/IDatabaseManager.cs
Normal file
12
src/Orchard/Data/Migrations/IDatabaseManager.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
namespace Orchard.Data.Migrations {
|
||||||
|
|
||||||
|
public interface IDatabaseManager : IDependency {
|
||||||
|
ISessionFactoryBuilder CreateCoordinator(DatabaseParameters databaseParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DatabaseParameters {
|
||||||
|
public string Provider { get; set; }
|
||||||
|
public string DataFolder { get; set; }
|
||||||
|
public string ConnectionString { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +0,0 @@
|
|||||||
namespace Orchard.Data.Migrations {
|
|
||||||
public interface IDatabaseMigrationManager : IDependency {
|
|
||||||
IDatabaseCoordinator CreateCoordinator(string provider, string dataFolder, string connectionString);
|
|
||||||
}
|
|
||||||
}
|
|
15
src/Orchard/Data/Migrations/ISessionFactoryBuilder.cs
Normal file
15
src/Orchard/Data/Migrations/ISessionFactoryBuilder.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using NHibernate;
|
||||||
|
using Orchard.Environment;
|
||||||
|
|
||||||
|
namespace Orchard.Data.Migrations {
|
||||||
|
public interface ISessionFactoryBuilder {
|
||||||
|
ISessionFactory BuildSessionFactory(SessionFactoryBuilderParameters parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SessionFactoryBuilderParameters {
|
||||||
|
public IEnumerable<RecordDescriptor> RecordDescriptors { get; set; }
|
||||||
|
public bool CreateDatabase { get; set; }
|
||||||
|
public bool UpdateSchema { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@@ -14,45 +14,56 @@ namespace Orchard.Data {
|
|||||||
public class SessionFactoryHolder : ISessionFactoryHolder {
|
public class SessionFactoryHolder : ISessionFactoryHolder {
|
||||||
private readonly IShellSettings _shellSettings;
|
private readonly IShellSettings _shellSettings;
|
||||||
private readonly ICompositionStrategy _compositionStrategy;
|
private readonly ICompositionStrategy _compositionStrategy;
|
||||||
private readonly IDatabaseMigrationManager _databaseMigrationManager;
|
private readonly IDatabaseManager _databaseManager;
|
||||||
|
|
||||||
private ISessionFactory _sessionFactory;
|
private ISessionFactory _sessionFactory;
|
||||||
|
|
||||||
public SessionFactoryHolder(
|
public SessionFactoryHolder(
|
||||||
IShellSettings shellSettings,
|
IShellSettings shellSettings,
|
||||||
ICompositionStrategy compositionStrategy,
|
ICompositionStrategy compositionStrategy,
|
||||||
IDatabaseMigrationManager databaseMigrationManager) {
|
IDatabaseManager databaseManager) {
|
||||||
_shellSettings = shellSettings;
|
_shellSettings = shellSettings;
|
||||||
_compositionStrategy = compositionStrategy;
|
_compositionStrategy = compositionStrategy;
|
||||||
_databaseMigrationManager = databaseMigrationManager;
|
_databaseManager = databaseManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void UpdateSchema() {
|
public void UpdateSchema() {
|
||||||
var coordinator = GetDatabaseCoordinator();
|
lock (this) {
|
||||||
coordinator.UpdateSchema(_compositionStrategy.GetRecordDescriptors());
|
if (_sessionFactory == null) {
|
||||||
|
_sessionFactory = BuildSessionFactory(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISessionFactory GetSessionFactory() {
|
public ISessionFactory GetSessionFactory() {
|
||||||
lock (this) {
|
lock (this) {
|
||||||
if (_sessionFactory == null) {
|
if (_sessionFactory == null) {
|
||||||
_sessionFactory = BuildSessionFactory();
|
_sessionFactory = BuildSessionFactory(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _sessionFactory;
|
return _sessionFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ISessionFactory BuildSessionFactory() {
|
private ISessionFactory BuildSessionFactory(bool updateSchema) {
|
||||||
var coordinator = GetDatabaseCoordinator();
|
|
||||||
return coordinator.BuildSessionFactory(_compositionStrategy.GetRecordDescriptors());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private IDatabaseCoordinator GetDatabaseCoordinator() {
|
|
||||||
var sitesPath = HostingEnvironment.MapPath("~/App_Data/Sites");
|
var sitesPath = HostingEnvironment.MapPath("~/App_Data/Sites");
|
||||||
var shellPath = Path.Combine(sitesPath, _shellSettings.Name);
|
var shellPath = Path.Combine(sitesPath, _shellSettings.Name);
|
||||||
return _databaseMigrationManager.CreateCoordinator(_shellSettings.DataProvider, shellPath, _shellSettings.DataConnectionString);
|
|
||||||
|
var coordinator = _databaseManager.CreateCoordinator(new DatabaseParameters {
|
||||||
|
Provider = _shellSettings.DataProvider,
|
||||||
|
DataFolder = shellPath,
|
||||||
|
ConnectionString = _shellSettings.DataConnectionString
|
||||||
|
});
|
||||||
|
|
||||||
|
var sessionFactory = coordinator.BuildSessionFactory(new SessionFactoryBuilderParameters {
|
||||||
|
CreateDatabase = false,
|
||||||
|
UpdateSchema = updateSchema,
|
||||||
|
RecordDescriptors = _compositionStrategy.GetRecordDescriptors()
|
||||||
|
});
|
||||||
|
|
||||||
|
return sessionFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user