【问题标题】:Change data type from int to long of key property in model .net Core 2.2将模型.net Core 2.2中关键属性的数据类型从int更改为long
【发布时间】:2019-08-18 04:41:37
【问题描述】:

我想将 ASP.Net core 2.2 中模型的主键数据类型从 int 更改为 long,因为它即将超出 int 范围。该应用程序是代码优先完成的,并使用 SQL Server 作为数据库。

更改模型中的数据类型有效,运行 Add-Migration 也有效,但 Update-Database 失败并出现错误:

System.Data.SqlClient.SqlException (0x80131904): The index 'IX_tblMTransactions_OriginalTransactionId' is dependent on column 'OriginalTransactionId'.
The object 'FK_tblMTransactions_tblMTransactions_OriginalTransactionId' is dependent on column 'OriginalTransactionId'.

所以我读到了它,似乎需要对迁移进行一些调整,比如在列更改之前删除外键和索引,然后再将它们带回来。不幸的是,我在.net core 2.2 中找不到任何有用的信息,我找到的最接近的是this question,但它谈到了.net core 2.1 和选项DropForeignKeyDropIndex 提到根据this article,.net core 2.2 似乎不再可用。

这里是迁移类:

public partial class _20190817_1746 : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<long>(
            name: "OriginalTransactionId",
            table: "tblMTransactions",
            nullable: true,
            oldClrType: typeof(int),
            oldNullable: true);

        migrationBuilder.AlterColumn<long>(
            name: "Id",
            table: "tblMTransactions",
            nullable: false,
            oldClrType: typeof(int))
            .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn)
            .OldAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<int>(
            name: "OriginalTransactionId",
            table: "tblMTransactions",
            nullable: true,
            oldClrType: typeof(long),
            oldNullable: true);

        migrationBuilder.AlterColumn<int>(
            name: "Id",
            table: "tblMTransactions",
            nullable: false,
            oldClrType: typeof(long))
            .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn)
            .OldAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
    }
}

这是该表的列、键和索引的屏幕截图:

有人知道如何调整 .NET Core 2.2 中的迁移类以使其正常工作吗?

谢谢

【问题讨论】:

  • DropForeignKey / DropIndex 在 2.2 中可用。只是链接(文档)是针对 2.1 的,没有针对 2.2 的文档
  • 很有趣 - 但它与文章中提到的命名空间不同吗?因为它在Microsoft.EntityFrameworkCore.Migrations 和 Ctrl 下找不到。 Dot (Visual Studio) 也没有在不同的命名空间下找到它。
  • 抱歉,链接的问题是针对 EF6 的。对于 EF Core,所有这些都是 MigrationBuilder 类的实例方法(如生成的迁移中的 CreateTableAlterColumn 等)。看看migrationBuilder.DropForeignKey(name: "...", table: "...")等。
  • @IvanStoev,它实际上像你说的那样工作 - 请参阅下面的答案。非常感谢!

标签: c# asp.net-core-mvc entity-framework-core-2.2


【解决方案1】:

感谢Ivan Stoev 我能够找到解决方案。我必须像这样手动添加索引和键的删除和创建:

public partial class _20190817_2317 : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropForeignKey(
            name: "FK_tblMTransactions_tblMTransactions_OriginalTransactionId",
            table: "tblMTransactions");

        migrationBuilder.DropIndex(
            name: "IX_tblMTransactions_OriginalTransactionId",
            table: "tblMTransactions");

        migrationBuilder.DropPrimaryKey(
            name: "PK_tblMTransactions",
            table: "tblMTransactions");

        migrationBuilder.AlterColumn<long>(
            name: "OriginalTransactionId",
            table: "tblMTransactions",
            nullable: true,
            oldClrType: typeof(int),
            oldNullable: true);

        migrationBuilder.AlterColumn<long>(
            name: "Id",
            table: "tblMTransactions",
            nullable: false,
            oldClrType: typeof(int))
            .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn)
            .OldAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);

        migrationBuilder.AddPrimaryKey(
            name: "PK_tblMTransactions",
            table: "tblMTransactions",
            column: "Id");

        migrationBuilder.CreateIndex(
            name: "IX_tblMTransactions_OriginalTransactionId",
            table: "tblMTransactions",
            column: "OriginalTransactionId");

        migrationBuilder.AddForeignKey(
            name: "FK_tblMTransactions_tblMTransactions_OriginalTransactionId",
            table: "tblMTransactions",
            column: "OriginalTransactionId",
            principalTable: "tblMTransactions",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<int>(
            name: "OriginalTransactionId",
            table: "tblMTransactions",
            nullable: true,
            oldClrType: typeof(long),
            oldNullable: true);

        migrationBuilder.AlterColumn<int>(
            name: "Id",
            table: "tblMTransactions",
            nullable: false,
            oldClrType: typeof(long))
            .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn)
            .OldAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
    }
}

再次感谢伊万!!

【讨论】:

  • 你不需要对 Down 方法做同样的事情吗?先删除键和索引,做alter然后再添加键和索引?
  • 如果表中有很多记录,添加主键可能需要很长时间。我不得不延长命令超时:Database.SetCommandTimeout(150000);见:stackoverflow.com/questions/39006847/…
  • 是的,在一个完美的世界中,您也应该在 Down() 方法中处理它,只是在我正在处理的项目中,我们永远不会在生产后撤消迁移,这就是我们不需要修改它的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-05
  • 1970-01-01
  • 1970-01-01
  • 2018-04-14
  • 2011-01-19
相关资源
最近更新 更多