Refactoring data builders into data service providers

IDataServicesProviderFactory used to build correct IDataServicesProvider instance
Components implementing IDataServiceProvider must also have public static ProviderName {get;} to be identified
The data service provider, for now, has the responsability of creating the ISessionFactory for a shell

--HG--
branch : dev
This commit is contained in:
Louis DeJardin
2010-06-25 14:41:19 -07:00
parent c35369fabc
commit 4fdecf04c5
21 changed files with 177 additions and 111 deletions

View File

@@ -0,0 +1,22 @@
using System;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using Orchard.Data.Providers;
namespace Orchard.Specs.Hosting {
public class TraceEnabledDataServicesProviderFactory : IDataServicesProviderFactory {
public IDataServicesProvider CreateProvider(DataServiceParameters sessionFactoryParameters) {
return new TraceEnabledBuilder(sessionFactoryParameters.DataFolder, sessionFactoryParameters.ConnectionString);
}
class TraceEnabledBuilder : SQLiteDataServicesProvider {
public TraceEnabledBuilder(string dataFolder, string connectionString) : base(dataFolder, connectionString) {
}
protected override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) {
var config = (SQLiteConfiguration)base.GetPersistenceConfigurer(createDatabase);
//config.ShowSql();
return config;
}
}
}
}

View File

@@ -1,25 +0,0 @@
using FluentNHibernate.Cfg.Db;
using NHibernate;
using Orchard.Data.Builders;
namespace Orchard.Specs.Hosting {
public class TraceEnabledSessionFactoryBuilder : ISessionFactoryBuilder {
public TraceEnabledSessionFactoryBuilder() {
}
public ISessionFactory BuildSessionFactory(SessionFactoryParameters parameters) {
var builder = new TraceEnabledBuilder(parameters.DataFolder, parameters.ConnectionString);
return builder.BuildSessionFactory(parameters);
}
class TraceEnabledBuilder : SQLiteBuilder {
public TraceEnabledBuilder(string dataFolder, string connectionString) : base(dataFolder, connectionString) {
}
protected override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) {
var config = (SQLiteConfiguration)base.GetPersistenceConfigurer(createDatabase);
//config.ShowSql();
return config;
}
}
}
}

View File

@@ -129,7 +129,7 @@
<Compile Include="Bindings\OrchardSiteFactory.cs" />
<Compile Include="Hosting\MessageSink.cs" />
<Compile Include="Hosting\HostingTraceListener.cs" />
<Compile Include="Hosting\TraceEnabledSessionFactoryBuilder.cs" />
<Compile Include="Hosting\TraceEnabledDataServicesProviderFactory.cs" />
<Compile Include="Hosting\Simple.Web\HelloYetAgainHandler.cs" />
<Compile Include="Hosting\RequestExtensions.cs" />
<Compile Include="Hosting\RequestDetails.cs" />

View File

