|
|
@@ -0,0 +1,77 @@
|
|
|
+using Inversion;
|
|
|
+using InvercargillSql;
|
|
|
+using InvercargillSql.Dialects;
|
|
|
+using InvercargillSql.Migrations;
|
|
|
+using InvercargillSql.Orm;
|
|
|
+using InvercargillSql.Orm.Projections;
|
|
|
+
|
|
|
+namespace InvercargillSqlInversion {
|
|
|
+
|
|
|
+ public delegate void EntityMapperFactoryFunc<T>(EntityMapperBuilder<T> cfg);
|
|
|
+ public delegate void ProjectionFactoryFunc<T>(ProjectionBuilder<T> cfg) throws Error;
|
|
|
+
|
|
|
+ public class DatabaseConfigurator : Object {
|
|
|
+
|
|
|
+ private Container container = inject<Container>();
|
|
|
+
|
|
|
+ public void register_connection(string connection_string, Lifecycle? lifecycle = null) throws Error {
|
|
|
+ var cs = ConnectionString.parse(connection_string);
|
|
|
+
|
|
|
+ // Auto-detect lifecycle if not specified
|
|
|
+ var effective_lifecycle = lifecycle ?? detect_lifecycle(cs);
|
|
|
+
|
|
|
+ // Register the connection
|
|
|
+ container.register<Connection>(() => ConnectionFactory.create_and_open(connection_string), effective_lifecycle);
|
|
|
+
|
|
|
+ // Register the dialect provider
|
|
|
+ container.register_transient<SqlDialect>(() => DialectFactory.create_from_string(connection_string));
|
|
|
+
|
|
|
+ // Register the migration runner
|
|
|
+ container.register_transient<MigrationRunner>(s => new MigrationRunner(s.resolve<Connection>(), s.resolve<SqlDialect>()));
|
|
|
+
|
|
|
+ // Register the type registry
|
|
|
+ container.register_singleton<InversionTypeProvider>()
|
|
|
+ .as<TypeProvider>();
|
|
|
+
|
|
|
+ // Register the orm session
|
|
|
+ container.register<OrmSession>(s => new OrmSession(s.resolve<Connection>(), s.resolve<TypeProvider>(), s.resolve<SqlDialect>()), effective_lifecycle);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public void add_migration<T>(TypedFactoryDelegate<T>? factory_func = null) {
|
|
|
+ container.register_transient<T>(factory_func)
|
|
|
+ .as<Migration>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void add_entity<T>(owned EntityMapperFactoryFunc<T> configuration_func) throws Error {
|
|
|
+ container.register_transient<EntityMapper>(s => {
|
|
|
+ var dialect = s.resolve<SqlDialect>();
|
|
|
+ var connection = s.resolve<Connection>();
|
|
|
+ var builder = new EntityMapperBuilder<T>();
|
|
|
+ configuration_func(builder);
|
|
|
+ var schema = dialect.introspect_schema(connection, builder.peek_table());
|
|
|
+ return builder.build_with_schema(schema);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ public void add_projection<T>(owned ProjectionFactoryFunc<T> configuration_func) throws Error {
|
|
|
+ container.register_transient<ProjectionDefinition>(s => {
|
|
|
+ var type_provider = s.resolve<TypeProvider>();
|
|
|
+ var builder = new ProjectionBuilder<T>(type_provider);
|
|
|
+ configuration_func(builder);
|
|
|
+ return builder.build();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ public void migrate_on_startup() {
|
|
|
+ container.register_startup<MigrationStartupService>();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private static Lifecycle detect_lifecycle(ConnectionString cs) {
|
|
|
+ bool is_in_memory = cs.database == ":memory:" ||
|
|
|
+ (cs.has_option("mode") && cs.get_option("mode") == "memory");
|
|
|
+ return is_in_memory ? Lifecycle.SINGLETON : Lifecycle.SCOPED;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|