private static async Task <ImplementationContainer> CreateImplementation(int appInstanceId, IServiceScopeFactory scopeFactory)
 {
     using (var scope = scopeFactory.CreateScope())
         using (var dbContext = scope.ServiceProvider.GetService <MetadataDbContext>())
         {
             return(await ImplementationContainer.Create(scope, dbContext, appInstanceId));
         }
 }
        public static async Task <ImplementationContainer> Create(IServiceScope scope, MetadataDbContext dbContext, int appInstanceId)
        {
            var instance = await dbContext.AppInstances.FirstOrDefaultAsync(x => x.Id == appInstanceId);

            if (instance == null)
            {
                return(null);
            }
            if (!instance.IsEnabled)
            {
                return(null);
            }
            var appType = await dbContext.AppTypes.FirstOrDefaultAsync(x => x.Id == instance.AppTypeId);

            var bundle = await MetadataBundle.FromDbWithoutNavigations(dbContext, instance.AppTypeId, instance.Id);

            bundle.FixupRelationships();
            var metadataCache = new MetadataCache(bundle);
            var metadataModel = new MetadataModel(bundle);
            var globalConfig  = scope.ServiceProvider.GetRequiredService <IOptions <GlobalConfiguration> >().Value;
            var config        = scope.ServiceProvider.GetRequiredService <IConfiguration>();
            var dataConnectionStringTemplate = config.GetConnectionString(instance.DataConnectionStringTemplateName);

            if (string.IsNullOrWhiteSpace(dataConnectionStringTemplate))
            {
                var logger = scope.ServiceProvider.GetRequiredService <ILogger <ImplementationContainer> >();
                logger.LogError($"No connection stirng named \"{instance.DataConnectionStringTemplateName}\" which is required for app instance {instance.Name}");
            }
            var lobConnectionStringTemplate = config.GetConnectionString(instance.LobConnectionStringTemplateName);

            if (string.IsNullOrWhiteSpace(lobConnectionStringTemplate))
            {
                var logger = scope.ServiceProvider.GetRequiredService <ILogger <ImplementationContainer> >();
                logger.LogError($"No connection stirng named \"{instance.LobConnectionStringTemplateName}\" which is required for app instance {instance.Name}");
            }
            InstanceSettings instanceSettings = null;

            globalConfig?.InstanceSettings?.TryGetValue(instance.Name, out instanceSettings);
            var instanceInfo = new InstanceInfo
            {
                AppInstanceId                = appInstanceId,
                AppTypeId                    = appType.Id,
                InstanceName                 = instance.Name,
                Provider                     = instance.DatabaseProviderId,
                DataConnectionString         = GetConnectionString(dataConnectionStringTemplate, instance.MainDatabaseName),
                LobConnectionString          = GetConnectionString(lobConnectionStringTemplate, instance.LobDatabaseName),
                MigrateDatabase              = instance.MigrateDatabase,
                GeneratedCodeNamespace       = instance.GeneratedCodeNamespace,
                DbContextName                = instance.DbContextName,
                InstanceSettings             = instanceSettings,
                LoadBusinessFromAssemblyName = instanceSettings?.LoadBusinessFromAssemblyName,
                SortOrder                    = instance.SortOrder,
            };

            var bridge = new BusinessAssemblyBridge(
                instanceInfo, globalConfig,
                scope.ServiceProvider.GetRequiredService <ILogger <BusinessAssemblyBridge> >());
            var reflector = new BusinessReflector(metadataCache);

            var implementationsContainer = new ImplementationContainer
            {
                Metadata               = metadataCache,
                MetadataModel          = metadataModel,
                BusinessAssemblyBridge = bridge,
                Reflector              = reflector,
                InstanceInfo           = instanceInfo
            };

            switch (instanceInfo.Provider)
            {
            case DatabaseProviderEnum.MySql:
                var mySqlDbContextOptionsBuilder = new DbContextOptionsBuilder <LobToolsDbContext_MySql>();
                implementationsContainer._lobToolsDbContextOptions = mySqlDbContextOptionsBuilder
                                                                     .UseMySql(instanceInfo.LobConnectionString, ServerVersion.AutoDetect(instanceInfo.LobConnectionString)).Options;
                break;

            case DatabaseProviderEnum.SqlServer:
                var lobToolsDbContextOptionsBuilder = new DbContextOptionsBuilder <LobToolsDbContext>();
                implementationsContainer._lobToolsDbContextOptions = lobToolsDbContextOptionsBuilder.UseSqlServer(instanceInfo.LobConnectionString).Options;
                break;

            case DatabaseProviderEnum.PostgreSql:
                var postgreSqlDbContextOptionsBuilder = new DbContextOptionsBuilder <LobToolsDbContext_PostgreSql>();
                implementationsContainer._lobToolsDbContextOptions = postgreSqlDbContextOptionsBuilder.UseNpgsql(instanceInfo.LobConnectionString).Options;
                break;

            default:
                throw new NotImplementedException($"The provider {instanceInfo.Provider} is not implemented");
            }
            if (bridge.BusinessDbContextFactory == null)
            {
                scope.ServiceProvider.GetRequiredService <ILogger <ImplementationContainer> >().LogError($"Business assembly not loaded");
            }
            else
            {
                var dbContextType = bridge.BusinessDbContextFactory.GetType().Assembly.GetTypes().Single(x => x.IsPublic && x.IsSubclassOf(typeof(DbContext)));
                reflector.RegisterAssembly(dbContextType.Assembly);
                var dbContextOptionsBuilder = Activator.CreateInstance(typeof(DbContextOptionsBuilder <>).MakeGenericType(dbContextType)) as DbContextOptionsBuilder;
                switch (instanceInfo.Provider)
                {
                case DatabaseProviderEnum.MySql:
                    implementationsContainer._dbContextOptions = dbContextOptionsBuilder
                                                                 .UseMySql(instanceInfo.DataConnectionString, ServerVersion.AutoDetect(instanceInfo.DataConnectionString)).Options;
                    break;

                case DatabaseProviderEnum.SqlServer:
                    implementationsContainer._dbContextOptions = dbContextOptionsBuilder.UseSqlServer(instanceInfo.DataConnectionString).Options;
                    break;

                case DatabaseProviderEnum.PostgreSql:
                    implementationsContainer._dbContextOptions = dbContextOptionsBuilder.UseNpgsql(instanceInfo.DataConnectionString).Options;
                    break;

                default:
                    throw new NotImplementedException($"The provider {instanceInfo.Provider} is not implemented");
                }
            }
            return(implementationsContainer);
        }
