1

我在项目中使用 MySQL 数据库时遇到问题。一般来说,一些项目表需要在输入数据时有一个自动递增的字段。但是,在 MySQL 中,除了 Id 之外的列只有在它是唯一键时才能自动递增。例如:

public class Client
{
    [Key]
    public Guid Id { get; set; }

    [MaxLength(200)]
    public string Name { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long Code { get; set; }

    public DateTime BirthDate { get; set; }
}

但是,在 MySQL 中,除了Id唯一键之外的列只能自动递增。例如:

modelBuilder.Entity<Client>()
    .HasIndex(c => c.Code)
    .IsUnique();

到目前为止,一切都很好。Code正确且正在编译。但是,在生成迁移时,结果是:

第1部分:

migrationBuilder.CreateTable(
    name: "Client",
    columns: table => new
    {
        Id = table.Column<Guid>(nullable: false),
        Code = table.Column<int>(nullable: false)
            .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
        Name = table.Column<string>(maxLength: 200, nullable: false),
        BirthDate = table.Column<DateTime>(nullable: false)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Client", x => x.Id);
    }
);

第2部分:

migrationBuilder.CreateIndex(
    name: "IX_Client_Code",
    table: "Client",
    column: "Code",
    unique: true);

Ao executar a atualização do banco de dados ( database update) a seguinte mensagem é exibida: Incorrect table definition; there can be only one auto column and it must be defined as a key.

此错误是由创建迁移的方式引起的。在上面的代码的第一部分中,已经明确指出“代码”是MySqlValueGenerationStrategy.IdentityColumn,因此会发生错误。为了解决这个问题,我必须创建两个迁移:第一个只将Code字段添加到 single,第二个插入自动增量。但是,我不想以这种方式使用它,因为每次我都必须创建至少两个迁移。

注意:在这种情况下,我可以放弃GUID`` 而只对表使用Code( int),但这是不可能的,因为我必须修改所有表的结构。另外,我发现的另一个可能的解决方案是将 ID 和 Code 设为主键,但我不太可能以这种方式使用它。

4

1 回答 1

2

有两种方法可以解决这个问题。

如果你只是想手动修复迁移代码,那么不要使用CreateIndex,而只是将备用键添加到创建表操作的约束中:

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.CreateTable(
        name: "Client",
        columns: table => new
        {
            Id = table.Column<Guid>(nullable: false),
            Name = table.Column<string>(maxLength: 200, nullable: true),
            Code = table.Column<long>(nullable: false)
                .Annotation("MySql:ValueGenerationStrategy",
                            MySqlValueGenerationStrategy.IdentityColumn),
            BirthDate = table.Column<DateTime>(nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_Client", x => x.Id);
            table.UniqueConstraint("AK_Client", x => x.Code); // <-- Add unique constraint
        });
}

没有数据注释来定义备用键,但您可以使用fluent API

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Client>(entity => entity.HasAlternateKey(e => e.Code));
}

这将创建与上面相同的工作迁移代码,并导致以下CREATE TABLE语句:

CREATE TABLE `Client` (
    `Id` char(36) NOT NULL,
    `Name` varchar(200) CHARACTER SET utf8mb4 NULL,
    `Code` bigint NOT NULL AUTO_INCREMENT,
    `BirthDate` datetime(6) NOT NULL,
    CONSTRAINT `PK_Client` PRIMARY KEY (`Id`),
    CONSTRAINT `AK_Client` UNIQUE (`Code`)
);

使用HasIndex().IsUnique()将不起作用,因为这将产生CreateIndex()与您在问题中描述的相同问题的呼叫。

于 2019-11-30T01:18:14.987 回答