带有MySQL的.NET Core 2.0:指定的密钥太长;最大密钥长度为3072字节

Bra*_*rad 3 mysql asp.net-identity asp.net-core-2.0

我是一名PHP / MySQL开发人员,试图转移到其他技术,例如.NET Core。我不确定我是否喜欢通过MySQL切换到SQL Server的想法(由于许可),因此我一直在尝试使.NET Core与MySQL很好地兼容。

我已经使用Identity作为身份验证方法建立了一个相当基本的.NET Core 2.0项目,并且当数据库驱动程序SqlLite与本地数据库一起使用时,一切工作正常。我尝试切换到MySQL数据库并运行迁移,但迁移失败。

我收到错误消息:Specified key was too long; max key length is 3072 bytes 尝试运行以下表创建查询时:

CREATE TABLE `AspNetUserTokens` (
    `UserId` varchar(767) NOT NULL,
    `LoginProvider` varchar(767) NOT NULL,
    `Name` varchar(767) NOT NULL,
    `Value` text NULL,
    PRIMARY KEY (`UserId`, `LoginProvider`, `Name`)
);
Run Code Online (Sandbox Code Playgroud)

Mysql数据库使用字符集,UTF8mb4因此不能使用上面指定的主键,该主键的大小约为9204字节。

如何自定义默认身份表的创建方式?如果可能的话,我想用这个表上更合理的主键(只不过是auto increment整数)来替换大键。

有什么方法可以自定义默认身份相关表的创建方式,而无需手动修改迁移文件。我可以OnModelCreating用我的方法做些什么ApplicationDbContext吗?我应该停止与MySQL对抗并屈服于MS SQL吗?

编辑

通过使用Pomelo MySQL驱动程序而不是Oracle,我能够解决该问题。Pomelo驱动程序似乎默认将字符串字段的最大长度限制为127个字符,从而使上述键可以容纳3072个字节的限制。但是,我仍然会对了解如何微调和自定义.NETCore脚手架中提供的基本Identity表感兴趣。

小智 12

我只是想添加到@neville 的答案中,让其他任何人都可以使用默认的 MySql.Data.EntityFrameworkCore nuget 包来解决。

您需要在 dbcontext OnModelCreating 中添加以下键的最大长度,然后运行 ​​add-migration 才能生效。

在此处创建一个示例 https://github.com/k-siddharatha/DotNetCoreEFMySql

只是为了这个问题。

protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);


            builder.Entity<IdentityUser>(entity => entity.Property(m => m.Id).HasMaxLength(85));
            builder.Entity<IdentityUser>(entity => entity.Property(m => m.NormalizedEmail).HasMaxLength(85));
            builder.Entity<IdentityUser>(entity => entity.Property(m => m.NormalizedUserName).HasMaxLength(85));

            builder.Entity<IdentityRole>(entity => entity.Property(m => m.Id).HasMaxLength(85));
            builder.Entity<IdentityRole>(entity => entity.Property(m => m.NormalizedName).HasMaxLength(85));

            builder.Entity<IdentityUserLogin<string>>(entity => entity.Property(m => m.LoginProvider).HasMaxLength(85));
            builder.Entity<IdentityUserLogin<string>>(entity => entity.Property(m => m.ProviderKey).HasMaxLength(85));
            builder.Entity<IdentityUserLogin<string>>(entity => entity.Property(m => m.UserId).HasMaxLength(85));
            builder.Entity<IdentityUserRole<string>>(entity => entity.Property(m => m.UserId).HasMaxLength(85));

            builder.Entity<IdentityUserRole<string>>(entity => entity.Property(m => m.RoleId).HasMaxLength(85));

            builder.Entity<IdentityUserToken<string>>(entity => entity.Property(m => m.UserId).HasMaxLength(85));
            builder.Entity<IdentityUserToken<string>>(entity => entity.Property(m => m.LoginProvider).HasMaxLength(85));
            builder.Entity<IdentityUserToken<string>>(entity => entity.Property(m => m.Name).HasMaxLength(85));

            builder.Entity<IdentityUserClaim<string>>(entity => entity.Property(m => m.Id).HasMaxLength(85));
            builder.Entity<IdentityUserClaim<string>>(entity => entity.Property(m => m.UserId).HasMaxLength(85));
            builder.Entity<IdentityRoleClaim<string>>(entity => entity.Property(m => m.Id).HasMaxLength(85));
            builder.Entity<IdentityRoleClaim<string>>(entity => entity.Property(m => m.RoleId).HasMaxLength(85));
        }
