public async Task <ActionResult> ReleaseMetadata(ReleaseMetadataRequest request)
        {
            if (!_permissionService.IsAllowed(new ActionRequestInfo(HttpContext, _implementationContainer, null, ActionTypeEnum.ManageMetadata)))
            {
                return(Unauthorized());
            }
            var appInstance = await _dbContext.AppInstances.SingleAsync(X => X.Id == request.AppInstanceId);

            var appType = await _dbContext.AppTypes.SingleAsync(x => x.Id == appInstance.AppTypeId);

            var bundle = await MetadataBundle.FromDbWithoutNavigations(_dbContext, appType.Id, appInstance.Id);

            var json   = JsonConvert.SerializeObject(bundle);
            var zipped = TextHelper.Zip(json);

            var release = new MetadataRelease
            {
                AppTypeId            = appType.Id,
                CreatedByUserId      = 0,            //Todo: How to get this value?
                ReleaseTime          = DateTime.UtcNow,
                MetadataSnapshotText = json,
                Version     = request.Version,
                VersionCode = request.VersionCode
            };
            await _dbContext.MetadataReleases.AddAsync(release);

            if (request.SetAsInstanceMetadata)
            {
                appInstance.MetadataRelease = release;
            }
            await _dbContext.SaveChangesAsync();

            return(Ok());
        }
Esempio n. 2
0
        public async Task <ActionResult <MetadataValidationResponse> > GenerateCode()
        {
            if (!_permissionService.IsAllowed(new ActionRequestInfo(HttpContext, _implementationContainer, null, ActionTypeEnum.ManageMetadata)))
            {
                return(Unauthorized());
            }
            var bundle = await MetadataBundle.FromDbWithoutNavigations(_dbContext
                                                                       , _implementationContainer.InstanceInfo.AppTypeId, _implementationContainer.InstanceInfo.AppInstanceId);

            bundle.FixupRelationships();
            var metadataCache = new MetadataCache(bundle);
            var errorList     = await GenerateCodeValidation();

            var result = new MetadataValidationResponse();

            if (errorList.Value?.Success != true)
            {
                return(errorList);
            }

            var(succeeded, diagnostics) = await _assemblyGenerator.GenerateAssembly(metadataCache, _implementationContainer.InstanceInfo
                                                                                    , _globalConfiguration.ImplementationsDirectory, _implementationContainer.InstanceInfo.InstanceName);

            if (!succeeded)
            {
                result.Errors.AddRange(diagnostics.Select(x => x.Message));
                result.Success = false;
                return(result);
            }
            result.Success = true;
            return(result);
        }
Esempio n. 3
0
 private void LoadPropertyGeneralUsageCategories(MetadataBundle bundle)
 {
     _propertyGeneralUsageCategories = bundle.PropertyGeneralUsageCategories.ToDictionary
                                       (
         x => x.Id,
         x => new PropertyGeneralUsageCategoryStruct
     {
         PropertyGeneralUsageCategoryId = x.Id,
         Name = x.Name
     }
                                       );
 }
Esempio n. 4
0
 private void LoadEntityGeneralUsageCategories(MetadataBundle bundle)
 {
     _entityGeneralUsageCategories = bundle.EntityTypeGeneralUsageCategories.ToDictionary
                                     (
         x => x.Id,
         x => new EntityGeneralUsageCategoryStruct
     {
         EntityGeneralUsageCategoryId = x.Id,
         Name = x.Name
     }
                                     );
 }
