/// <summary> /// Generate migration /// </summary> /// <param name="entityType"></param> /// <param name="ddlStatement"></param> /// <param name="propertyFilter"></param> /// <returns></returns> public static string GenerateTableMigration(Type entityType, DdlStatement ddlStatement, Func <PropertyInfo, bool> propertyFilter) { var sb = new StringBuilder(); // todo: handle this case: OrganisationUnit -> OrganisationBase<OrganisationUnit> (parent prop here) -> OrganisationBase var isRoot = MappingHelper.IsRootEntity(entityType); switch (ddlStatement) { case DdlStatement.Create: { var props = GetPersistedProperties(entityType, !isRoot); if (propertyFilter != null) { props = props.Where(p => propertyFilter.Invoke(p)).ToList(); } if (props.Any() || isRoot) { sb.AppendLine($" // {entityType.FullName}"); sb.Append($@" Create.Table(""{MappingHelper.GetTableName(entityType)}"")"); AddColumns(sb, props, ddlStatement); var discriminatorColumn = MappingHelper.GetDiscriminatorColumn(entityType); if (!string.IsNullOrWhiteSpace(discriminatorColumn)) { sb.AppendLine(); sb.Append($@" .{nameof(SheshaFluentMigratorExtensions.WithDiscriminator)}()"); } sb.AppendLine(";"); } break; } case DdlStatement.Alter: { var props = GetPersistedProperties(entityType, !isRoot); if (propertyFilter != null) { props = props.Where(p => propertyFilter.Invoke(p)).ToList(); } if (props.Any()) { sb.AppendLine($" // {entityType.FullName}"); sb.Append($@" Alter.Table(""{MappingHelper.GetTableName(entityType)}"")"); AddColumns(sb, props, ddlStatement); sb.AppendLine(";"); } break; } } return(sb.ToString()); }
public int ExecuteDDL(DdlStatement ddlStatement) { return(ExecuteNonQuery(ddlStatement)); }
/// <summary> /// Process framework helpers and return list of unprocessed properties /// </summary> /// <param name="sb"></param> /// <param name="properties"></param> /// <param name="statement"></param> /// <returns></returns> private static List <PropertyInfo> ProcessFrameworkColumns(StringBuilder sb, List <PropertyInfo> properties, DdlStatement statement) { var helpers = new Dictionary <string, List <string> >() { { nameof(SheshaFluentMigratorExtensions.WithFullAuditColumns), new List <string> { nameof(ISoftDelete.IsDeleted), nameof(IDeletionAudited.DeleterUserId), nameof(IHasDeletionTime.DeletionTime), nameof(ICreationAudited.CreatorUserId), nameof(IHasCreationTime.CreationTime), nameof(IModificationAudited.LastModifierUserId), nameof(IHasModificationTime.LastModificationTime) } }, { nameof(SheshaFluentMigratorExtensions.WithAuditColumns), new List <string> { nameof(ICreationAudited.CreatorUserId), nameof(IHasCreationTime.CreationTime), nameof(IModificationAudited.LastModifierUserId), nameof(IHasModificationTime.LastModificationTime) } }, { nameof(SheshaFluentMigratorExtensions.WithCreationAuditColumns), new List <string> { nameof(ICreationAudited.CreatorUserId), nameof(IHasCreationTime.CreationTime) } }, { nameof(SheshaFluentMigratorExtensions.WithModificationAuditColumns), new List <string> { nameof(IModificationAudited.LastModifierUserId), nameof(IHasModificationTime.LastModificationTime) } }, { nameof(SheshaFluentMigratorExtensions.WithDeletionAuditColumns), new List <string> { nameof(ISoftDelete.IsDeleted), nameof(IDeletionAudited.DeleterUserId), nameof(IHasDeletionTime.DeletionTime) } } }; foreach (var helper in helpers) { if (helper.Value.All(propName => properties.Any(p => p.Name == propName))) { // apply helper sb.AppendLine(); sb.Append($@" .{helper.Key}()"); // filter properties properties = properties.Where(p => !helper.Value.Contains(p.Name)).ToList(); } } // handle tenantId var tenantProp = properties.FirstOrDefault(p => p.Name == nameof(IMayHaveTenant.TenantId)); if (tenantProp != null) { //IMustHaveTenant var helper = typeof(IMustHaveTenant).IsAssignableFrom(tenantProp.DeclaringType) ? nameof(SheshaFluentMigratorExtensions.WithTenantIdAsRequired) : typeof(IMayHaveTenant).IsAssignableFrom(tenantProp.DeclaringType) ? nameof(SheshaFluentMigratorExtensions.WithTenantIdAsNullable) : null; if (!string.IsNullOrWhiteSpace(helper)) { properties.Remove(tenantProp); // apply helper sb.AppendLine(); sb.Append($@" .{helper}()"); } } return(properties); }
private static void AddColumns(StringBuilder sb, List <PropertyInfo> properties, DdlStatement statement) { var allProps = properties.ToList(); // make a copy of the list to prevent mutations var idProp = properties.FirstOrDefault(p => p.Name == "Id"); if (idProp != null) { if (statement == DdlStatement.Create) { sb.AppendLine(); if (idProp.PropertyType == typeof(Guid)) { sb.Append($@" .{nameof(SheshaFluentMigratorExtensions.WithIdAsGuid)}()"); } else if (idProp.PropertyType == typeof(int)) { sb.Append($@" .{nameof(SheshaFluentMigratorExtensions.WithIdAsInt32)}()"); } else if (idProp.PropertyType == typeof(Int64)) { sb.Append($@" .{nameof(SheshaFluentMigratorExtensions.WithIdAsInt64)}()"); } else { throw new NotSupportedException($"Id of type {idProp.PropertyType.FullName} is not supported"); } allProps.Remove(idProp); } } var customProps = ProcessFrameworkColumns(sb, allProps, statement) .OrderBy(p => p.Name) .ToList(); foreach (var property in customProps) { sb.AppendLine(); if (property.PropertyType.IsEntityType()) { var fkTable = MappingHelper.GetTableName(property.PropertyType); var fkColumn = MappingHelper.GetForeignKeyColumn(property); var method = statement == DdlStatement.Create ? nameof(SheshaFluentMigratorExtensions.WithForeignKeyColumn) : nameof(SheshaFluentMigratorExtensions.AddForeignKeyColumn); sb.Append($@" .{method}(""{fkColumn}"", ""{fkTable}"")"); } else { var method = statement == DdlStatement.Create ? nameof(ICreateTableWithColumnSyntax.WithColumn) : nameof(IAlterTableAddColumnOrAlterColumnSyntax.AddColumn); var columnName = MappingHelper.GetColumnName(property); sb.Append($@" .{method}(""{columnName}"")"); if (property.PropertyType == typeof(string)) { var maxLength = property.GetAttribute <StringLengthAttribute>()?.MaximumLength; sb.Append(maxLength != null && maxLength < int.MaxValue ? $@".{nameof(IColumnTypeSyntax<IFluentSyntax>.AsString)}({maxLength})" : $@".{nameof(SheshaFluentMigratorExtensions.AsStringMax)}()"); } else if (property.PropertyType == typeof(int) || property.PropertyType == typeof(int?) || property.PropertyType.IsEnumType()) { sb.Append($@".{nameof(IColumnTypeSyntax<IFluentSyntax>.AsInt32)}()"); } else if (property.PropertyType == typeof(Int64) || property.PropertyType == typeof(Int64?)) { sb.Append($@".{nameof(IColumnTypeSyntax<IFluentSyntax>.AsInt64)}()"); } else if (property.PropertyType == typeof(decimal) || property.PropertyType == typeof(decimal?)) { var precisionAttribute = property.GetAttribute <PrecisionAndScaleAttribute>(); if (precisionAttribute != null) { sb.Append($@".{nameof(IColumnTypeSyntax<IFluentSyntax>.AsDecimal)}({precisionAttribute.Precision}, {precisionAttribute.Scale})"); } else { sb.Append($@".{nameof(IColumnTypeSyntax<IFluentSyntax>.AsDecimal)}()"); } } else if (property.PropertyType == typeof(float) || property.PropertyType == typeof(float?)) { sb.Append($@".{nameof(IColumnTypeSyntax<IFluentSyntax>.AsFloat)}()"); } else if (property.PropertyType == typeof(double) || property.PropertyType == typeof(double?)) { sb.Append($@".{nameof(IColumnTypeSyntax<IFluentSyntax>.AsDouble)}()"); } else if (property.PropertyType == typeof(bool) || property.PropertyType == typeof(bool?)) { sb.Append($@".{nameof(IColumnTypeSyntax<IFluentSyntax>.AsBoolean)}()"); } else if (property.PropertyType == typeof(DateTime) || property.PropertyType == typeof(DateTime?)) { sb.Append($@".{nameof(IColumnTypeSyntax<IFluentSyntax>.AsDateTime)}()"); } else if (property.PropertyType == typeof(Guid) || property.PropertyType == typeof(Guid?)) { sb.Append($@".{nameof(IColumnTypeSyntax<IFluentSyntax>.AsGuid)}()"); } else if (property.PropertyType == typeof(TimeSpan) || property.PropertyType == typeof(TimeSpan?)) { sb.Append($@".{nameof(IColumnTypeSyntax<IFluentSyntax>.AsInt64)}()"); } else { throw new NotSupportedException($"unsupported property type: '{property.PropertyType.FullName}'"); } if (property.PropertyType.IsNullableType() || property.PropertyType == typeof(string) || property.DeclaringType?.BaseType != null && property.DeclaringType.BaseType.IsEntityType() /*property declared in the subclass*/) { sb.Append($@".{nameof(IColumnOptionSyntax<IFluentSyntax, IFluentSyntax>.Nullable)}()"); } } } }