【问题标题】:Identity Entity Framework Library - Update Database [MySQL]身份实体框架库 - 更新数据库 [MySQL]
【发布时间】:2014-05-09 10:42:09
【问题描述】:

我刚刚将 Microsoft.AspNet.Identity.EntityFramework 库更新到了最新版本 (2.0.0.0),我发现创建表时出现了一些错误。当我生成迁移代码(Up 和 Down 方法)时,我无法将更改上传到数据库,因为我在执行“Updata-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");
    }

谁能帮我解决这个问题?

提前致谢!!

【问题讨论】:

    标签: c# mysql entity-framework


    【解决方案1】:

    我知道这是一篇旧帖子,但我今天遇到了同样的问题并对此进行了一些调查,并希望分享我的发现和解决方案。

    问题是微软在两个版本之间为AspNetRolesName列添加了唯一索引,并且由于该列的大小为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);
        }
    }
    

    此代码将使用 base.OnModelCreating 调用的默认配置初始化身份模型,然后使用我们自己的覆盖在基类中完成的设置。

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

    这将解决问题,您将拥有 Asp.NET 身份系统的全部功能。

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

    【讨论】:

    • 这是目前最好的方法(EF6.1、ASP.NET MVC 5)。
    • 同意,这是最好的解决方案(EF6,MVC5)。不要忘记删除在密钥仍为 256 长时生成的最后一次迁移。添加上面的代码,删除上次的迁移,重新运行add-migration,查看迁移代码,现在Name字段的长度是128。
    【解决方案2】:

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

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

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

    【讨论】:

    • 这对我有用,谢谢你的提示。我刚刚转到生成的 DbMigration 文件(其中包含用于创建数据库的所有 SQL 命令),并将每个实例 256 更改为 190。问题解决了!
    【解决方案3】:

    您可能想查看本教程:http://www.asp.net/mvc/tutorials/security/aspnet-identity-using-mysql-storage-with-an-entityframework-mysql-provider - 特别是“添加自定义 MigrationHistory 上下文”部分,它解释了如何设置自定义 HistoryContext 来解决主键大小问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-05
      • 2011-04-28
      • 2011-04-26
      相关资源
      最近更新 更多