Esempio n. 5
0
 public MetadataModel(MetadataBundle bundle)
 {
     AdditionalBehaviors = bundle.AdditionalBehaviors.ToDictionary(x => x.Name,
                                                                   x => new AdditionalBehaviorMetadata
     {
         Definition = x.Definition,
         Name       = x.Name
     });
     PropertyDefaults = bundle.PropertyFacetDefaultValues
                        .GroupBy(x => x.GeneralUsageCategory.Name)
                        .Select(x => new PropertyGeneralUsageCategory
     {
         Name     = x.Key,
         Defaults = x
                    .Select(y => PropertyFacet.Create(y))
                    .ToDictionary(y => y.Name, y => y)
     }).ToDictionary(x => x.Name, x => x as IPropertyGeneralUsageCategory);
     EntityTypes = bundle.EntityTypes.Select(x =>
                                             new EntityMetadata
     {
         Name       = x.Name,
         SchemaName = x.SchemaName,
         EntityGeneralUsageCategoryId = x.GeneralUsageCategoryId,
         SingularTitle   = x.SingularTitle,
         PluralTitle     = x.PluralTitle,
         DisplayNamePath = x.DisplayNamePath,
         CodePath        = x.CodePath,
         PrimaryKeyPath  = x.Properties?.FirstOrDefault(p => p.GeneralUsageCategoryId == 2)?.Name,                        //TODO: Unsafe
         Properties      = x.Properties?.Select(p =>
                                                new PropertyMetadata
         {
             Name           = p.Name,
             GeneralUsage   = p.GeneralUsageCategory.Name,
             DataType       = p.DataType.Identifier,
             EntityTypeName = p.DataEntityType?.Name,
             LocalFacets    = p.PropertyFacetValues
                              ?.Select(v => PropertyFacet.Create(v))
                              ?.ToDictionary(v => v.Name, v => v),
             ForeignKeyName      = p.ForeignKeyProperty?.Name,
             InversePropertyName = p.InverseProperty?.Name,
             Title        = p.Title,
             IsNullable   = p.IsNullable,
             IsExpression = p.IsExpression,
             Behaviors    = p.PropertyBehaviors?.Select(x => new PropertyBehaviorMetadata
             {
                 BehaviorName = x.AdditionalBehavior.Name,
                 Parameters   = x.Parameters
             })?.ToList()
         }).ToDictionary(p => p.Name, p => p)
     }).ToDictionary(x => x.Name, x => x as IEntityTypeMetadataModel);
 }
        public async Task <ActionResult <MetadataValidationResponse> > GenerateCode()
        {
            if (!_permissionService.IsAllowed(new ActionRequestInfo(HttpContext, _implementationContainer, null, ActionTypeEnum.ManageMetadata)))
            {
                return(Unauthorized());
            }
            var bundle = await MetadataBundle.FromDbWithoutNavigations(_dbContext
                                                                       , _implementationContainer.InstanceInfo.AppTypeId, _implementationContainer.InstanceInfo.AppInstanceId);

            bundle.FixupRelationships();
            var metadataCache = new MetadataCache(bundle);
            var errorList     = await GenerateCodeValidation();

            var result = new MetadataValidationResponse();

            if (errorList.Value?.Success != true)
            {
                return(errorList);
            }

            var r = await _assemblyGenerator.GenerateCode(metadataCache, _implementationContainer.InstanceInfo
                                                          , _globalConfiguration.ImplementationsDirectory, _implementationContainer.InstanceInfo.InstanceName);

            if (!r.Succeeded)
            {
                result.Errors.AddRange(r.Diagnostics.Select(x => x.Message));
                result.Success = false;
                return(result);
            }
            var copyFileName = _implementationContainer.InstanceInfo.InstanceSettings?.CopyAutoGeneratedEntitiesTo;

            if (!string.IsNullOrWhiteSpace(copyFileName))
            {
                try
                {
                    System.IO.File.Copy(r.SourceCodeFileName, copyFileName, true);
                }
                catch (Exception ex)
                {
                    result.Errors.Add("Could not copy source code to: " + copyFileName + "Reson: " + ex.GetFullMessage());
                }
            }
            result.Success = true;
            return(result);
        }
