From 0f3b267dd37feb33caeb3489b8b640e26fe70c04 Mon Sep 17 00:00:00 2001 From: Atiqur Rahman Foyshal Date: Thu, 20 Nov 2025 13:50:52 +0600 Subject: [PATCH 01/12] Add support TableFor with Alter, Delete and Schema --- .../Extensions/FluentMigratorExtensions.cs | 39 ++++++++++++++- .../UpgradeTo490/SchemaMigration.cs | 47 +++++++++---------- 2 files changed, 59 insertions(+), 27 deletions(-) diff --git a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs index 81f9d6f88f8..bbede67a9c6 100644 --- a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs +++ b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs @@ -1,9 +1,13 @@ using System.ComponentModel.DataAnnotations.Schema; using System.Data; using System.Reflection; +using FluentMigrator.Builders.Alter; using FluentMigrator.Builders.Alter.Table; using FluentMigrator.Builders.Create; using FluentMigrator.Builders.Create.Table; +using FluentMigrator.Builders.Delete; +using FluentMigrator.Builders.Schema; +using FluentMigrator.Builders.Schema.Table; using FluentMigrator.Infrastructure.Extensions; using FluentMigrator.Model; using FluentMigrator.Runner; @@ -63,7 +67,7 @@ private static void DefineByOwnType(string columnName, Type propType, CreateTabl /// The builder to add the database engine(s) to /// The migration runner builder public static IMigrationRunnerBuilder AddNopDbEngines(this IMigrationRunnerBuilder builder) - { + { if (!DataSettingsManager.IsDatabaseInstalled()) return builder.AddSqlServer().AddMySql5().AddPostgres92(); @@ -145,6 +149,39 @@ public static void TableFor(this ICreateExpressionRoot expressionRoot) builder.RetrieveTableExpressions(type); } + /// + /// Retrieves expressions into IDeleteExpressionRoot + /// + /// The root expression for a DELETE operation + /// Entity type + public static void TableFor(this IDeleteExpressionRoot expressionRoot) where TEntity : BaseEntity + { + var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); + expressionRoot.Table(tableName); + } + + /// + /// Retrieves expressions into IAlterExpressionRoot + /// + /// The root expression for a ALTER operation + /// Entity type + public static IAlterTableAddColumnOrAlterColumnOrSchemaOrDescriptionSyntax TableFor(this IAlterExpressionRoot expressionRoot) where TEntity : BaseEntity + { + var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); + return expressionRoot.Table(tableName); + } + + /// + /// Retrieves expressions into IAlterExpressionRoot + /// + /// The root expression for a SCHEMA + /// Entity type + public static ISchemaTableSyntax TableFor(this ISchemaExpressionRoot schema) + { + var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); + return schema.Table(tableName); + } + /// /// Retrieves expressions for building an entity table /// diff --git a/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs b/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs index 3e12547f59e..6cbd40d17a5 100644 --- a/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs +++ b/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs @@ -15,12 +15,10 @@ public class SchemaMigration : ForwardOnlyMigration public override void Up() { //#7387 - var productTableName = nameof(Product); - var ageVerificationColumnName = nameof(Product.AgeVerification); - if (!Schema.Table(productTableName).Column(ageVerificationColumnName).Exists()) + if (!Schema.TableFor().Column(ageVerificationColumnName).Exists()) { - Alter.Table(productTableName) + Alter.TableFor() .AddColumn(ageVerificationColumnName) .AsBoolean() .NotNullable() @@ -28,9 +26,9 @@ public override void Up() } var minimumAgeToPurchaseColumnName = nameof(Product.MinimumAgeToPurchase); - if (!Schema.Table(productTableName).Column(minimumAgeToPurchaseColumnName).Exists()) + if (!Schema.TableFor().Column(minimumAgeToPurchaseColumnName).Exists()) { - Alter.Table(productTableName) + Alter.TableFor() .AddColumn(minimumAgeToPurchaseColumnName) .AsInt32() .NotNullable() @@ -42,62 +40,59 @@ public override void Up() var topicAvailableEndDateColumnName = nameof(Topic.AvailableEndDateTimeUtc); var topicAvailableStartDateColumnName = nameof(Topic.AvailableStartDateTimeUtc); - if (!Schema.Table(topicTableName).Column(topicAvailableEndDateColumnName).Exists()) + if (!Schema.TableFor().Column(topicAvailableEndDateColumnName).Exists()) { - Alter.Table(topicTableName) + Alter.TableFor() .AddColumn(topicAvailableEndDateColumnName) .AsDateTime() .Nullable(); } - if (!Schema.Table(topicTableName).Column(topicAvailableStartDateColumnName).Exists()) + if (!Schema.TableFor().Column(topicAvailableStartDateColumnName).Exists()) { - Alter.Table(topicTableName) + Alter.TableFor() .AddColumn(topicAvailableStartDateColumnName) .AsDateTime() .Nullable(); } //#873 - var productTagTableName = nameof(ProductTag); - if (!Schema.Table(productTagTableName).Column(nameof(ProductTag.MetaDescription)).Exists()) - Alter.Table(productTagTableName).AddColumn(nameof(ProductTag.MetaDescription)).AsString().Nullable(); + if (!Schema.TableFor().Column(nameof(ProductTag.MetaDescription)).Exists()) + Alter.TableFor().AddColumn(nameof(ProductTag.MetaDescription)).AsString().Nullable(); - if (!Schema.Table(productTagTableName).Column(nameof(ProductTag.MetaKeywords)).Exists()) - Alter.Table(productTagTableName).AddColumn(nameof(ProductTag.MetaKeywords)).AsString(400).Nullable(); + if (!Schema.TableFor().Column(nameof(ProductTag.MetaKeywords)).Exists()) + Alter.TableFor().AddColumn(nameof(ProductTag.MetaKeywords)).AsString(400).Nullable(); - if (!Schema.Table(productTagTableName).Column(nameof(ProductTag.MetaTitle)).Exists()) - Alter.Table(productTagTableName).AddColumn(nameof(ProductTag.MetaTitle)).AsString(400).Nullable(); + if (!Schema.TableFor().Column(nameof(ProductTag.MetaTitle)).Exists()) + Alter.TableFor().AddColumn(nameof(ProductTag.MetaTitle)).AsString(400).Nullable(); //#7390 - if (!Schema.Table(nameof(Menu)).Exists()) + if (!Schema.TableFor().Exists()) Create.TableFor(); - if (!Schema.Table(nameof(MenuItem)).Exists()) + if (!Schema.TableFor().Exists()) Create.TableFor(); var footerColumn1ColumnName = "IncludeInFooterColumn1"; - if (Schema.Table(topicTableName).Column(footerColumn1ColumnName).Exists()) + if (Schema.TableFor().Column(footerColumn1ColumnName).Exists()) Delete.Column(footerColumn1ColumnName).FromTable(topicTableName); var footerColumn2ColumnName = "IncludeInFooterColumn2"; - if (Schema.Table(topicTableName).Column(footerColumn2ColumnName).Exists()) + if (Schema.TableFor().Column(footerColumn2ColumnName).Exists()) Delete.Column(footerColumn2ColumnName).FromTable(topicTableName); var footerColumn3ColumnName = "IncludeInFooterColumn3"; - if (Schema.Table(topicTableName).Column(footerColumn3ColumnName).Exists()) + if (Schema.TableFor().Column(footerColumn3ColumnName).Exists()) Delete.Column(footerColumn3ColumnName).FromTable(topicTableName); var includeTopicInTopMenuColumnName = "IncludeInTopMenu"; - if (Schema.Table(topicTableName).Column(includeTopicInTopMenuColumnName).Exists()) + if (Schema.TableFor().Column(includeTopicInTopMenuColumnName).Exists()) Delete.Column(includeTopicInTopMenuColumnName).FromTable(topicTableName); var categoryTableName = nameof(Category); var includeCategoryInTopMenuColumnName = "IncludeInTopMenu"; - if (Schema.Table(categoryTableName).Column(includeCategoryInTopMenuColumnName).Exists()) + if (Schema.TableFor().Column(includeCategoryInTopMenuColumnName).Exists()) Delete.Column(includeCategoryInTopMenuColumnName).FromTable(categoryTableName); - - } } From c218904d19011955af48b20a7da53bdb9facbffc Mon Sep 17 00:00:00 2001 From: Atiqur Rahman Foyshal Date: Thu, 20 Nov 2025 15:00:37 +0600 Subject: [PATCH 02/12] Add support for AddColumnFor, FromTable --- .../Extensions/FluentMigratorExtensions.cs | 31 +++++++++- .../UpgradeTo490/SchemaMigration.cs | 59 +++++++++++-------- 2 files changed, 63 insertions(+), 27 deletions(-) diff --git a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs index bbede67a9c6..dfa16446135 100644 --- a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs +++ b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs @@ -1,12 +1,16 @@ using System.ComponentModel.DataAnnotations.Schema; using System.Data; +using System.Linq.Expressions; using System.Reflection; +using FluentMigrator.Builders; using FluentMigrator.Builders.Alter; using FluentMigrator.Builders.Alter.Table; using FluentMigrator.Builders.Create; using FluentMigrator.Builders.Create.Table; using FluentMigrator.Builders.Delete; +using FluentMigrator.Builders.Delete.Column; using FluentMigrator.Builders.Schema; +using FluentMigrator.Builders.Schema.Column; using FluentMigrator.Builders.Schema.Table; using FluentMigrator.Infrastructure.Extensions; using FluentMigrator.Model; @@ -172,16 +176,39 @@ public static IAlterTableAddColumnOrAlterColumnOrSchemaOrDescriptionSyntax Table } /// - /// Retrieves expressions into IAlterExpressionRoot + /// Retrieves expressions into ISchemaExpressionRoot /// /// The root expression for a SCHEMA /// Entity type - public static ISchemaTableSyntax TableFor(this ISchemaExpressionRoot schema) + public static ISchemaTableSyntax TableFor(this ISchemaExpressionRoot schema) where TEntity : BaseEntity { var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); return schema.Table(tableName); } + public static ISchemaColumnSyntax ColumnFor( + this ISchemaTableSyntax schema, Expression> selector) where TEntity : BaseEntity + { + var property = ((MemberExpression)selector.Body)?.Member?.Name; + var columnName = NameCompatibilityManager.GetColumnName(typeof(TEntity), property!); + return schema.Column(columnName); + } + + public static IAlterTableColumnAsTypeSyntax AddColumnFor( + this IAlterTableAddColumnOrAlterColumnSyntax tableSchema, Expression> selector) where TEntity : BaseEntity + { + var property = ((MemberExpression)selector.Body)?.Member?.Name; + var columnName = NameCompatibilityManager.GetColumnName(typeof(TEntity), property!); + return tableSchema.AddColumn(columnName); + } + + public static IInSchemaSyntax FromTable( + this IDeleteColumnFromTableSyntax tableSchema) where TEntity : BaseEntity + { + var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); + return tableSchema.FromTable(tableName); + } + /// /// Retrieves expressions for building an entity table /// diff --git a/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs b/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs index 6cbd40d17a5..ab78faf6cd8 100644 --- a/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs +++ b/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs @@ -15,57 +15,67 @@ public class SchemaMigration : ForwardOnlyMigration public override void Up() { //#7387 - var ageVerificationColumnName = nameof(Product.AgeVerification); - if (!Schema.TableFor().Column(ageVerificationColumnName).Exists()) + if (!Schema.TableFor().ColumnFor(t => t.AgeVerification).Exists()) { Alter.TableFor() - .AddColumn(ageVerificationColumnName) + .AddColumnFor(t => t.AgeVerification) .AsBoolean() .NotNullable() .WithDefaultValue(false); } - var minimumAgeToPurchaseColumnName = nameof(Product.MinimumAgeToPurchase); - if (!Schema.TableFor().Column(minimumAgeToPurchaseColumnName).Exists()) + if (!Schema.TableFor().ColumnFor(t => t.MinimumAgeToPurchase).Exists()) { Alter.TableFor() - .AddColumn(minimumAgeToPurchaseColumnName) + .AddColumnFor(t => t.MinimumAgeToPurchase) .AsInt32() .NotNullable() .WithDefaultValue(0); } //#7294 - var topicTableName = nameof(Topic); - var topicAvailableEndDateColumnName = nameof(Topic.AvailableEndDateTimeUtc); - var topicAvailableStartDateColumnName = nameof(Topic.AvailableStartDateTimeUtc); - if (!Schema.TableFor().Column(topicAvailableEndDateColumnName).Exists()) + if (!Schema.TableFor().ColumnFor(t => t.AvailableEndDateTimeUtc).Exists()) { Alter.TableFor() - .AddColumn(topicAvailableEndDateColumnName) + .AddColumnFor(t => t.AvailableEndDateTimeUtc) .AsDateTime() .Nullable(); } - if (!Schema.TableFor().Column(topicAvailableStartDateColumnName).Exists()) + if (!Schema.TableFor().ColumnFor(t => t.AvailableStartDateTimeUtc).Exists()) { Alter.TableFor() - .AddColumn(topicAvailableStartDateColumnName) + .AddColumnFor(t => t.AvailableStartDateTimeUtc) .AsDateTime() .Nullable(); } //#873 - if (!Schema.TableFor().Column(nameof(ProductTag.MetaDescription)).Exists()) - Alter.TableFor().AddColumn(nameof(ProductTag.MetaDescription)).AsString().Nullable(); + if (!Schema.TableFor().ColumnFor(t => t.MetaDescription).Exists()) + { + Alter.TableFor() + .AddColumnFor(t => t.MetaDescription) + .AsString() + .Nullable(); + } - if (!Schema.TableFor().Column(nameof(ProductTag.MetaKeywords)).Exists()) - Alter.TableFor().AddColumn(nameof(ProductTag.MetaKeywords)).AsString(400).Nullable(); + if (!Schema.TableFor().ColumnFor(t => t.MetaKeywords).Exists()) + { + Alter.TableFor() + .AddColumnFor(t => t.MetaKeywords) + .AsString(400) + .Nullable(); + } - if (!Schema.TableFor().Column(nameof(ProductTag.MetaTitle)).Exists()) - Alter.TableFor().AddColumn(nameof(ProductTag.MetaTitle)).AsString(400).Nullable(); + if (!Schema.TableFor().ColumnFor(t => t.MetaTitle).Exists()) + { + Alter.TableFor() + .AddColumnFor(t => t.MetaTitle) + .AsString(400) + .Nullable(); + } //#7390 if (!Schema.TableFor().Exists()) @@ -76,23 +86,22 @@ public override void Up() var footerColumn1ColumnName = "IncludeInFooterColumn1"; if (Schema.TableFor().Column(footerColumn1ColumnName).Exists()) - Delete.Column(footerColumn1ColumnName).FromTable(topicTableName); + Delete.Column(footerColumn1ColumnName).FromTable(); var footerColumn2ColumnName = "IncludeInFooterColumn2"; if (Schema.TableFor().Column(footerColumn2ColumnName).Exists()) - Delete.Column(footerColumn2ColumnName).FromTable(topicTableName); + Delete.Column(footerColumn2ColumnName).FromTable(); var footerColumn3ColumnName = "IncludeInFooterColumn3"; if (Schema.TableFor().Column(footerColumn3ColumnName).Exists()) - Delete.Column(footerColumn3ColumnName).FromTable(topicTableName); + Delete.Column(footerColumn3ColumnName).FromTable(); var includeTopicInTopMenuColumnName = "IncludeInTopMenu"; if (Schema.TableFor().Column(includeTopicInTopMenuColumnName).Exists()) - Delete.Column(includeTopicInTopMenuColumnName).FromTable(topicTableName); + Delete.Column(includeTopicInTopMenuColumnName).FromTable(); - var categoryTableName = nameof(Category); var includeCategoryInTopMenuColumnName = "IncludeInTopMenu"; if (Schema.TableFor().Column(includeCategoryInTopMenuColumnName).Exists()) - Delete.Column(includeCategoryInTopMenuColumnName).FromTable(categoryTableName); + Delete.Column(includeCategoryInTopMenuColumnName).FromTable(); } } From 325c3649dd68f5b24afe4a69380eab7e0c997333 Mon Sep 17 00:00:00 2001 From: Atiqur Rahman Foyshal Date: Thu, 20 Nov 2025 15:39:42 +0600 Subject: [PATCH 03/12] add summary --- .../Extensions/FluentMigratorExtensions.cs | 55 ++++++++++++++++--- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs index dfa16446135..aa32610de37 100644 --- a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs +++ b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs @@ -154,10 +154,10 @@ public static void TableFor(this ICreateExpressionRoot expressionRoot) } /// - /// Retrieves expressions into IDeleteExpressionRoot + /// Targets the entity's mapped table for a DELETE operation. /// /// The root expression for a DELETE operation - /// Entity type + /// The entity type mapped to the database table public static void TableFor(this IDeleteExpressionRoot expressionRoot) where TEntity : BaseEntity { var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); @@ -165,10 +165,14 @@ public static void TableFor(this IDeleteExpressionRoot expressionRoot) } /// - /// Retrieves expressions into IAlterExpressionRoot + /// Targets the entity's mapped table for an ALTER TABLE operation. /// - /// The root expression for a ALTER operation - /// Entity type + /// The root expression for an ALTER operation + /// The entity type mapped to the database table + /// + /// A fluent syntax interface allowing further ALTER TABLE operations + /// such as adding or modifying columns. + /// public static IAlterTableAddColumnOrAlterColumnOrSchemaOrDescriptionSyntax TableFor(this IAlterExpressionRoot expressionRoot) where TEntity : BaseEntity { var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); @@ -176,16 +180,31 @@ public static IAlterTableAddColumnOrAlterColumnOrSchemaOrDescriptionSyntax Table } /// - /// Retrieves expressions into ISchemaExpressionRoot + /// Targets the entity's mapped table for schema-related operations. /// - /// The root expression for a SCHEMA - /// Entity type + /// The root expression for schema inspection + /// The entity type mapped to the database table + /// + /// A fluent syntax interface for performing schema operations + /// such as checking table or column existence. + /// public static ISchemaTableSyntax TableFor(this ISchemaExpressionRoot schema) where TEntity : BaseEntity { var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); return schema.Table(tableName); } + /// + /// Targets a specific column of the entity's mapped table for schema inspection, + /// resolving the column name via . + /// + /// The entity type mapped to the database table + /// The schema table expression + /// An expression selecting the entity property + /// + /// A fluent syntax interface for performing schema operations + /// such as checking column existence. + /// public static ISchemaColumnSyntax ColumnFor( this ISchemaTableSyntax schema, Expression> selector) where TEntity : BaseEntity { @@ -194,6 +213,17 @@ public static ISchemaColumnSyntax ColumnFor( return schema.Column(columnName); } + /// + /// Adds a new column to the entity's mapped table for ALTER TABLE operations, + /// resolving the column name via . + /// + /// The entity type mapped to the database table + /// The alter table expression + /// An expression selecting the entity property + /// + /// A fluent syntax interface allowing further ALTER TABLE operations + /// on the specified column. + /// public static IAlterTableColumnAsTypeSyntax AddColumnFor( this IAlterTableAddColumnOrAlterColumnSyntax tableSchema, Expression> selector) where TEntity : BaseEntity { @@ -202,6 +232,15 @@ public static IAlterTableColumnAsTypeSyntax AddColumnFor( return tableSchema.AddColumn(columnName); } + /// + /// Targets the mapped table of the specified entity for a DELETE COLUMN operation, + /// resolving the table name via . + /// + /// The entity type mapped to the database table + /// The delete column from table syntax + /// + /// A fluent syntax interface allowing the deletion of columns from the specified table. + /// public static IInSchemaSyntax FromTable( this IDeleteColumnFromTableSyntax tableSchema) where TEntity : BaseEntity { From 3da30624884cc12d94569ad3ba3d78978cc6ef6b Mon Sep 17 00:00:00 2001 From: Atiqur Rahman Foyshal Date: Thu, 20 Nov 2025 16:47:03 +0600 Subject: [PATCH 04/12] refactor variable naming --- .../Extensions/FluentMigratorExtensions.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs index aa32610de37..ea2bbfcb572 100644 --- a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs +++ b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs @@ -182,16 +182,16 @@ public static IAlterTableAddColumnOrAlterColumnOrSchemaOrDescriptionSyntax Table /// /// Targets the entity's mapped table for schema-related operations. /// - /// The root expression for schema inspection + /// The root expression for schema inspection /// The entity type mapped to the database table /// /// A fluent syntax interface for performing schema operations /// such as checking table or column existence. /// - public static ISchemaTableSyntax TableFor(this ISchemaExpressionRoot schema) where TEntity : BaseEntity + public static ISchemaTableSyntax TableFor(this ISchemaExpressionRoot expressionRoot) where TEntity : BaseEntity { var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); - return schema.Table(tableName); + return expressionRoot.Table(tableName); } /// @@ -199,18 +199,18 @@ public static ISchemaTableSyntax TableFor(this ISchemaExpressionRoot sc /// resolving the column name via . /// /// The entity type mapped to the database table - /// The schema table expression + /// The schema table expression /// An expression selecting the entity property /// /// A fluent syntax interface for performing schema operations /// such as checking column existence. /// public static ISchemaColumnSyntax ColumnFor( - this ISchemaTableSyntax schema, Expression> selector) where TEntity : BaseEntity + this ISchemaTableSyntax tableSchema, Expression> selector) where TEntity : BaseEntity { var property = ((MemberExpression)selector.Body)?.Member?.Name; var columnName = NameCompatibilityManager.GetColumnName(typeof(TEntity), property!); - return schema.Column(columnName); + return tableSchema.Column(columnName); } /// @@ -237,15 +237,15 @@ public static IAlterTableColumnAsTypeSyntax AddColumnFor( /// resolving the table name via . /// /// The entity type mapped to the database table - /// The delete column from table syntax + /// The delete column expression from table syntax /// /// A fluent syntax interface allowing the deletion of columns from the specified table. /// public static IInSchemaSyntax FromTable( - this IDeleteColumnFromTableSyntax tableSchema) where TEntity : BaseEntity + this IDeleteColumnFromTableSyntax expressionRoot) where TEntity : BaseEntity { var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); - return tableSchema.FromTable(tableName); + return expressionRoot.FromTable(tableName); } /// From bfdc757fb40bf8bfefc5cb9bdb43d034ddcae15b Mon Sep 17 00:00:00 2001 From: Atiqur Rahman Foyshal Date: Tue, 25 Nov 2025 09:14:49 +0600 Subject: [PATCH 05/12] Add TableExist and ColumnExist method --- .../Extensions/FluentMigratorExtensions.cs | 51 ++++++++++++++----- .../UpgradeTo490/SchemaMigration.cs | 28 +++++----- 2 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs index ea2bbfcb572..458424c97a0 100644 --- a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs +++ b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs @@ -10,7 +10,6 @@ using FluentMigrator.Builders.Delete; using FluentMigrator.Builders.Delete.Column; using FluentMigrator.Builders.Schema; -using FluentMigrator.Builders.Schema.Column; using FluentMigrator.Builders.Schema.Table; using FluentMigrator.Infrastructure.Extensions; using FluentMigrator.Model; @@ -195,22 +194,48 @@ public static ISchemaTableSyntax TableFor(this ISchemaExpressionRoot ex } /// - /// Targets a specific column of the entity's mapped table for schema inspection, - /// resolving the column name via . + /// Determines whether the database table mapped to the specified entity exists, + /// resolving the table name using . /// - /// The entity type mapped to the database table - /// The schema table expression - /// An expression selecting the entity property - /// - /// A fluent syntax interface for performing schema operations - /// such as checking column existence. - /// - public static ISchemaColumnSyntax ColumnFor( - this ISchemaTableSyntax tableSchema, Expression> selector) where TEntity : BaseEntity + /// The entity type mapped to the database table. + /// The root schema expression. + /// true if the table exists; otherwise, false. + public static bool TableExist(this ISchemaExpressionRoot expressionRoot) where TEntity : BaseEntity { + var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); + return expressionRoot.Table(tableName).Exists(); + } + + /// + /// Checks whether a mapped column exists in the database table for the specified entity. + /// Resolves both the table name and column name using . + /// + /// The entity type mapped to the database table. + /// The root schema expression. + /// An expression selecting the entity property to check. + /// true if the column exists; otherwise, false. + public static bool ColumnExist( + this ISchemaExpressionRoot expressionRoot, Expression> selector) where TEntity : BaseEntity + { + var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); var property = ((MemberExpression)selector.Body)?.Member?.Name; var columnName = NameCompatibilityManager.GetColumnName(typeof(TEntity), property!); - return tableSchema.Column(columnName); + return expressionRoot.Table(tableName).Column(columnName).Exists(); + } + + /// + /// Checks whether a mapped column exists in the database table for the specified entity. + /// Resolves both the table name and column name using . + /// + /// The entity type mapped to the database table. + /// The root schema expression. + /// The column name + /// true if the column exists; otherwise, false. + public static bool ColumnExist( + this ISchemaExpressionRoot expressionRoot, string columnName) where TEntity : BaseEntity + { + var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); + return expressionRoot.Table(tableName).Column(columnName).Exists(); } /// diff --git a/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs b/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs index ab78faf6cd8..d188c5da73a 100644 --- a/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs +++ b/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs @@ -15,7 +15,7 @@ public class SchemaMigration : ForwardOnlyMigration public override void Up() { //#7387 - if (!Schema.TableFor().ColumnFor(t => t.AgeVerification).Exists()) + if (!Schema.ColumnExist(t => t.AgeVerification)) { Alter.TableFor() .AddColumnFor(t => t.AgeVerification) @@ -24,7 +24,7 @@ public override void Up() .WithDefaultValue(false); } - if (!Schema.TableFor().ColumnFor(t => t.MinimumAgeToPurchase).Exists()) + if (!Schema.ColumnExist(t => t.MinimumAgeToPurchase)) { Alter.TableFor() .AddColumnFor(t => t.MinimumAgeToPurchase) @@ -35,7 +35,7 @@ public override void Up() //#7294 - if (!Schema.TableFor().ColumnFor(t => t.AvailableEndDateTimeUtc).Exists()) + if (!Schema.ColumnExist(t => t.AvailableEndDateTimeUtc)) { Alter.TableFor() .AddColumnFor(t => t.AvailableEndDateTimeUtc) @@ -43,7 +43,7 @@ public override void Up() .Nullable(); } - if (!Schema.TableFor().ColumnFor(t => t.AvailableStartDateTimeUtc).Exists()) + if (!Schema.ColumnExist(t => t.AvailableStartDateTimeUtc)) { Alter.TableFor() .AddColumnFor(t => t.AvailableStartDateTimeUtc) @@ -53,7 +53,7 @@ public override void Up() //#873 - if (!Schema.TableFor().ColumnFor(t => t.MetaDescription).Exists()) + if (!Schema.ColumnExist(t => t.MetaDescription)) { Alter.TableFor() .AddColumnFor(t => t.MetaDescription) @@ -61,7 +61,7 @@ public override void Up() .Nullable(); } - if (!Schema.TableFor().ColumnFor(t => t.MetaKeywords).Exists()) + if (!Schema.ColumnExist(t => t.MetaKeywords)) { Alter.TableFor() .AddColumnFor(t => t.MetaKeywords) @@ -69,7 +69,7 @@ public override void Up() .Nullable(); } - if (!Schema.TableFor().ColumnFor(t => t.MetaTitle).Exists()) + if (!Schema.ColumnExist(t => t.MetaTitle)) { Alter.TableFor() .AddColumnFor(t => t.MetaTitle) @@ -78,30 +78,30 @@ public override void Up() } //#7390 - if (!Schema.TableFor().Exists()) + if (!Schema.TableExist()) Create.TableFor(); - if (!Schema.TableFor().Exists()) + if (!Schema.TableExist()) Create.TableFor(); var footerColumn1ColumnName = "IncludeInFooterColumn1"; - if (Schema.TableFor().Column(footerColumn1ColumnName).Exists()) + if (Schema.ColumnExist(footerColumn1ColumnName)) Delete.Column(footerColumn1ColumnName).FromTable(); var footerColumn2ColumnName = "IncludeInFooterColumn2"; - if (Schema.TableFor().Column(footerColumn2ColumnName).Exists()) + if (Schema.ColumnExist(footerColumn2ColumnName)) Delete.Column(footerColumn2ColumnName).FromTable(); var footerColumn3ColumnName = "IncludeInFooterColumn3"; - if (Schema.TableFor().Column(footerColumn3ColumnName).Exists()) + if (Schema.ColumnExist(footerColumn3ColumnName)) Delete.Column(footerColumn3ColumnName).FromTable(); var includeTopicInTopMenuColumnName = "IncludeInTopMenu"; - if (Schema.TableFor().Column(includeTopicInTopMenuColumnName).Exists()) + if (Schema.ColumnExist(includeTopicInTopMenuColumnName)) Delete.Column(includeTopicInTopMenuColumnName).FromTable(); var includeCategoryInTopMenuColumnName = "IncludeInTopMenu"; - if (Schema.TableFor().Column(includeCategoryInTopMenuColumnName).Exists()) + if (Schema.ColumnExist(includeCategoryInTopMenuColumnName)) Delete.Column(includeCategoryInTopMenuColumnName).FromTable(); } } From 248315d2e13d126623c08c41f6ca91a5aa334a76 Mon Sep 17 00:00:00 2001 From: Atiqur Rahman Foyshal Date: Tue, 25 Nov 2025 09:20:17 +0600 Subject: [PATCH 06/12] Update method AddColumnFor, remove redundant TableFor --- .../Extensions/FluentMigratorExtensions.cs | 5 +++-- .../UpgradeTo490/SchemaMigration.cs | 21 +++++++------------ 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs index 458424c97a0..7ca32bd759c 100644 --- a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs +++ b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs @@ -250,11 +250,12 @@ public static bool ColumnExist( /// on the specified column. /// public static IAlterTableColumnAsTypeSyntax AddColumnFor( - this IAlterTableAddColumnOrAlterColumnSyntax tableSchema, Expression> selector) where TEntity : BaseEntity + this IAlterExpressionRoot expressionRoot, Expression> selector) where TEntity : BaseEntity { + var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); var property = ((MemberExpression)selector.Body)?.Member?.Name; var columnName = NameCompatibilityManager.GetColumnName(typeof(TEntity), property!); - return tableSchema.AddColumn(columnName); + return expressionRoot.Table(tableName).AddColumn(columnName); } /// diff --git a/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs b/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs index d188c5da73a..d67fb4b11db 100644 --- a/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs +++ b/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs @@ -17,8 +17,7 @@ public override void Up() //#7387 if (!Schema.ColumnExist(t => t.AgeVerification)) { - Alter.TableFor() - .AddColumnFor(t => t.AgeVerification) + Alter.AddColumnFor(t => t.AgeVerification) .AsBoolean() .NotNullable() .WithDefaultValue(false); @@ -26,8 +25,7 @@ public override void Up() if (!Schema.ColumnExist(t => t.MinimumAgeToPurchase)) { - Alter.TableFor() - .AddColumnFor(t => t.MinimumAgeToPurchase) + Alter.AddColumnFor(t => t.MinimumAgeToPurchase) .AsInt32() .NotNullable() .WithDefaultValue(0); @@ -37,16 +35,14 @@ public override void Up() if (!Schema.ColumnExist(t => t.AvailableEndDateTimeUtc)) { - Alter.TableFor() - .AddColumnFor(t => t.AvailableEndDateTimeUtc) + Alter.AddColumnFor(t => t.AvailableEndDateTimeUtc) .AsDateTime() .Nullable(); } if (!Schema.ColumnExist(t => t.AvailableStartDateTimeUtc)) { - Alter.TableFor() - .AddColumnFor(t => t.AvailableStartDateTimeUtc) + Alter.AddColumnFor(t => t.AvailableStartDateTimeUtc) .AsDateTime() .Nullable(); } @@ -55,24 +51,21 @@ public override void Up() if (!Schema.ColumnExist(t => t.MetaDescription)) { - Alter.TableFor() - .AddColumnFor(t => t.MetaDescription) + Alter.AddColumnFor(t => t.MetaDescription) .AsString() .Nullable(); } if (!Schema.ColumnExist(t => t.MetaKeywords)) { - Alter.TableFor() - .AddColumnFor(t => t.MetaKeywords) + Alter.AddColumnFor(t => t.MetaKeywords) .AsString(400) .Nullable(); } if (!Schema.ColumnExist(t => t.MetaTitle)) { - Alter.TableFor() - .AddColumnFor(t => t.MetaTitle) + Alter.AddColumnFor(t => t.MetaTitle) .AsString(400) .Nullable(); } From 659d39923ac235bf84bb25c924410a807d64cb99 Mon Sep 17 00:00:00 2001 From: Atiqur Rahman Foyshal Date: Tue, 25 Nov 2025 09:26:46 +0600 Subject: [PATCH 07/12] Refactor delete column --- .../Nop.Data/Extensions/FluentMigratorExtensions.cs | 13 +++++++++++++ .../Migrations/UpgradeTo490/SchemaMigration.cs | 10 +++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs index 7ca32bd759c..f67d9aa13a8 100644 --- a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs +++ b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs @@ -163,6 +163,19 @@ public static void TableFor(this IDeleteExpressionRoot expressionRoot) expressionRoot.Table(tableName); } + /// + /// Deletes a column from the table mapped to the specified entity, + /// resolving the table name using . + /// + /// The entity type mapped to the database table. + /// The root delete expression. + /// The name of the column to delete. + public static void Column(this IDeleteExpressionRoot expressionRoot, string columnName) where TEntity : BaseEntity + { + var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); + expressionRoot.Column(columnName).FromTable(tableName); + } + /// /// Targets the entity's mapped table for an ALTER TABLE operation. /// diff --git a/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs b/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs index d67fb4b11db..4e9af08a18d 100644 --- a/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs +++ b/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs @@ -79,22 +79,22 @@ public override void Up() var footerColumn1ColumnName = "IncludeInFooterColumn1"; if (Schema.ColumnExist(footerColumn1ColumnName)) - Delete.Column(footerColumn1ColumnName).FromTable(); + Delete.Column(footerColumn1ColumnName); var footerColumn2ColumnName = "IncludeInFooterColumn2"; if (Schema.ColumnExist(footerColumn2ColumnName)) - Delete.Column(footerColumn2ColumnName).FromTable(); + Delete.Column(footerColumn2ColumnName); var footerColumn3ColumnName = "IncludeInFooterColumn3"; if (Schema.ColumnExist(footerColumn3ColumnName)) - Delete.Column(footerColumn3ColumnName).FromTable(); + Delete.Column(footerColumn3ColumnName); var includeTopicInTopMenuColumnName = "IncludeInTopMenu"; if (Schema.ColumnExist(includeTopicInTopMenuColumnName)) - Delete.Column(includeTopicInTopMenuColumnName).FromTable(); + Delete.Column(includeTopicInTopMenuColumnName); var includeCategoryInTopMenuColumnName = "IncludeInTopMenu"; if (Schema.ColumnExist(includeCategoryInTopMenuColumnName)) - Delete.Column(includeCategoryInTopMenuColumnName).FromTable(); + Delete.Column(includeCategoryInTopMenuColumnName); } } From 48c027ce5d8d1d9fef07c980cbdce1bc8130cb1e Mon Sep 17 00:00:00 2001 From: Atiqur Rahman Foyshal Date: Tue, 25 Nov 2025 10:07:34 +0600 Subject: [PATCH 08/12] Refactor --- .../Nop.Data/Extensions/FluentMigratorExtensions.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs index f67d9aa13a8..8a526e0a86e 100644 --- a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs +++ b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs @@ -231,8 +231,10 @@ public static bool ColumnExist( this ISchemaExpressionRoot expressionRoot, Expression> selector) where TEntity : BaseEntity { var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); - var property = ((MemberExpression)selector.Body)?.Member?.Name; - var columnName = NameCompatibilityManager.GetColumnName(typeof(TEntity), property!); + var propertyMemberExpression = selector.Body as MemberExpression + ?? (selector.Body as UnaryExpression)?.Operand as MemberExpression + ?? throw new ArgumentException("Selector must be a property expression.", nameof(selector)); + var columnName = NameCompatibilityManager.GetColumnName(typeof(TEntity), propertyMemberExpression.Member.Name); return expressionRoot.Table(tableName).Column(columnName).Exists(); } @@ -266,8 +268,10 @@ public static IAlterTableColumnAsTypeSyntax AddColumnFor( this IAlterExpressionRoot expressionRoot, Expression> selector) where TEntity : BaseEntity { var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); - var property = ((MemberExpression)selector.Body)?.Member?.Name; - var columnName = NameCompatibilityManager.GetColumnName(typeof(TEntity), property!); + var propertyMemberExpression = selector.Body as MemberExpression + ?? (selector.Body as UnaryExpression)?.Operand as MemberExpression + ?? throw new ArgumentException("Selector must be a property expression.", nameof(selector)); + var columnName = NameCompatibilityManager.GetColumnName(typeof(TEntity), propertyMemberExpression.Member.Name); return expressionRoot.Table(tableName).AddColumn(columnName); } From 311ec44fc97d9715775cff7b731660e5c4617c32 Mon Sep 17 00:00:00 2001 From: Atiqur Rahman Foyshal Date: Tue, 25 Nov 2025 10:13:51 +0600 Subject: [PATCH 09/12] Remove unnecessary methods --- .../Extensions/FluentMigratorExtensions.cs | 60 ------------------- 1 file changed, 60 deletions(-) diff --git a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs index 8a526e0a86e..7c999b4e8b6 100644 --- a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs +++ b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs @@ -2,15 +2,12 @@ using System.Data; using System.Linq.Expressions; using System.Reflection; -using FluentMigrator.Builders; using FluentMigrator.Builders.Alter; using FluentMigrator.Builders.Alter.Table; using FluentMigrator.Builders.Create; using FluentMigrator.Builders.Create.Table; using FluentMigrator.Builders.Delete; -using FluentMigrator.Builders.Delete.Column; using FluentMigrator.Builders.Schema; -using FluentMigrator.Builders.Schema.Table; using FluentMigrator.Infrastructure.Extensions; using FluentMigrator.Model; using FluentMigrator.Runner; @@ -152,17 +149,6 @@ public static void TableFor(this ICreateExpressionRoot expressionRoot) builder.RetrieveTableExpressions(type); } - /// - /// Targets the entity's mapped table for a DELETE operation. - /// - /// The root expression for a DELETE operation - /// The entity type mapped to the database table - public static void TableFor(this IDeleteExpressionRoot expressionRoot) where TEntity : BaseEntity - { - var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); - expressionRoot.Table(tableName); - } - /// /// Deletes a column from the table mapped to the specified entity, /// resolving the table name using . @@ -176,36 +162,6 @@ public static void Column(this IDeleteExpressionRoot expressionRoot, st expressionRoot.Column(columnName).FromTable(tableName); } - /// - /// Targets the entity's mapped table for an ALTER TABLE operation. - /// - /// The root expression for an ALTER operation - /// The entity type mapped to the database table - /// - /// A fluent syntax interface allowing further ALTER TABLE operations - /// such as adding or modifying columns. - /// - public static IAlterTableAddColumnOrAlterColumnOrSchemaOrDescriptionSyntax TableFor(this IAlterExpressionRoot expressionRoot) where TEntity : BaseEntity - { - var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); - return expressionRoot.Table(tableName); - } - - /// - /// Targets the entity's mapped table for schema-related operations. - /// - /// The root expression for schema inspection - /// The entity type mapped to the database table - /// - /// A fluent syntax interface for performing schema operations - /// such as checking table or column existence. - /// - public static ISchemaTableSyntax TableFor(this ISchemaExpressionRoot expressionRoot) where TEntity : BaseEntity - { - var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); - return expressionRoot.Table(tableName); - } - /// /// Determines whether the database table mapped to the specified entity exists, /// resolving the table name using . @@ -275,22 +231,6 @@ public static IAlterTableColumnAsTypeSyntax AddColumnFor( return expressionRoot.Table(tableName).AddColumn(columnName); } - /// - /// Targets the mapped table of the specified entity for a DELETE COLUMN operation, - /// resolving the table name via . - /// - /// The entity type mapped to the database table - /// The delete column expression from table syntax - /// - /// A fluent syntax interface allowing the deletion of columns from the specified table. - /// - public static IInSchemaSyntax FromTable( - this IDeleteColumnFromTableSyntax expressionRoot) where TEntity : BaseEntity - { - var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); - return expressionRoot.FromTable(tableName); - } - /// /// Retrieves expressions for building an entity table /// From 83075750a28760cb9f19caf5b177d37d61d75c7e Mon Sep 17 00:00:00 2001 From: Atiqur Rahman Foyshal Date: Tue, 25 Nov 2025 11:56:58 +0600 Subject: [PATCH 10/12] Add TableFor extension method for IAlterExpressionRoot --- .../Extensions/FluentMigratorExtensions.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs index 7c999b4e8b6..3ec7822688c 100644 --- a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs +++ b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs @@ -149,6 +149,21 @@ public static void TableFor(this ICreateExpressionRoot expressionRoot) builder.RetrieveTableExpressions(type); } + /// + /// Targets the entity's mapped table for an ALTER TABLE operation. + /// + /// The root expression for an ALTER operation + /// The entity type mapped to the database table + /// + /// A fluent syntax interface allowing further ALTER TABLE operations + /// such as adding or modifying columns. + /// + public static IAlterTableAddColumnOrAlterColumnOrSchemaOrDescriptionSyntax TableFor(this IAlterExpressionRoot expressionRoot) where TEntity : BaseEntity + { + var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); + return expressionRoot.Table(tableName); + } + /// /// Deletes a column from the table mapped to the specified entity, /// resolving the table name using . From 47d62ab6d8f8c2cbe51b47afa1120bd16daa8dea Mon Sep 17 00:00:00 2001 From: Atiqur Rahman Foyshal Date: Tue, 25 Nov 2025 12:03:25 +0600 Subject: [PATCH 11/12] Add method, AlterColumnFor --- .../Extensions/FluentMigratorExtensions.cs | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs index 3ec7822688c..569b69c1e52 100644 --- a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs +++ b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs @@ -150,18 +150,24 @@ public static void TableFor(this ICreateExpressionRoot expressionRoot) } /// - /// Targets the entity's mapped table for an ALTER TABLE operation. + /// Targets a specific column of the entity’s mapped table for an ALTER COLUMN operation, + /// resolving both table and column names using . /// - /// The root expression for an ALTER operation - /// The entity type mapped to the database table + /// The entity type mapped to the database table. + /// The root expression for an ALTER TABLE operation. + /// An expression selecting the entity property to alter. /// - /// A fluent syntax interface allowing further ALTER TABLE operations - /// such as adding or modifying columns. + /// A fluent syntax interface for specifying the new column type + /// and additional ALTER COLUMN options. /// - public static IAlterTableAddColumnOrAlterColumnOrSchemaOrDescriptionSyntax TableFor(this IAlterExpressionRoot expressionRoot) where TEntity : BaseEntity + public static IAlterTableColumnAsTypeSyntax AlterColumnFor(this IAlterExpressionRoot expressionRoot, Expression> selector) where TEntity : BaseEntity { var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); - return expressionRoot.Table(tableName); + var propertyMemberExpression = selector.Body as MemberExpression + ?? (selector.Body as UnaryExpression)?.Operand as MemberExpression + ?? throw new ArgumentException("Selector must be a property expression.", nameof(selector)); + var columnName = NameCompatibilityManager.GetColumnName(typeof(TEntity), propertyMemberExpression.Member.Name); + return expressionRoot.Table(tableName).AlterColumn(columnName); } /// From b94c26b55faccf1dd75509b31fea9d57a084fff5 Mon Sep 17 00:00:00 2001 From: Atiqur Rahman Foyshal Date: Tue, 25 Nov 2025 13:48:05 +0600 Subject: [PATCH 12/12] Add TableFor extension method for ISchemaExpressionRoot --- .../Extensions/FluentMigratorExtensions.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs index 569b69c1e52..4ab5dc404e7 100644 --- a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs +++ b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs @@ -8,6 +8,7 @@ using FluentMigrator.Builders.Create.Table; using FluentMigrator.Builders.Delete; using FluentMigrator.Builders.Schema; +using FluentMigrator.Builders.Schema.Table; using FluentMigrator.Infrastructure.Extensions; using FluentMigrator.Model; using FluentMigrator.Runner; @@ -230,6 +231,21 @@ public static bool ColumnExist( return expressionRoot.Table(tableName).Column(columnName).Exists(); } + /// + /// Targets the entity's mapped table for schema-related operations. + /// + /// The root expression for schema inspection + /// The entity type mapped to the database table + /// + /// A fluent syntax interface for performing schema operations + /// such as checking table or column existence. + /// + public static ISchemaTableSyntax TableFor(this ISchemaExpressionRoot expressionRoot) where TEntity : BaseEntity + { + var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity)); + return expressionRoot.Table(tableName); + } + /// /// Adds a new column to the entity's mapped table for ALTER TABLE operations, /// resolving the column name via .