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

时间:2018-02-08 05:51:47

标签: 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`)
);

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

如何自定义默认身份表的创建方式?如果可能的话,我想用这个表上更健全的主键替换庞大的键,这只是一个auto increment整数。

有没有办法自定义如何创建默认的身份相关表,而无需手动黑客攻击文件。我可以用OnModelCreating的{​​{1}}方法做任何事情吗?我应该停止与MySQL战斗并屈服于MS SQL吗?

修改

我能够使用Pomelo MySQL Driver而非Oracle来解决此问题。 Pomelo驱动程序似乎默认字符串字段最大长度为127个字符,这允许上面的键适合3072字节限制。但是,我仍然有兴趣知道如何微调和自定义.NETCore脚手架中提供的基本身份表。

4 个答案:

答案 0 :(得分:4)

我不建议完全离开MySQL以解决这些问题。它现在已经是最常用的数据库了。既然您已经花时间处理这些问题并从中学习,那么尝试完整的循环并获得完整的理解是值得的。

就你使用柚子而言,你应该没问题。我建议坚持这一点。它确实有更多的git和nuget下载,也有更多的git明星。 Oracle的nuget,甚至是它的发布"版本仍未完成。据报道,它有未实现的功能https://bugs.mysql.com/bug.php?id=82981。如果MS正式提到官方提供商旁边的Pomelo,它应该是真的。

关于您的主要问题,您应该可以在OnModelCreate

中执行此类操作
builder.Entity<ApplicationUser>()
    .Property(u => u.Id)
    .HasMaxLength(36);

请注意,根据IdentityUser<TKey>Id = Guid.NewGuid().ToString(),它只需要36个字符。或者,您可以利用Id是虚拟字段并在ApplicationUser类中执行此操作的事实:

[MaxLength(36)]
public override string Id { get; set; }

另外,我并不是要反驳我所说的内容,但是对于某些项目来说,尝试SQL Server也没什么坏处。与MySQL相比,我确实在SQL Server中找到了几个便利。我不认为许可是不尝试SQL Server的原因。许多情况下许可并不重要,有几个原因。

  1. 您可以在linux和windows中免费托管10 GB。对于许多情况,10 GB对于数据库来说很重要。
  2. &#34; web&#34;版本完全免费,存储仅限于VM空间。至少在azure的情况下,您只需支付服务费用。不确定其余的
  3. 如果您正在尝试使用.NET,那么它主要由那些不会介意许可的企业使用。如果你碰巧为他们工作或自由职业,你就不用担心许可证。

答案 1 :(得分:4)

以下设置适用于具有自定义身份的 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));

我仅将 MaxLength 用于主键和索引。

答案 2 :(得分:0)

我只是想添加到@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));
        }

答案 3 :(得分:0)

更好的选择是 MaxLengthForKeys 为身份存储中的所有键设置此项(在 ConfigureServices 方法内)。

services.AddDefaultIdentity<User>(options =>
{
    options.SignIn.RequireConfirmedAccount = true;
    options.Stores.MaxLengthForKeys = 85;
})
.AddEntityFrameworkStores<ApplicationDbContext>();

这是文档中的注释

<块引用>

如果设置为正数,默认的 OnModelCreating 将使用此值作为用作键的任何属性的最大长度,即 UserId、LoginProvider,