Esempio n. 7
0
        public MetadataCache(MetadataBundle bundle)
        {
            _dataTypesByIndetifier = bundle.DataTypes.ToDictionary(x => x.Identifier);
            LoadEntityGeneralUsageCategories(bundle);
            LoadPropertyGeneralUsageCategories(bundle);

            if (!_facetsDefined)
            {
                _facetsDefined = true;
                EntityTypeMetadata.DefineFacets(bundle.EntityTypeFacetDefinitions);
                PropertyMetadata.DefineFacets(bundle.PropertyFacetDefinitions);

                foreach (var defaultValue in bundle.PropertyFacetDefaultValues)
                {
                    (PropertyMetadata._facets[defaultValue.FacetDefinitionId] as IMetadataFacet <PropertyGeneralUsageCategoryStruct>)
                    .AddDefaultValue(GetPropertyGeneralUsageCategory(defaultValue.GeneralUsageCategoryId), defaultValue.DefaultValue);
                }

                foreach (var defaultValue in bundle.EntityTypeFacetDefaultValues)
                {
                    (EntityTypeMetadata._facets[defaultValue.GeneralUsageCategoryId] as IMetadataFacet <EntityGeneralUsageCategoryStruct>)
                    .AddDefaultValue(GetEntityGeneralUsageCategory(defaultValue.GeneralUsageCategoryId), defaultValue.DefaultValue);
                }
            }

            var map = new Dictionary <int, PropertyMetadata>();

            foreach (var dbEntityMetadata in bundle.EntityTypes)
            {
                var entityTypeMetadata = new EntityTypeMetadata(dbEntityMetadata, null);
                foreach (var dbPropertyMetadata in dbEntityMetadata.Properties ?? Enumerable.Empty <Property>())
                {
                    var propertyMetadata = new PropertyMetadata(this, dbPropertyMetadata.Name, entityTypeMetadata, new PropertyGeneralUsageCategoryStruct
                    {
                        PropertyGeneralUsageCategoryId = dbPropertyMetadata.GeneralUsageCategoryId,
                        Name = dbPropertyMetadata.GeneralUsageCategory.Name
                    }, dbPropertyMetadata.DataType, dbPropertyMetadata.IsNullable, dbPropertyMetadata.IsExpression, dbPropertyMetadata.Title,
                                                                dbPropertyMetadata.ExpressionDefinition?.Identifier, dbPropertyMetadata.PropertyBehaviors)
                    {
                        EntityTypeName = dbPropertyMetadata.DataEntityType?.Name
                    };
                    map.Add(dbPropertyMetadata.Id, propertyMetadata);

                    if (dbPropertyMetadata.PropertyFacetValues != null)
                    {
                        foreach (var facetValue in dbPropertyMetadata.PropertyFacetValues)
                        {
                            dynamic facet = PropertyMetadata._facets[facetValue.FacetDefinitionId];
                            propertyMetadata.SetValue(facet, facetValue.Value);
                        }
                    }
                }

                if (dbEntityMetadata.FacetValues != null)
                {
                    foreach (var facetValue in dbEntityMetadata.FacetValues)
                    {
                        dynamic facet = EntityTypeMetadata._facets[facetValue.FacetDefinitionId];
                        entityTypeMetadata.SetValue(facet, facetValue.Value);
                    }
                }

                _entityTypesByName.Add(dbEntityMetadata.Name, entityTypeMetadata);
                _entityTypesById.Add(dbEntityMetadata.Id, entityTypeMetadata);
            }

            foreach (var property in bundle.EntityTypes.Where(x => x.Properties != null).SelectMany(x => x.Properties))
            {
                if (property.ForeignKeyPropertyId.HasValue)
                {
                    map[property.Id].ForeignKey = map[property.ForeignKeyPropertyId.Value];
                }
                if (property.InversePropertyId.HasValue)
                {
                    map[property.Id].InverseProperty = map[property.InversePropertyId.Value];
                }
            }

            foreach (var entityType in bundle.EntityTypes.Where(x => x.BaseEntityTypeId.HasValue))
            {
                _entityTypesByName[entityType.Name].BaseEntityType = _entityTypesByName[entityType.BaseEntityType.Name];
            }

            _expressions = new Dictionary <string, ExpressionInfo>();
            foreach (var expressionDefiniction in bundle.ExpressionDefinitions)
            {
                _expressions.Add(expressionDefiniction.Identifier, new ExpressionInfo
                {
                    MainInputEntityTypeName = expressionDefiniction.MainInputEntityType.Name
                });
            }

            foreach (var body in bundle.ExpressionBodies)
            {
                if (!_expressions.TryGetValue(body.Definition.Identifier, out var info))
                {
                    continue;
                }
                info.Format = body.FormatId;
                info.Body   = body.Body;
            }
        }
        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);
        }
Esempio n. 9
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);
        }