Example #1
0
        /// <summary>
        ///     Validates the entites against the database schema
        /// </summary>
        private void CheckSchemaAgainstEntityModels()
        {
            if (!this.SqlConnectionConfiguration.ValidateSchema)
            {
                return;
            }

            if (!this.SqlConnectionConfiguration.SupportsMetadata)
            {
                return;
            }

            if (schemaAlreadyChecked)
            {
                return;
            }

            using var databaseMetadata = new DatabaseMetadata(this.SqlConnectionConfiguration, this.Logger);

            var dataSets = this.GetType()
                           .GetProperties()
                           .Where(x => x.PropertyType.IsGenericType && x.PropertyType.GetGenericTypeDefinition() == typeof(DbSet <>))
                           .ToList();

            foreach (var dataSet in dataSets)
            {
                var entityType = dataSet.PropertyType.GetGenericArguments().Single();

                var tableSchema = "dbo";
                var tableName   = entityType.Name;

                if (dataSet.PropertyType.BaseType == typeof(object))
                {
                    this.Logger.Debug("Skipping DBSet:{0} type:{1} - inhertince validation not supported", dataSet.Name, dataSet.PropertyType.FullName);
                    continue;
                }

                // Get Schema / Table
                var tableAttribute = ReflectionHelper.SingleOrDefaultAttribute <TableAttribute>(entityType);

                if (tableAttribute != null)
                {
                    if (tableAttribute.Schema.IsNotBlank())
                    {
                        tableSchema = tableAttribute.Schema;
                    }

                    tableName = tableAttribute.Name;
                }

                var properties = entityType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

                var tableMeta = databaseMetadata.Table(tableSchema, tableName);

                if (tableMeta == null)
                {
                    var message = FormattableString.Invariant($"Schema.Table : {tableSchema}.{tableName} not found in sql meta data for dbset:{dataSet.Name}");
                    throw new DataException(message);
                }

                foreach (var property in properties)
                {
                    if (!SqlTypeMapping.SupportedCSharpType(property))
                    {
                        this.Logger.Debug("Skipping Property:{0} type:{1}", property.Name, property.PropertyType.FullName);
                        continue;
                    }

                    var columnName = property.Name;

                    var columnAttribute = ReflectionHelper.SingleOrDefaultAttribute <ColumnAttribute>(property);

                    if (columnAttribute != null && columnAttribute.Name.IsNotBlank())
                    {
                        columnName = columnAttribute !.Name;
                    }

                    var columnMeta = tableMeta.Column(columnName);

                    if (columnMeta == null)
                    {
                        var message = FormattableString.Invariant($"Table.Column={tableName}.{columnName} not found for Class.Property={entityType.Name}.{property.Name} type:{property.PropertyType.Name}");
                        throw new DataException(message);
                    }

                    // check if Type matches / compatable
                    if (!SqlTypeMapping.AreTypesCompatible(columnMeta, property))
                    {
                        var message = FormattableString.Invariant($"incompatable data type Class.Property={entityType.Name}.{property.Name} type:{property.PropertyType.Name} Table.Column={tableName}.{columnName} type:{columnMeta.SqlDbType} length:{columnMeta.MaxLength}");
                        throw new DataException(message);
                    }
                }
            }

            schemaAlreadyChecked = true;
        }