簡體   English   中英

Entity Framework Core:無法在生產服務器上運行遷移腳本,聚集索引的最大鍵長度為 900 字節

[英]Entity Framework Core: Unable to run migration script on production server, The maximum key length for a clustered index is 900 bytes

我正在嘗試在由 Plesk 托管的生產服務器上部署我的 ASP.NET Core 網站。 我的解決方案中有 2 個項目:1 個包含我的DbContext ,1 個包含我的 Web 項目。

我為我的DbContext生成了遷移:

dotnet ef migrations add AddIdentity --project ..\MyProject.Data

然后我生成了文檔中提到的生產遷移腳本( https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dotnet#dotnet-ef-migrations-script

dotnet ef migrations script --idempotent --output "MigrationScripts\AddIdentity.sql" --context MyDbContext --project ..\MyProject.Data

然后我導航到生產服務器 (MyLittleAdmin) 上的 SQL 實用程序並將生成的 SQL 腳本粘貼到其中。 這成功了,但我收到以下錯誤:

警告! 聚集索引的最大鍵長度為 900 字節。 索引“PK_AspNetUserLogins”的最大長度為 1800 字節。 對於某些大值組合,插入/更新操作將失敗。

警告! 聚集索引的最大鍵長度為 900 字節。 索引“PK_AspNetUserTokens”的最大長度為 1804 字節。 對於某些大值組合,插入/更新操作將失敗。

如果忽略此錯誤,稍后我可能會遇到查詢因“沒有明顯原因”(這個原因)而失敗的麻煩。

我的代碼非常簡單:

internal class MintPlayerContext : IdentityDbContext<User, Role, int>
{
    private readonly IConfiguration configuration;
    public MintPlayerContext(IConfiguration configuration) : base()
    {
        this.configuration = configuration;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
        optionsBuilder.UseSqlServer(configuration.GetConnectionString("MintPlayer"), options => options.MigrationsAssembly("MintPlayer.Data"));
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}

internal class User : IdentityUser<int>
{
    public string PictureUrl { get; set; }
}

internal class Role : IdentityRole<int>
{
}

我也嘗試過使用 Guid(我最終想使用 Guid),但即使 int 的 MyLittleAdmin 抱怨 Key 太長。 我已經在谷歌上查過,但這只是提供診斷文章,並沒有真正提供解決方案。

現在這是遷移的 AspNetUsers 部分:

CREATE TABLE [AspNetUsers] (
    [Id] int NOT NULL IDENTITY,
    [UserName] nvarchar(256) NULL,
    [NormalizedUserName] nvarchar(256) NULL,
    [Email] nvarchar(256) NULL,
    [NormalizedEmail] nvarchar(256) NULL,
    [EmailConfirmed] bit NOT NULL,
    [PasswordHash] nvarchar(max) NULL,
    [SecurityStamp] nvarchar(max) NULL,
    [ConcurrencyStamp] nvarchar(max) NULL,
    [PhoneNumber] nvarchar(max) NULL,
    [PhoneNumberConfirmed] bit NOT NULL,
    [TwoFactorEnabled] bit NOT NULL,
    [LockoutEnd] datetimeoffset NULL,
    [LockoutEnabled] bit NOT NULL,
    [AccessFailedCount] int NOT NULL,
    [PictureUrl] nvarchar(max) NULL,
    CONSTRAINT [PK_AspNetUsers] PRIMARY KEY ([Id])
);

我能做些什么來解決這個問題?

編輯:

我嘗試修改我的 DbContext 配置以強制 Key 僅為 Id:

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

    modelBuilder.Entity<User>().HasKey(u => u.Id);
    modelBuilder.Entity<Role>().HasKey(r => r.Id);
}

這似乎確實影響了遷移:

[Id] int NOT NULL IDENTITY,

代替:

[Id] uniqueidentifier NOT NULL,

但它仍然給出同樣的錯誤

編輯:添加 AspNetUserLogins、AspNetUserRoles,去掉 if 的

CREATE TABLE [AspNetUserLogins] (
    [LoginProvider] nvarchar(450) NOT NULL,
    [ProviderKey] nvarchar(450) NOT NULL,
    [ProviderDisplayName] nvarchar(max) NULL,
    [UserId] int NOT NULL,
    CONSTRAINT [PK_AspNetUserLogins] PRIMARY KEY ([LoginProvider], [ProviderKey]),
    CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE
);

CREATE TABLE [AspNetUserTokens] (
    [UserId] int NOT NULL,
    [LoginProvider] nvarchar(450) NOT NULL,
    [Name] nvarchar(450) NOT NULL,
    [Value] nvarchar(max) NULL,
    CONSTRAINT [PK_AspNetUserTokens] PRIMARY KEY ([UserId], [LoginProvider], [Name]),
    CONSTRAINT [FK_AspNetUserTokens_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE
);

您可以嘗試將其更改為:

CREATE TABLE [AspNetUserTokens] (
    [UserId] int NOT NULL,
    [LoginProvider] nvarchar(150) NOT NULL,
    [Name] nvarchar(150) NOT NULL,
    [Value] nvarchar(150) NULL,
    CONSTRAINT [PK_AspNetUserTokens] PRIMARY KEY ([UserId], [LoginProvider], [Name]),
    CONSTRAINT [FK_AspNetUserTokens_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE
);

我認為名稱不能包含超過 150 個字符。 我的意思是它只是一個名字。

所有列的總長度需要小於 900。

ALTER TABLE sampleTable ALTER COLUMN column1 VARCHAR (400) NULL;
ALTER TABLE sampleTable ALTER COLUMN column2 VARCHAR (200) NULL;
ALTER TABLE sampleTable ALTER COLUMN column3 VARCHAR (200) NULL;

根據評論,您應該嘗試外部 Oauth 提供並提出一個合理的數字。

此外,nvarchar 的存儲大小為 *2。 450 * 2 將觸發錯誤。 你可以嘗試減少它。

AspNetUserLoginsAspNetUserTokens需要定義一個較短的鍵。 我假設模型中沒有定義任何鍵,所以所有列都被添加到鍵中。 也許包括一些大的字符串列。

謝謝大家,很及時。 感謝您的所有建議,我設法讓它發揮作用。

由於我使用的是 Code-first,我不能只修改我生成的遷移。 所以這就是我所做的:

internal class MintPlayerContext : IdentityDbContext<User, Role, int>
{
    // dotnet ef migrations add AddIdentity --project ..\MyProject.Data
    // dotnet ef database update --project ..\MyProject.Data
    // (only looks at your appsettings.json file, not your appsettings.*.json, so for local development)

    // To generate production migrations
    // dotnet ef migrations script --idempotent --output "MigrationScripts\AddIdentity.sql" --context MyDbContext --project ..\MyProject.Data

    private readonly IConfiguration configuration;
    public MintPlayerContext(IConfiguration configuration) : base()
    {
        this.configuration = configuration;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
        optionsBuilder.UseSqlServer(configuration.GetConnectionString("MyProject"), options => options.MigrationsAssembly("MyProject.Data"));
    }

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

        modelBuilder.Entity<Microsoft.AspNetCore.Identity.IdentityUserLogin<int>>()
            .Property(ut => ut.LoginProvider)
            .HasMaxLength(50);
        modelBuilder.Entity<Microsoft.AspNetCore.Identity.IdentityUserLogin<int>>()
            .Property(ut => ut.ProviderKey)
            .HasMaxLength(200);

        modelBuilder.Entity<Microsoft.AspNetCore.Identity.IdentityUserToken<int>>()
            .Property(ut => ut.LoginProvider)
            .HasMaxLength(50);
        modelBuilder.Entity<Microsoft.AspNetCore.Identity.IdentityUserToken<int>>()
            .Property(ut => ut.Name)
            .HasMaxLength(50);
    }
}

我將使用 Guid's 為了不讓 UserIds 被猜測。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM