diff --git a/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs b/src/Libraries/Nop.Data/Extensions/FluentMigratorExtensions.cs
index 81f9d6f88f8..7c999b4e8b6 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.Linq.Expressions;
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.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,88 @@ public static void TableFor(this ICreateExpressionRoot expressionRoot)
builder.RetrieveTableExpressions(type);
}
+ ///
+ /// 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);
+ }
+
+ ///
+ /// 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 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 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();
+ }
+
+ ///
+ /// 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();
+ }
+
+ ///
+ /// 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 IAlterExpressionRoot expressionRoot, Expression> selector) where TEntity : BaseEntity
+ {
+ var tableName = NameCompatibilityManager.GetTableName(typeof(TEntity));
+ 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);
+ }
+
///
/// 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..4e9af08a18d 100644
--- a/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs
+++ b/src/Libraries/Nop.Data/Migrations/UpgradeTo490/SchemaMigration.cs
@@ -15,89 +15,86 @@ 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.ColumnExist(t => t.AgeVerification))
{
- Alter.Table(productTableName)
- .AddColumn(ageVerificationColumnName)
+ Alter.AddColumnFor(t => t.AgeVerification)
.AsBoolean()
.NotNullable()
.WithDefaultValue(false);
}
- var minimumAgeToPurchaseColumnName = nameof(Product.MinimumAgeToPurchase);
- if (!Schema.Table(productTableName).Column(minimumAgeToPurchaseColumnName).Exists())
+ if (!Schema.ColumnExist(t => t.MinimumAgeToPurchase))
{
- Alter.Table(productTableName)
- .AddColumn(minimumAgeToPurchaseColumnName)
+ Alter.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.Table(topicTableName).Column(topicAvailableEndDateColumnName).Exists())
+ if (!Schema.ColumnExist(t => t.AvailableEndDateTimeUtc))
{
- Alter.Table(topicTableName)
- .AddColumn(topicAvailableEndDateColumnName)
+ Alter.AddColumnFor(t => t.AvailableEndDateTimeUtc)
.AsDateTime()
.Nullable();
}
- if (!Schema.Table(topicTableName).Column(topicAvailableStartDateColumnName).Exists())
+ if (!Schema.ColumnExist(t => t.AvailableStartDateTimeUtc))
{
- Alter.Table(topicTableName)
- .AddColumn(topicAvailableStartDateColumnName)
+ Alter.AddColumnFor(t => t.AvailableStartDateTimeUtc)
.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.ColumnExist(t => t.MetaDescription))
+ {
+ Alter.AddColumnFor(t => t.MetaDescription)
+ .AsString()
+ .Nullable();
+ }
- if (!Schema.Table(productTagTableName).Column(nameof(ProductTag.MetaKeywords)).Exists())
- Alter.Table(productTagTableName).AddColumn(nameof(ProductTag.MetaKeywords)).AsString(400).Nullable();
+ if (!Schema.ColumnExist(t => t.MetaKeywords))
+ {
+ Alter.AddColumnFor(t => t.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.ColumnExist(t => t.MetaTitle))
+ {
+ Alter.AddColumnFor(t => t.MetaTitle)
+ .AsString(400)
+ .Nullable();
+ }
//#7390
- if (!Schema.Table(nameof(Menu)).Exists())
+ if (!Schema.TableExist