/// <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; }