ASP.NET 3 IDを見ると、一意の主キーにstring
ではなくGuid
を使用しています。
Entity Framework
code first
ユーザーのApplicationUser
クラスでは、Identityクラスを継承します
public class ApplicationUser : IdentityUser
{
}
entity Frameworkの移行を作成すると、aspnetusers
の代わりにnvarchar(450)
のキータイプでテーブルuniqueidentifier
が作成されます。
これをASP.NET Identity 2
ENtity Framework
プロジェクトと比較すると、nvarchar(450)
ではなくuniqueidentifier
のIDフィールドが作成されました
データベースのパフォーマンスのために、uniqueidentifier
の主キーと外部キーはnvarchar(450)
よりも優れていると思います
ASP.NET Identity 3
でnvarchar(450)
の代わりにGuid
およびstring
の代わりにuniqueidentifier
の一意のキーに使用する方法はありますか?
前の質問 StringをGUIDに変換する方法がありますが、データベーステーブルIDをGUIDにしたいです。
長さがnvarchar(128)であった場合、以前のベータ版でも別の question が見つかりました。指定された理由は、すべてのデータベースがGUIDをサポートしているわけではなく、柔軟性のために変更されたためです。
identity 3
全体を書き換えずに文字列からGuidに変更する簡単な方法が必要ですか?
nvarchar(450)
は本当に過剰であり、SQL Serverデータベースの制約を作成するときにあらゆる種類の警告を出します。データベース管理者は間違いなくこれらの警告を好まないでしょう。
カスタムApplicationUser
はIdentityUser<TKey>
から継承し、カスタムロールはIdentityRole<TKey>
から継承する必要があります
public class ApplicationUser : IdentityUser<Guid> { }
public class Role : IdentityRole<Guid> { }
カスタムコンテキストクラスはIdentityDbContext<ApplicationUser, Role, TKey>
を継承し、流uidなapiを使用してGUIDキーを自動生成します。
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, Role, Guid>
{
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<ApplicationUser>(b =>
{
b.Property(u => u.Id).HasDefaultValueSql("newsequentialid()");
});
builder.Entity<Role>(b =>
{
b.Property(u => u.Id).HasDefaultValueSql("newsequentialid()");
});
}
}
次に、スタートアップでこのようなコンテナにIdentityサービスを追加します
services.AddIdentity<ApplicationUser, Role>()
.AddEntityFrameworkStores<ApplicationDbContext, Guid>()
.AddDefaultTokenProviders()
.AddUserStore<UserStore<ApplicationUser, Role, ApplicationDbContext, Guid>> ()
.AddRoleStore<RoleStore<Role, ApplicationDbContext, Guid>>();
データベースを作成していない場合は、移行フォルダーをクリアしてefコマンドを実行します
私はまだこの例の移行をいじっていません(いくつかの調整が必要な場合があります)が、ASP.NET Identity v3は、この点でv2よりもはるかに拡張可能です。
以下は、ユーザーとロールの両方のGUID主キーに基づくIDストアを提供するはずです。
public class ApplicationUser : IdentityUser<Guid>
{
}
public class GuidDataContext :
IdentityDbContext<ApplicationUser, IdentityRole<Guid>, Guid>
{
}
そしてあなたのスタートアップクラスで:
services.AddIdentity<ApplicationUser, IdentityRole<Guid>>(
identity =>
{
// whatever identity options you want
identity.User.RequireUniqueEmail = true;
identity.Password.RequiredLength = 8;
}).
AddEntityFrameworkStores<GuidDataContext, Guid>().AddDefaultTokenProviders();
同様に、カスタムユーザーにカスタムフィールドを追加したり、オプションをカスタマイズしたりする必要がない場合は、次の操作を実行できます。
public class GuidDataContext :
IdentityDbContext<IdentityUser<Guid>, IdentityRole<Guid>, Guid>
{
}
そしてあなたのスタートアップで:
services
.AddIdentity<IdentityUser<Guid>, IdentityRole<Guid>>()
.AddEntityFrameworkStores<GuidDataContext, Guid>()
.AddDefaultTokenProviders();
ApplicationUserは、 IdentityUser をidとして文字列を持つものとして定義されている基本クラスから継承します。そのため、実際にguid/uniqueidentifierを使用するには、その基本クラスから継承しないようにする必要があります。
内部的にはidにguid文字列を使用していることに注意してください。少なくとも、次のようにキーのフィールドサイズを制限できる必要があります。
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<ApplicationUser>(b =>
{
// you could limit the field size to just long enough for a guid id as string
b.Property(p => p.Id)
.HasMaxLength(36);
// instead, you could define the id as Guid but more work required
//b.Property(p => p.Id)
// .ForSqlServerHasColumnType("uniqueidentifier")
// .ForSqlServerHasDefaultValueSql("newid()")
// .IsRequired();
});
}
}
キーにGuids/uniqueidentifierを使用できますが、独自の基本クラスを使用する(または基本クラスをまったく使用しない)だけでなく、より多くの作業が必要になり、カスタムDbContextを使用してモデルをマップします。 ここからのEFコード を借りて変更すると、うまくいきます。 serStore から継承し、IDでユーザーを検索するための仮想メソッドをオーバーライドする必要があります。 IUserStore は、FindByIdメソッドシグネチャを文字列で定義します。したがって、オーバーライドするには、IDで取得または検索する必要があるメソッド内で文字列をGUIDに変換する必要があります。
私は cloudscribeプロジェクト でそれを正確に行っています。これはIdentityのカスタムマルチテナント実装を持っています
編集:実際にコードを詳しく見ると、IdentityUserにはキーのタイプを定義できる汎用バージョンがあります
public class IdentityUser<TKey> where TKey : IEquatable<TKey>
したがって、次のように独自の基本クラスを定義することができるかもしれません
IdentityUser<Guid>
ただし、ID文字列を取得して文字列をGUIDに変換するUserStoreメソッドをオーバーライドする必要があると思います。