@@ -1,7 +1,9 @@
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using Autofac.Features.Metadata;
using NUnit.Framework;
using Orchard.Data.Builders;
using Orchard.Data.Providers;
using Orchard.Environment.Descriptor;
using Orchard.Environment.Descriptor.Models;
using Orchard.Environment.ShellBuilders.Models;
@@ -50,19 +52,25 @@ namespace Orchard.Tests.Data.Builders {
[Test]
public void SQLiteSchemaShouldBeGeneratedAndUsable() {
var recordDescriptors = new[] {
new RecordBlueprint {TableName = "Hello", Type = typeof (FooRecord)}
};
var manager = (ISessionFactoryBuilder)new SessionFactoryBuilder();
new RecordBlueprint {TableName = "Hello", Type = typeof (FooRecord)}
};
var manager = (IDataServicesProviderFactory) new DataServicesProviderFactory(new[] {
new Meta<CreateDataServicesProvider>(
(dataFolder, connectionString) => new SQLiteDataServicesProvider(dataFolder, connectionString),
new Dictionary<string, object> {{"ProviderName", "SQLite"}})
});
var sessionFactory = manager.BuildSessionFactory(new SessionFactoryParameters {
Provider = "SQLite",
DataFolder = _tempDataFolder,
UpdateSchema = true,
RecordDescriptors = recordDescriptors
});
Provider = "SQLite",
DataFolder = _tempDataFolder,
UpdateSchema = true,
RecordDescriptors = recordDescriptors
});
var session = sessionFactory.OpenSession();
var foo = new FooRecord { Name = "hi there" };
var foo = new FooRecord {Name = "hi there"};
session.Save(foo);
session.Flush();
session.Close();
@@ -82,14 +90,18 @@ namespace Orchard.Tests.Data.Builders {
new RecordBlueprint {TableName = "Hello", Type = typeof (FooRecord)}
};
var manager = (ISessionFactoryBuilder)new SessionFactoryBuilder();
var manager = (IDataServicesProviderFactory)new DataServicesProviderFactory(new[] {
new Meta<CreateDataServicesProvider>(
(dataFolder, connectionString) => new SqlServerDataServicesProvider(dataFolder, connectionString),
new Dictionary<string, object> {{"ProviderName", "SqlServer"}})
});
var sessionFactory = manager.BuildSessionFactory(new SessionFactoryParameters {
Provider = "SqlServer",
DataFolder = _tempDataFolder,
ConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFileName=" + databasePath + ";Integrated Security=True;User Instance=True;",
UpdateSchema = true,
RecordDescriptors = recordDescriptors,
});
Provider = "SqlServer",
DataFolder = _tempDataFolder,
ConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFileName=" + databasePath + ";Integrated Security=True;User Instance=True;",
UpdateSchema = true,
RecordDescriptors = recordDescriptors,
});

View File

