C# 身份实体框架库-更新数据库[MySQL]

C# 身份实体框架库-更新数据库[MySQL],c#,mysql,entity-framework,C#,Mysql,Entity Framework,我刚刚将库Microsoft.AspNet.Identity.EntityFramework更新为最新版本(2.0.0.0),在创建表时发现一些错误。当我生成迁移代码(Up和Down方法)时,我无法将更改上载到数据库,因为我在执行“updatea database”时遇到了索引问题 指定的密钥太长;最大密钥长度为767字节 要执行的代码: public override void Up() { CreateTable( "dbo.AspNetRol

我刚刚将库Microsoft.AspNet.Identity.EntityFramework更新为最新版本(2.0.0.0),在创建表时发现一些错误。当我生成迁移代码(Up和Down方法)时,我无法将更改上载到数据库,因为我在执行“updatea database”时遇到了索引问题

指定的密钥太长;最大密钥长度为767字节

要执行的代码:

public override void Up()
    {
        CreateTable(
            "dbo.AspNetRoles",
            c => new
                {
                    Id = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                    Name = c.String(nullable: false, maxLength: 256, storeType: "nvarchar"),
                })
            .PrimaryKey(t => t.Id)
            .Index(t => t.Name, unique: true, name: "RoleNameIndex");

        CreateTable(
            "dbo.AspNetUserRoles",
            c => new
                {
                    UserId = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                    RoleId = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                })
            .PrimaryKey(t => new { t.UserId, t.RoleId })
            .ForeignKey("dbo.AspNetRoles", t => t.RoleId, cascadeDelete: true)
            .ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
            .Index(t => t.UserId)
            .Index(t => t.RoleId);

        CreateTable(
            "dbo.AspNetUsers",
            c => new
                {
                    Id = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                    Email = c.String(maxLength: 256, storeType: "nvarchar"),
                    EmailConfirmed = c.Boolean(nullable: false),
                    PasswordHash = c.String(maxLength: 256, storeType: "nvarchar"),
                    SecurityStamp = c.String(maxLength: 256, storeType: "nvarchar"),
                    PhoneNumber = c.String(maxLength: 256, storeType: "nvarchar"),
                    PhoneNumberConfirmed = c.Boolean(nullable: false),
                    TwoFactorEnabled = c.Boolean(nullable: false),
                    LockoutEndDateUtc = c.DateTime(precision: 0),
                    LockoutEnabled = c.Boolean(nullable: false),
                    AccessFailedCount = c.Int(nullable: false),
                    UserName = c.String(nullable: false, maxLength: 256, storeType: "nvarchar"),
                })
            .PrimaryKey(t => t.Id)
            .Index(t => t.UserName, unique: true, name: "UserNameIndex");

        CreateTable(
            "dbo.AspNetUserClaims",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    UserId = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                    ClaimType = c.String(maxLength: 256, storeType: "nvarchar"),
                    ClaimValue = c.String(maxLength: 256, storeType: "nvarchar"),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
            .Index(t => t.UserId);

        CreateTable(
            "dbo.AspNetUserLogins",
            c => new
                {
                    LoginProvider = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                    ProviderKey = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                    UserId = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                })
            .PrimaryKey(t => new { t.LoginProvider, t.ProviderKey, t.UserId })
            .ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
            .Index(t => t.UserId);

    }

    public override void Down()
    {
        DropForeignKey("dbo.AspNetUserRoles", "UserId", "dbo.AspNetUsers");
        DropForeignKey("dbo.AspNetUserLogins", "UserId", "dbo.AspNetUsers");
        DropForeignKey("dbo.AspNetUserClaims", "UserId", "dbo.AspNetUsers");
        DropForeignKey("dbo.AspNetUserRoles", "RoleId", "dbo.AspNetRoles");
        DropIndex("dbo.AspNetUserLogins", new[] { "UserId" });
        DropIndex("dbo.AspNetUserClaims", new[] { "UserId" });
        DropIndex("dbo.AspNetUsers", "UserNameIndex");
        DropIndex("dbo.AspNetUserRoles", new[] { "RoleId" });
        DropIndex("dbo.AspNetUserRoles", new[] { "UserId" });
        DropIndex("dbo.AspNetRoles", "RoleNameIndex");
        DropTable("dbo.AspNetUserLogins");
        DropTable("dbo.AspNetUserClaims");
        DropTable("dbo.AspNetUsers");
        DropTable("dbo.AspNetUserRoles");
        DropTable("dbo.AspNetRoles");
    }
当我使用Microsoft.AspNet.Identity.EntityFramework的1.0.0.0版本时,更新数据库的代码是不同的,我没有任何问题

public override void Up()
    {
        CreateTable(
            "dbo.AspNetRoles",
            c => new
                {
                    Id = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                    Name = c.String(nullable: false, maxLength: 256, storeType: "nvarchar"),
                })
            .PrimaryKey(t => t.Id);

        CreateTable(
            "dbo.AspNetUsers",
            c => new
                {
                    Id = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                    UserName = c.String(maxLength: 256, storeType: "nvarchar"),
                    PasswordHash = c.String(maxLength: 256, storeType: "nvarchar"),
                    SecurityStamp = c.String(maxLength: 256, storeType: "nvarchar"),
                    Discriminator = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                })
            .PrimaryKey(t => t.Id);

        CreateTable(
            "dbo.AspNetUserClaims",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    ClaimType = c.String(maxLength: 256, storeType: "nvarchar"),
                    ClaimValue = c.String(maxLength: 256, storeType: "nvarchar"),
                    User_Id = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.AspNetUsers", t => t.User_Id, cascadeDelete: true)
            .Index(t => t.User_Id);

        CreateTable(
            "dbo.AspNetUserLogins",
            c => new
                {
                    UserId = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                    LoginProvider = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                    ProviderKey = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                })
            .PrimaryKey(t => new { t.UserId, t.LoginProvider, t.ProviderKey })
            .ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
            .Index(t => t.UserId);

        CreateTable(
            "dbo.AspNetUserRoles",
            c => new
                {
                    UserId = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                    RoleId = c.String(nullable: false, maxLength: 128, storeType: "nvarchar"),
                })
            .PrimaryKey(t => new { t.UserId, t.RoleId })
            .ForeignKey("dbo.AspNetRoles", t => t.RoleId, cascadeDelete: true)
            .ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
            .Index(t => t.UserId)
            .Index(t => t.RoleId);

    }



    public override void Down()
    {
        DropForeignKey("dbo.AspNetUserRoles", "UserId", "dbo.AspNetUsers");
        DropForeignKey("dbo.AspNetUserLogins", "UserId", "dbo.AspNetUsers");
        DropForeignKey("dbo.AspNetUserClaims", "UserId", "dbo.AspNetUsers");
        DropForeignKey("dbo.AspNetUserRoles", "RoleId", "dbo.AspNetRoles");
        DropIndex("dbo.AspNetUserLogins", new[] { "UserId" });
        DropIndex("dbo.AspNetUserClaims", new[] { "UserId" });
        DropIndex("dbo.AspNetUsers", "UserNameIndex");
        DropIndex("dbo.AspNetUserRoles", new[] { "RoleId" });
        DropIndex("dbo.AspNetUserRoles", new[] { "UserId" });
        DropIndex("dbo.AspNetRoles", "RoleNameIndex");
        DropTable("dbo.AspNetUserLogins");
        DropTable("dbo.AspNetUserClaims");
        DropTable("dbo.AspNetUsers");
        DropTable("dbo.AspNetUserRoles");
        DropTable("dbo.AspNetRoles");
    }
有人能帮我解决这个问题吗


提前谢谢

您可能想查看本教程:
-特别是“添加自定义MigrationHistory上下文”一节,它解释了如何设置自定义HistoryContext来解决主键大小问题。

这可能是由于您的数据库使用了
UTF8
排序规则

一种可能的解决方法是将包含
maxLength:256
的代码的所有部分更改为
maxLength:190


另一个是将数据库中的
UTF8
排序规则更改为
latin1
或类似的排序规则。

我知道这是一篇老文章,但我今天遇到了同样的问题,并对此进行了一些调查,希望与大家分享我的发现和解决方案

问题在于,Microsoft在两个版本之间为
AspNetRoles
Name
列添加了一个唯一的索引,由于该列的大小为256,因此它打破了MySql的索引规则。此问题也会出现在
AspNetUsers
上的
Name
列上

因此,我分析了如何解决这个问题,我认为最正确的做法是减少
Name
列的长度(我认为,没有任何理由让角色/用户的名称这么长)

在研究了IdentityDbContext(基类)上的代码后,我认为解决此问题的最正确方法是覆盖
ApplicationDbContext
中的
OnModelCreating
,并调整其中的列大小,如下所示:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    //... default code for ApplicationDbContext

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        if (modelBuilder == null)
        {
            throw new ArgumentNullException("modelBuilder");
        }

        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<ApplicationUser>().Property(u => u.UserName).HasMaxLength(128);

        //Uncomment this to have Email length 128 too (not neccessary)
        //modelBuilder.Entity<ApplicationUser>().Property(u => u.Email).HasMaxLength(128);

        modelBuilder.Entity<IdentityRole>().Property(r => r.Name).HasMaxLength(128);
    }
}
public类ApplicationDbContext:IdentityDbContext
{
//…ApplicationDbContext的默认代码
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
if(modelBuilder==null)
{
抛出新的ArgumentNullException(“modelBuilder”);
}
基于模型创建(modelBuilder);
modelBuilder.Entity().Property(u=>u.UserName).HasMaxLength(128);
//取消对此的注释,使电子邮件长度也达到128(不是必需的)
//modelBuilder.Entity().Property(u=>u.Email).HasMaxLength(128);
modelBuilder.Entity().Property(r=>r.Name).HasMaxLength(128);
}
}
此代码将使用
base.OnModelCreating
调用使用默认配置初始化标识模型,然后使用我们自己的调用覆盖在基类中完成的设置

由于您正在创建迁移项目,因此需要重新运行迁移创建以获得更新的模型(或手动修改模型以调整列大小)

这将解决此问题,并且您将拥有Asp.NET标识系统的全部功能


当然,为了在创建项目时不出现任何错误,您可以修改迁移代码,但这样您将与您的上下文定义的模型有所不同,这不好,可能会导致问题。

这对我很有效,谢谢您的提示。我只是转到生成的DbMigration文件(其中包含用于创建数据库的所有SQL命令),并将256的每个实例都更改为190。问题解决了!这是目前最好的方法(EF6.1,ASP.NETMVC5)。同意,这是最好的解决方案(EF6,MVC5)。不要忘记删除上次迁移,它是在密钥仍然为256长时生成的。添加上面的代码,删除上次迁移并重新运行Add migration,然后检查迁移代码以查看Name字段的长度现在是128。