![](/img/trans.png)
[英]How to run migration SQL script using Entity Framework Core
[英]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 將觸發錯誤。 你可以嘗試減少它。
AspNetUserLogins
和AspNetUserTokens
需要定義一個較短的鍵。 我假設模型中沒有定義任何鍵,所以所有列都被添加到鍵中。 也許包括一些大的字符串列。
謝謝大家,很及時。 感謝您的所有建議,我設法讓它發揮作用。
由於我使用的是 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.