@@ -8,7 +8,7 @@ using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Tool.hbm2ddl;
using Orchard.Data;
using Orchard.Data.Builders;
using Orchard.Data.Providers;
using Orchard.Environment.Descriptor.Models;
using Orchard.Environment.ShellBuilders.Models;
@@ -19,7 +19,7 @@ namespace Orchard.Tests {
//var persistenceModel = AutoMap.Source(new Types(types))
// .Alterations(alt => AddAlterations(alt, types))
// .Conventions.AddFromAssemblyOf<DataModule>();
var persistenceModel = AbstractBuilder.CreatePersistenceModel(types.Select(t => new RecordBlueprint { TableName = "Test_" + t.Name,Type = t }));
var persistenceModel = AbstractDataServicesProvider.CreatePersistenceModel(types.Select(t => new RecordBlueprint { TableName = "Test_" + t.Name,Type = t }));
return Fluently.Configure()
.Database(SQLiteConfiguration.Standard.UsingFile(fileName).ShowSql())

View File

@@ -14,7 +14,7 @@ using (Html.BeginFormAntiForgeryPost()) { %>
<%:Html.TextBoxFor(m => m.Name, new {@class = "textMedium", disabled = "disabled"}) %>
<%:Html.HiddenFor(m => m.Name) %>
</fieldset>
<% Html.RenderTemplate(Model.Templates); %>
<% Html.RenderTemplates(Model.Templates); %>
<h2><%:T("Parts") %></h2>
<div class="manage add-to-type"><%: Html.ActionLink(T("Add").Text, "AddPart", new { }, new { @class = "button" }) %></div>
<%:Html.EditorFor(m => m.Parts, "Parts", "") %>

View File

@@ -12,7 +12,7 @@
<button type="submit" title="<%:T("Remove") %>"><%:T("Remove") %></button>
<% } %> --%>
</div>
<% Html.RenderTemplate(Model.Templates); %>
<% Html.RenderTemplates(Model.Templates); %>
<h4><%:T("Global configuration") %></h4>
<div class="manage minor"><%:Html.ActionLink(T("Edit").Text, "EditPart", new { area = "Orchard.ContentTypes", id = Model.PartDefinition.Name }) %></div>

View File

@@ -8,7 +8,7 @@ using Orchard.Commands.Builtin;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Data.Builders;
using Orchard.Data.Providers;
using Orchard.Environment.Extensions;
using Orchard.Localization;
using Orchard.Mvc;
@@ -41,7 +41,7 @@ namespace Orchard.Setup {
builder.RegisterType<PageClassBuilder>().As<IPageClassBuilder>().InstancePerLifetimeScope();
builder.RegisterType<Notifier>().As<INotifier>().InstancePerLifetimeScope();
builder.RegisterType<NotifyFilter>().As<IFilterProvider>().InstancePerLifetimeScope();
builder.RegisterType<SessionFactoryBuilder>().As<ISessionFactoryBuilder>().InstancePerLifetimeScope();
builder.RegisterType<DataServicesProviderFactory>().As<IDataServicesProviderFactory>().InstancePerLifetimeScope();
builder.RegisterType<DefaultCommandManager>().As<ICommandManager>().InstancePerLifetimeScope();
builder.RegisterType<HelpCommand>().As<ICommandHandler>().InstancePerLifetimeScope();

View File

@@ -1,23 +0,0 @@
using System.Collections.Generic;
using NHibernate;
using Orchard.Environment.Descriptor;
using Orchard.Environment.Descriptor.Models;
using Orchard.Environment.ShellBuilders.Models;
namespace Orchard.Data.Builders {
public interface ISessionFactoryBuilder : IDependency {
ISessionFactory BuildSessionFactory(SessionFactoryParameters sessionFactoryParameters);
}
public class SessionFactoryParameters {
public string Provider { get; set; }
public string DataFolder { get; set; }
public string ConnectionString { get; set; }
public bool CreateDatabase { get; set; }
public bool UpdateSchema { get; set; }
public IEnumerable<RecordBlueprint> RecordDescriptors { get; set; }
}
}

View File

@@ -1,17 +0,0 @@
using System;
using NHibernate;
namespace Orchard.Data.Builders {
public class SessionFactoryBuilder : ISessionFactoryBuilder {
public ISessionFactory BuildSessionFactory(SessionFactoryParameters parameters) {
AbstractBuilder builder;
if (string.Equals(parameters.Provider, "SQLite", StringComparison.InvariantCultureIgnoreCase)) {
builder = new SQLiteBuilder(parameters.DataFolder, parameters.ConnectionString);
}
else {
builder = new SqlServerBuilder(parameters.DataFolder, parameters.ConnectionString);
}
return builder.BuildSessionFactory(parameters);
}
}
}

View File

@@ -1,9 +1,21 @@
using Autofac;
using System.Reflection;
using Autofac;
using Orchard.Data.Providers;
using Module = Autofac.Module;
namespace Orchard.Data {
public class DataModule : Module {
protected override void Load(ContainerBuilder builder) {
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerDependency();
}
protected override void AttachToComponentRegistration(Autofac.Core.IComponentRegistry componentRegistry, Autofac.Core.IComponentRegistration registration) {
if (typeof(IDataServicesProvider).IsAssignableFrom(registration.Activator.LimitType)) {
var propertyInfo = registration.Activator.LimitType.GetProperty("ProviderName", BindingFlags.Static | BindingFlags.Public);
if (propertyInfo != null) {
registration.Metadata["ProviderName"] = propertyInfo.GetValue(null, null);
}
}
}
}
}

View File

@@ -11,12 +11,11 @@ using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using Orchard.ContentManagement.Records;
using Orchard.Data.Conventions;
using Orchard.Environment.Descriptor;
using Orchard.Environment.Descriptor.Models;
using Orchard.Environment.ShellBuilders.Models;
namespace Orchard.Data.Builders {
public abstract class AbstractBuilder {
namespace Orchard.Data.Providers {
public abstract class AbstractDataServicesProvider : IDataServicesProvider {
protected abstract IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase);
public ISessionFactory BuildSessionFactory(SessionFactoryParameters parameters) {
@@ -67,5 +66,7 @@ namespace Orchard.Data.Builders {
public IEnumerable<Type> GetTypes() { return _recordDescriptors.Select(descriptor => descriptor.Type); }
}
}
}

View File

@@ -0,0 +1,7 @@
namespace Orchard.Data.Providers {
public class DataServiceParameters {
public string Provider { get; set; }
public string DataFolder { get; set; }
public string ConnectionString { get; set; }
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using Autofac.Features.Metadata;
namespace Orchard.Data.Providers {
public delegate IDataServicesProvider CreateDataServicesProvider(string dataFolder, string connectionString);
public class DataServicesProviderFactory : IDataServicesProviderFactory {
private readonly IEnumerable<Meta<CreateDataServicesProvider>> _providers;
public DataServicesProviderFactory(IEnumerable<Meta<CreateDataServicesProvider>> providers) {
_providers = providers;
}
public IDataServicesProvider CreateProvider(DataServiceParameters parameters) {
var factory = GetProviderFactory(parameters.Provider) ?? GetProviderFactory("SqlServer");
return factory != null ? factory(parameters.DataFolder, parameters.ConnectionString) : null;
}
CreateDataServicesProvider GetProviderFactory(string providerName) {
foreach (var providerMeta in _providers) {
object name;
if (!providerMeta.Metadata.TryGetValue("ProviderName", out name)) {
continue;
}
if (string.Equals(Convert.ToString(name), providerName, StringComparison.OrdinalIgnoreCase)) {
return providerMeta.Value;
}
}
return null;
}
}
}

View File

@@ -0,0 +1,7 @@
using NHibernate;
namespace Orchard.Data.Providers {
public interface IDataServicesProvider : ITransientDependency {
ISessionFactory BuildSessionFactory(SessionFactoryParameters sessionFactoryParameters);
}
}

View File

@@ -0,0 +1,14 @@
using NHibernate;
namespace Orchard.Data.Providers {
public interface IDataServicesProviderFactory : IDependency {
IDataServicesProvider CreateProvider(DataServiceParameters sessionFactoryParameters);
}
public static class IDataServicesProviderSelectorExtensions {
public static ISessionFactory BuildSessionFactory(this IDataServicesProviderFactory factory, SessionFactoryParameters sessionFactoryParameters) {
var provider = factory.CreateProvider(sessionFactoryParameters);
return provider != null ? provider.BuildSessionFactory(sessionFactoryParameters) : null;
}
}
}

View File

@@ -1,16 +1,20 @@
using System.IO;
using FluentNHibernate.Cfg.Db;
namespace Orchard.Data.Builders {
public class SQLiteBuilder : AbstractBuilder {
namespace Orchard.Data.Providers {
public class SQLiteDataServicesProvider : AbstractDataServicesProvider {
private readonly string _dataFolder;
private readonly string _connectionString;
public SQLiteBuilder(string dataFolder, string connectionString) {
public SQLiteDataServicesProvider(string dataFolder, string connectionString) {
_dataFolder = dataFolder;
_connectionString = connectionString;
}
public static string ProviderName {
get { return "SQLite"; }
}
protected override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) {
var persistence = SQLiteConfiguration.Standard;
if (string.IsNullOrEmpty(_connectionString)) {

View File

@@ -0,0 +1,10 @@
using System.Collections.Generic;
using Orchard.Environment.ShellBuilders.Models;
namespace Orchard.Data.Providers {
public class SessionFactoryParameters : DataServiceParameters {
public IEnumerable<RecordBlueprint> RecordDescriptors { get; set; }
public bool CreateDatabase { get; set; }
public bool UpdateSchema { get; set; }
}
}

View File

@@ -1,17 +1,21 @@
using System;
using FluentNHibernate.Cfg.Db;
namespace Orchard.Data.Builders {
public class SqlServerBuilder : AbstractBuilder {
namespace Orchard.Data.Providers {
public class SqlServerDataServicesProvider : AbstractDataServicesProvider {
private readonly string _dataFolder;
private readonly string _connectionString;
public SqlServerBuilder(string dataFolder, string connectionString) {
public SqlServerDataServicesProvider(string dataFolder, string connectionString) {
_dataFolder = dataFolder;
_connectionString = connectionString;
}
public static string ProviderName {
get { return "SqlServer"; }
}
protected override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) {
var persistence = MsSqlConfiguration.MsSql2008;
if (string.IsNullOrEmpty(_connectionString)) {

View File

@@ -1,7 +1,7 @@
using System;
using System.IO;
using NHibernate;
using Orchard.Data.Builders;
using Orchard.Data.Providers;
using Orchard.Environment.Configuration;
using Orchard.Environment.Descriptor;
using Orchard.Environment.Descriptor.Models;
@@ -20,7 +20,7 @@ namespace Orchard.Data {
public class SessionFactoryHolder : ISessionFactoryHolder {
private readonly ShellSettings _shellSettings;
private readonly ShellBlueprint _shellBlueprint;
private readonly ISessionFactoryBuilder _sessionFactoryBuilder;
private readonly IDataServicesProviderFactory _dataServicesProviderFactory;
private readonly IAppDataFolder _appDataFolder;
private ISessionFactory _sessionFactory;
@@ -28,11 +28,11 @@ namespace Orchard.Data {
public SessionFactoryHolder(
ShellSettings shellSettings,
ShellBlueprint shellBlueprint,
ISessionFactoryBuilder sessionFactoryBuilder,
IDataServicesProviderFactory dataServicesProviderFactory,
IAppDataFolder appDataFolder) {
_shellSettings = shellSettings;
_shellBlueprint = shellBlueprint;
_sessionFactoryBuilder = sessionFactoryBuilder;
_dataServicesProviderFactory = dataServicesProviderFactory;
_appDataFolder = appDataFolder;
T = NullLocalizer.Instance;
@@ -81,7 +81,7 @@ namespace Orchard.Data {
var shellFolder = _appDataFolder.MapPath(shellPath);
var sessionFactory = _sessionFactoryBuilder.BuildSessionFactory(new SessionFactoryParameters {
var sessionFactory = _dataServicesProviderFactory.BuildSessionFactory(new SessionFactoryParameters {
Provider = _shellSettings.DataProvider,
DataFolder = shellFolder,
ConnectionString = _shellSettings.DataConnectionString,

View File

@@ -388,6 +388,9 @@
<Compile Include="DataMigration\Schema\CreateTableCommand.cs" />
<Compile Include="DataMigration\Schema\TableCommand.cs" />
<Compile Include="DataMigration\Schema\SchemaCommand.cs" />
<Compile Include="Data\Providers\DataServiceParameters.cs" />
<Compile Include="Data\Providers\IDataServicesProvider.cs" />
<Compile Include="Data\Providers\SessionFactoryParameters.cs" />
<Compile Include="Data\SessionLocator.cs" />
<Compile Include="Data\IRepository.cs" />
<Compile Include="Data\ISessionLocator.cs" />
@@ -501,11 +504,11 @@
<Compile Include="Commands\OrchardSwitchAttribute.cs" />
<Compile Include="Commands\OrchardSwitchesAttribute.cs" />
<Compile Include="Data\Conventions\RecordTableNameConvention.cs" />
<Compile Include="Data\Builders\AbstractBuilder.cs" />
<Compile Include="Data\Builders\SessionFactoryBuilder.cs" />
<Compile Include="Data\Builders\ISessionFactoryBuilder.cs" />
<Compile Include="Data\Builders\SQLiteBuilder.cs" />
<Compile Include="Data\Builders\SqlServerBuilder.cs" />
<Compile Include="Data\Providers\AbstractDataServicesProvider.cs" />
<Compile Include="Data\Providers\DataServicesProviderFactory.cs" />
<Compile Include="Data\Providers\IDataServicesProviderFactory.cs" />
<Compile Include="Data\Providers\SQLiteDataServicesProvider.cs" />
<Compile Include="Data\Providers\SqlServerDataServicesProvider.cs" />
<Compile Include="Data\Conventions\StringLengthConvention.cs" />
<Compile Include="Data\SessionFactoryHolder.cs" />
<Compile Include="Environment\AutofacUtil\LifetimeScopeContainer.cs" />