Run Code Online (Sandbox Code Playgroud)

  • 这很有用并受到好评。但尽管如此,还是有一些遗漏,例如 AspNetUsers 表、AspNetUserTokens 的 PK 索引和 PersistedGrants。在没有找到实际修复的情况下,必须手动修改 InitialCreate 文件来解决这些问题 (2认同)

Nev*_*ane 6

对于这些问题,我不建议您完全离开MySQL。一段时间以来,它一直是最常用的数据库。由于您已经花时间解决了这些问题并从中学习了经验,因此值得尝试完整的周期并获得完整的理解。

就使用Pomelo而言,您应该没问题。我建议坚持。它确实在git和nuget上都有更多的下载,并且还有更多的git star。Oracle的nuget,甚至其“发行”版本仍未完成。据报道,它具有未实现的功能https://bugs.mysql.com/bug.php?id=82981。如果MS Pomelo在官方提供者旁边正式提到了它,那的确应该是。

关于您的主要问题,您应该可以在自己的服务器中执行以下操作OnModelCreate

builder.Entity<ApplicationUser>()
    .Property(u => u.Id)
    .HasMaxLength(36);
Run Code Online (Sandbox Code Playgroud)

请注意,根据IdentityUser<TKey>Id = Guid.NewGuid().ToString(),它仅需要36个字符。另外,您可以利用Id一个虚拟字段这一事实的优势,并在您的ApplicationUser课堂上这样做:

[MaxLength(36)]
public override string Id { get; set; }
Run Code Online (Sandbox Code Playgroud)

另外,我并不是要与我所说的相抵触,但是对于某些项目而言,尝试使用SQL Server也没有害处。与MySQL相比,我确实在SQL Server中找到了许多便利。我认为许可不是不尝试使用SQL Server的理由。在许多情况下,许可实际上并不重要有几个原因。

  1. 您可以在Linux和Windows中最多托管10 GB的空闲空间。在许多情况下,数据库需要10 GB。
  2. “ Web”版本是完全免费的,并且存储空间仅限于VM空间。至少天蓝色就是这种情况,您只需为服务付费。不确定其余
  3. 如果您尝试使用.NET,则主要由那些不介意许可的企业使用。如果您碰巧为他们工作或是自由职业者,则不必担心许可证问题。


Laz*_*iya 5

以下设置适用于具有自定义身份的 Asp.Net 5.0:

builder.Entity<AppUser>(entity => entity.Property(m => m.Id).HasMaxLength(85));
builder.Entity<AppRole>(entity => entity.Property(m => m.Id).HasMaxLength(85));

builder.Entity<IdentityUserClaim<string>>(entity => entity.Property(m => m.Id).HasMaxLength(85));
builder.Entity<IdentityRoleClaim<string>>(entity => entity.Property(m => m.Id).HasMaxLength(85));

builder.Entity<IdentityUserLogin<string>>(entity => entity.Property(m => m.LoginProvider).HasMaxLength(85));
builder.Entity<IdentityUserLogin<string>>(entity => entity.Property(m => m.ProviderKey).HasMaxLength(85));

builder.Entity<IdentityUserToken<string>>(entity => entity.Property(m => m.LoginProvider).HasMaxLength(85));
builder.Entity<IdentityUserToken<string>>(entity => entity.Property(m => m.Name).HasMaxLength(85));
Run Code Online (Sandbox Code Playgroud)

MaxLength只用于主键和索引。