FluentMigrator中CreateTable需显式指定列类型(如.AsDateTime()),主键须用.PrimaryKey().Identity(),外键需单独Create.ForeignKey;Down应撤销变更而非删表;Migration类须public、带long型[Migration]特性、引用完整NuGet包,并配置CopyLocalLockFileAssemblies。

Migration类里怎么写CreateTable才不会报错
FluentMigrator默认不支持在CreateTable中直接用C#类型推导数据库类型,必须显式指定列类型,否则运行时抛System.ArgumentException: No type mapping is configured for type 'DateTime'这类错误。
常见写法是用WithColumn(...).AsDateTime().NotNullable(),而不是.AsType(typeof(DateTime))(后者不被识别)。
-
AsInt32()、AsString(50)、AsDateTime()是安全的内置映射 - 主键要显式调用
.PrimaryKey().Identity(),仅.PrimaryKey()不够(SQL Server会报“无法添加标识列”) - 外键需在
Create.Table之后单独用Create.ForeignKey,不能嵌套在WithColumn链里
如何让Up和Down真正可逆且不丢数据
很多人写Down只做Delete.Table("xxx"),但实际场景中表可能已有数据,直接删表会导致迁移回滚失败或数据丢失。
关键原则:Down操作应尽量“撤销变更”,而非“清空重建”。例如:
- 新增列 → Down里用
Delete.Column("NewCol").FromTable("Users")(注意:SQL Server要求列无默认值/约束才能删) - 改列类型 → Down里不能简单反向改回来,得先
Alter.Column("Age").OnTable("Users").ToDouble()再Alter.Column("Age").OnTable("Users").ToInt32(),但更稳妥是用临时列+数据迁移 - 重命名表 → 必须用
Rename.Table("OldName").To("NewName"),不能Delete.Table+Create.Table,否则Down无法还原
命令行执行迁移时为什么找不到Migration类
典型错误是FluentMigrator.Console.exe --target=MyApp.dll --db=sqlserver2019 --migration=20230101000000报No migrations found,根本原因不是路径错,而是Assembly未正确标记。
- 确保Migration类所在程序集引用了
FluentMigratorNuGet包(不是FluentMigrator.Core) - Migration类必须有
[Migration(20230101000000)]特性,且数字是long类型(64位),写成20230101会被截断导致匹配失败 - 类必须是
public且继承Migration基类,不能是internal或抽象类 - 若用.NET 6+ SDK风格项目,需在
.csproj中加,否则依赖dll不随主程序集复制true
多环境(Dev/Test/Prod)怎么共用同一套Migration
FluentMigrator本身不管理环境配置,靠外部传参驱动。硬编码连接字符串或在Migration里#if DEBUG是危险做法——编译产物会混入环境逻辑,上线后可能执行错SQL。
正确方式是把差异点全部外置:
- 连接字符串通过
--connection参数传入,不要写死在代码里 - 表名前缀(如
dev_)用IMigrationProcessorConvention实现,在ProcessorOptions中注入,而非在Create.Table("Users")里拼接 - 条件性迁移(如只在Test环境加测试数据)应拆分为独立Migration类,并用
[Tags("test")]标记,执行时加--tags=test
最易被忽略的是:Migration类里的Down方法如果依赖环境变量或配置文件,会导致回滚行为不一致——Down必须是纯逻辑逆操作,所有环境都走同一套代码路径。