Пример #3
0
        public static async Task <ImplementationContainer> Create(IServiceScope scope, MetadataDbContext dbContext, int appInstanceId)
        {
            var instance = await dbContext.AppInstances.FirstOrDefaultAsync(x => x.Id == appInstanceId);

            if (instance == null)
            {
                return(null);
            }
            if (!instance.IsEnabled)
            {
                return(null);
            }
            var appType = await dbContext.AppTypes.FirstOrDefaultAsync(x => x.Id == instance.AppTypeId);

            var bundle = await MetadataBundle.FromDbWithoutNavigations(dbContext, instance.AppTypeId, instance.Id);

            bundle.FixupRelationships();
            var metadataCache = new MetadataCache(bundle);
            var metadataModel = new MetadataModel(bundle);
            var instanceInfo  = new InstanceInfo
            {
                AppInstanceId    = appInstanceId,
                AppTypeId        = appType.Id,
                InstanceName     = instance.Name,
                Provider         = instance.DatabaseProviderId,
                ConnectionString = instance.DataConnectionString,
                MigrateDatabase  = instance.MigrateDatabase
            };

            var bridge = new BusinessAssemblyBridge(
                instanceInfo,
                scope.ServiceProvider.GetRequiredService <IOptions <GlobalConfiguration> >().Value,
                scope.ServiceProvider.GetRequiredService <ILogger <BusinessAssemblyBridge> >());
            var reflector = new BusinessReflector(metadataCache);

            var implementationsContainer = new ImplementationContainer
            {
                Metadata               = metadataCache,
                MetadataModel          = metadataModel,
                BusinessAssemblyBridge = bridge,
                Reflector              = reflector,
                InstanceInfo           = instanceInfo
            };

            if (bridge.BusinessDbContextFactory == null)
            {
                scope.ServiceProvider.GetRequiredService <ILogger <ImplementationContainer> >().LogError($"Business assembly not loaded");
            }
            else
            {
                var dbContextType = bridge.BusinessDbContextFactory.GetType().Assembly.GetTypes().Single(x => x.IsSubclassOf(typeof(DbContext)));
                reflector.RegisterAssembly(dbContextType.Assembly);
                var dbContextOptionsBuilder = Activator.CreateInstance(typeof(DbContextOptionsBuilder <>).MakeGenericType(dbContextType)) as DbContextOptionsBuilder;
                switch (instanceInfo.Provider)
                {
                case DatabaseProviderEnum.MySql:
                    implementationsContainer._dbContextOptions = dbContextOptionsBuilder.UseMySql(instanceInfo.ConnectionString).Options;
                    break;

                case DatabaseProviderEnum.SqlServer:
                    implementationsContainer._dbContextOptions = dbContextOptionsBuilder.UseSqlServer(instanceInfo.ConnectionString).Options;
                    break;

                default:
                    throw new NotImplementedException($"The provider {instanceInfo.Provider} is not implemented");
                }
            }
            return(implementationsContainer);
        }