Identity ASP.NET Core'da model özelleştirme
Tarafından Arthur Vickers
ASP.NET Core, ASP.NET Core Identity uygulamalarında kullanıcı hesaplarını yönetmek ve depolamak için bir çerçeve sağlar. Identitykimlik doğrulama mekanizması olarak Bireysel Kullanıcı Hesapları seçildiğinde projenize eklenir. Varsayılan olarak, Identity Entity Framework (EF) Core veri modelini kullanır. Bu makalede modelin nasıl özelleştirileceği Identity açıklanmaktadır.
Identity ve EF Core Geçişler
Modeli incelemeden önce, veritabanı oluşturmak ve güncelleştirmek için Geçişler ile EF Core nasıl Identity çalıştığını anlamak yararlı olur. En üst düzeyde işlem şu şekildedir:
- Kodda veri modeli tanımlama veya güncelleştirme.
- Bu modeli veritabanına uygulanabilecek değişikliklere çevirmek için bir Geçiş ekleyin.
- Geçiş işleminin amacınızı doğru şekilde temsil ettiğini denetleyin.
- Veritabanını modelle eşitlenecek şekilde güncelleştirmek için Geçişi uygulayın.
- Modeli daha da geliştirmek ve veritabanını eşitlenmiş durumda tutmak için 1 ile 4 arasındaki adımları yineleyin.
Geçişleri eklemek ve uygulamak için aşağıdaki yaklaşımlardan birini kullanın:
- Visual Studio kullanılıyorsa Paket Yöneticisi Konsolu (PMC) penceresi. Daha fazla bilgi için bkz EF Core . PMC araçları.
- Komut satırını kullanıyorsanız .NET CLI. Daha fazla bilgi için bkz EF Core . .NET komut satırı araçları.
- Uygulama çalıştırıldığında hata sayfasında Geçişleri Uygula düğmesine tıklama.
ASP.NET Core'un geliştirme zamanı hata sayfası işleyicisi vardır. İşleyici, uygulama çalıştırıldığında geçişleri uygulayabilir. Üretim uygulamaları genellikle geçişlerden SQL betikleri oluşturur ve veritabanı değişikliklerini denetimli bir uygulama ve veritabanı dağıtımının parçası olarak dağıtır.
kullanan Identity yeni bir uygulama oluşturulduğunda yukarıdaki 1. ve 2. adımlar zaten tamamlanmıştır. Yani, ilk veri modeli zaten var ve ilk geçiş projeye eklendi. İlk geçişin yine de veritabanına uygulanması gerekir. İlk geçiş aşağıdaki yaklaşımlardan biri aracılığıyla uygulanabilir:
- PMC'de çalıştırın
Update-Database
. - Komut kabuğunda komutunu çalıştırın
dotnet ef database update
. - Uygulama çalıştırıldığında hata sayfasındaki Geçişleri Uygula düğmesine tıklayın.
Modelde değişiklikler yapılırken önceki adımları yineleyin.
Model Identity
Varlık türleri
Model Identity aşağıdaki varlık türlerinden oluşur.
Varlık türü | Açıklama |
---|---|
User |
Kullanıcıyı temsil eder. |
Role |
Bir rolü temsil eder. |
UserClaim |
Kullanıcının sahip olduğu bir talebi temsil eder. |
UserToken |
Bir kullanıcı için kimlik doğrulama belirtecini temsil eder. |
UserLogin |
Kullanıcıyı oturum açma bilgileriyle ilişkilendirir. |
RoleClaim |
Bir rol içindeki tüm kullanıcılara verilen bir talebi temsil eder. |
UserRole |
Kullanıcıları ve rolleri ilişkilendiren birleştirme varlığı. |
Varlık türü ilişkileri
Varlık türleri aşağıdaki yollarla birbiriyle ilişkilidir:
- Her
User
birinde birçokUserClaims
olabilir. - Her
User
birinde birçokUserLogins
olabilir. - Her
User
birinde birçokUserTokens
olabilir. - Her
Role
birinde birçok ilişkiliRoleClaims
olabilir. - Her
User
birinde birçok ilişkiliRoles
olabilir ve herRole
birinin birçokUsers
ile ilişkilendirilebilir. Bu, veritabanında birleştirme tablosu gerektiren çoka çok ilişkisidir. Birleştirme tablosu varlık tarafındanUserRole
temsil edilir.
Varsayılan model yapılandırması
Identity, modeli yapılandırmak ve kullanmak için öğesini DbContext devralan birçok bağlam sınıfını tanımlar. Bu yapılandırma, bağlam sınıfının yönteminde Code First Fluent API'sini OnModelCreating kullanarak EF Core gerçekleştirilir. Varsayılan yapılandırma:
builder.Entity<TUser>(b =>
{
// Primary key
b.HasKey(u => u.Id);
// Indexes for "normalized" username and email, to allow efficient lookups
b.HasIndex(u => u.NormalizedUserName).HasName("UserNameIndex").IsUnique();
b.HasIndex(u => u.NormalizedEmail).HasName("EmailIndex");
// Maps to the AspNetUsers table
b.ToTable("AspNetUsers");
// A concurrency token for use with the optimistic concurrency checking
b.Property(u => u.ConcurrencyStamp).IsConcurrencyToken();
// Limit the size of columns to use efficient database types
b.Property(u => u.UserName).HasMaxLength(256);
b.Property(u => u.NormalizedUserName).HasMaxLength(256);
b.Property(u => u.Email).HasMaxLength(256);
b.Property(u => u.NormalizedEmail).HasMaxLength(256);
// The relationships between User and other entity types
// Note that these relationships are configured with no navigation properties
// Each User can have many UserClaims
b.HasMany<TUserClaim>().WithOne().HasForeignKey(uc => uc.UserId).IsRequired();
// Each User can have many UserLogins
b.HasMany<TUserLogin>().WithOne().HasForeignKey(ul => ul.UserId).IsRequired();
// Each User can have many UserTokens
b.HasMany<TUserToken>().WithOne().HasForeignKey(ut => ut.UserId).IsRequired();
// Each User can have many entries in the UserRole join table
b.HasMany<TUserRole>().WithOne().HasForeignKey(ur => ur.UserId).IsRequired();
});
builder.Entity<TUserClaim>(b =>
{
// Primary key
b.HasKey(uc => uc.Id);
// Maps to the AspNetUserClaims table
b.ToTable("AspNetUserClaims");
});
builder.Entity<TUserLogin>(b =>
{
// Composite primary key consisting of the LoginProvider and the key to use
// with that provider
b.HasKey(l => new { l.LoginProvider, l.ProviderKey });
// Limit the size of the composite key columns due to common DB restrictions
b.Property(l => l.LoginProvider).HasMaxLength(128);
b.Property(l => l.ProviderKey).HasMaxLength(128);
// Maps to the AspNetUserLogins table
b.ToTable("AspNetUserLogins");
});
builder.Entity<TUserToken>(b =>
{
// Composite primary key consisting of the UserId, LoginProvider and Name
b.HasKey(t => new { t.UserId, t.LoginProvider, t.Name });
// Limit the size of the composite key columns due to common DB restrictions
b.Property(t => t.LoginProvider).HasMaxLength(maxKeyLength);
b.Property(t => t.Name).HasMaxLength(maxKeyLength);
// Maps to the AspNetUserTokens table
b.ToTable("AspNetUserTokens");
});
builder.Entity<TRole>(b =>
{
// Primary key
b.HasKey(r => r.Id);
// Index for "normalized" role name to allow efficient lookups
b.HasIndex(r => r.NormalizedName).HasName("RoleNameIndex").IsUnique();
// Maps to the AspNetRoles table
b.ToTable("AspNetRoles");
// A concurrency token for use with the optimistic concurrency checking
b.Property(r => r.ConcurrencyStamp).IsConcurrencyToken();
// Limit the size of columns to use efficient database types
b.Property(u => u.Name).HasMaxLength(256);
b.Property(u => u.NormalizedName).HasMaxLength(256);
// The relationships between Role and other entity types
// Note that these relationships are configured with no navigation properties
// Each Role can have many entries in the UserRole join table
b.HasMany<TUserRole>().WithOne().HasForeignKey(ur => ur.RoleId).IsRequired();
// Each Role can have many associated RoleClaims
b.HasMany<TRoleClaim>().WithOne().HasForeignKey(rc => rc.RoleId).IsRequired();
});
builder.Entity<TRoleClaim>(b =>
{
// Primary key
b.HasKey(rc => rc.Id);
// Maps to the AspNetRoleClaims table
b.ToTable("AspNetRoleClaims");
});
builder.Entity<TUserRole>(b =>
{
// Primary key
b.HasKey(r => new { r.UserId, r.RoleId });
// Maps to the AspNetUserRoles table
b.ToTable("AspNetUserRoles");
});
Model genel türleri
Identity yukarıda listelenen varlık türlerinin her biri için varsayılan Ortak Dil Çalışma Zamanı (CLR) türlerini tanımlar. Bu türlerin tümüne ön ek eklenir Identity:
IdentityUser
IdentityRole
IdentityUserClaim
IdentityUserToken
IdentityUserLogin
IdentityRoleClaim
IdentityUserRole
Bu türleri doğrudan kullanmak yerine, türler uygulamanın kendi türleri için temel sınıflar olarak kullanılabilir. tarafından Identity tanımlanan sınıflar, modeldeki DbContext
bir veya daha fazla varlık türü için farklı CLR türlerinin kullanılabilmesi için geneldir. Bu genel türler, birincil anahtar (PK) veri türünün değiştirilmesine de olanak sağlar User
.
rolleri için destek ile kullanırken Identity , bir IdentityDbContext sınıf kullanılmalıdır. Örneğin:
// Uses all the built-in Identity types
// Uses `string` as the key type
public class IdentityDbContext
: IdentityDbContext<IdentityUser, IdentityRole, string>
{
}
// Uses the built-in Identity types except with a custom User type
// Uses `string` as the key type
public class IdentityDbContext<TUser>
: IdentityDbContext<TUser, IdentityRole, string>
where TUser : IdentityUser
{
}
// Uses the built-in Identity types except with custom User and Role types
// The key type is defined by TKey
public class IdentityDbContext<TUser, TRole, TKey> : IdentityDbContext<
TUser, TRole, TKey, IdentityUserClaim<TKey>, IdentityUserRole<TKey>,
IdentityUserLogin<TKey>, IdentityRoleClaim<TKey>, IdentityUserToken<TKey>>
where TUser : IdentityUser<TKey>
where TRole : IdentityRole<TKey>
where TKey : IEquatable<TKey>
{
}
// No built-in Identity types are used; all are specified by generic arguments
// The key type is defined by TKey
public abstract class IdentityDbContext<
TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken>
: IdentityUserContext<TUser, TKey, TUserClaim, TUserLogin, TUserToken>
where TUser : IdentityUser<TKey>
where TRole : IdentityRole<TKey>
where TKey : IEquatable<TKey>
where TUserClaim : IdentityUserClaim<TKey>
where TUserRole : IdentityUserRole<TKey>
where TUserLogin : IdentityUserLogin<TKey>
where TRoleClaim : IdentityRoleClaim<TKey>
where TUserToken : IdentityUserToken<TKey>
Roller olmadan da (yalnızca talepler) kullanılabilir Identity ; bu durumda bir IdentityUserContext<TUser> sınıfın kullanılması gerekir:
// Uses the built-in non-role Identity types except with a custom User type
// Uses `string` as the key type
public class IdentityUserContext<TUser>
: IdentityUserContext<TUser, string>
where TUser : IdentityUser
{
}
// Uses the built-in non-role Identity types except with a custom User type
// The key type is defined by TKey
public class IdentityUserContext<TUser, TKey> : IdentityUserContext<
TUser, TKey, IdentityUserClaim<TKey>, IdentityUserLogin<TKey>,
IdentityUserToken<TKey>>
where TUser : IdentityUser<TKey>
where TKey : IEquatable<TKey>
{
}
// No built-in Identity types are used; all are specified by generic arguments, with no roles
// The key type is defined by TKey
public abstract class IdentityUserContext<
TUser, TKey, TUserClaim, TUserLogin, TUserToken> : DbContext
where TUser : IdentityUser<TKey>
where TKey : IEquatable<TKey>
where TUserClaim : IdentityUserClaim<TKey>
where TUserLogin : IdentityUserLogin<TKey>
where TUserToken : IdentityUserToken<TKey>
{
}
Modeli özelleştirme
Model özelleştirmesinin başlangıç noktası, uygun bağlam türünden türetmektir. Model genel türleri bölümüne bakın. Bu bağlam türü özel olarak çağrılır ApplicationDbContext
ve ASP.NET Core şablonları tarafından oluşturulur.
Bağlam, modeli iki şekilde yapılandırmak için kullanılır:
- Genel tür parametreleri için varlık ve anahtar türleri sağlama.
- Bu türlerin eşlemesini değiştirmek için geçersiz kılma
OnModelCreating
.
geçersiz kılma OnModelCreating
base.OnModelCreating
sırasında önce çağrılmalıdır; geçersiz kılma yapılandırması bir sonraki çağrılmalıdır. EF Core genellikle yapılandırma için son bir kazanan ilkesine sahiptir. Örneğin, bir varlık türünün yöntemi önce bir tablo adıyla, sonra yeniden farklı bir tablo adıyla çağrılırsa ToTable
, ikinci çağrıdaki tablo adı kullanılır.
NOT: 'den türetilmezse IdentityDbContext
AddEntityFrameworkStores
DbContext
, , TUserLogin
ve TUserToken
için TUserClaim
doğru POCO türlerini çıkaramayabilir. AddEntityFrameworkStores
Doğru POCO türlerini çıkarmazsa, geçici çözüm olarak ve UserStore<...>>
aracılığıyla services.AddScoped<IUser/RoleStore<TUser>
doğru türleri doğrudan ekleyin.
Özel kullanıcı verileri
Özel kullanıcı verileri , öğesinden IdentityUser
devralınarak desteklenir. Bu türü ApplicationUser
adlandırmak özeldir:
public class ApplicationUser : IdentityUser
{
public string CustomTag { get; set; }
}
Bağlam için ApplicationUser
genel bağımsız değişken olarak türünü kullanın:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
sınıfında geçersiz kılmaya OnModelCreating
ApplicationDbContext
gerek yoktur. EF Core özelliği kurala CustomTag
göre eşler. Ancak veritabanının yeni CustomTag
bir sütun oluşturacak şekilde güncelleştirilmesi gerekir. Sütunu oluşturmak için bir geçiş ekleyin ve veritabanını ve EF Core Geçişler'deIdentity açıklandığı gibi güncelleştirin.
güncelleştirin Pages/Shared/_LoginPartial.cshtml
ve şununla ApplicationUser
değiştirinIdentityUser
:
@using Microsoft.AspNetCore.Identity
@using WebApp1.Areas.Identity.Data
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager
veya Startup.ConfigureServices
öğesini güncelleştirin Areas/Identity/IdentityHostingStartup.cs
ve ile ApplicationUser
değiştirinIdentityUser
.
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
Çağrılması AddDefaultIdentity aşağıdaki koda eşdeğerdir:
services.AddAuthentication(o =>
{
o.DefaultScheme = IdentityConstants.ApplicationScheme;
o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies(o => { });
services.AddIdentityCore<TUser>(o =>
{
o.Stores.MaxLengthForKeys = 128;
o.SignIn.RequireConfirmedAccount = true;
})
.AddDefaultUI()
.AddDefaultTokenProviders();
Identity sınıf kitaplığı olarak Razor sağlanır. Daha fazla bilgi için bkz. ASP.NET Core projelerinde yapı iskelesiIdentity. Sonuç olarak, yukarıdaki kod için AddDefaultUIbir çağrı gerektirir. Yapı iskelesi Identity projeye dosya eklemek Identity için kullanıldıysa çağrısı kaldırın AddDefaultUI
. Daha fazla bilgi için bkz.
Birincil anahtar türünü değiştirme
Veritabanı oluşturulduktan sonra PK sütununun veri türünde yapılan bir değişiklik birçok veritabanı sisteminde sorunludur. PK'nin değiştirilmesi genellikle tabloyu bırakarak yeniden oluşturmayı içerir. Bu nedenle, veritabanı oluşturulduğunda ilk geçişte anahtar türleri belirtilmelidir.
PK türünü değiştirmek için şu adımları izleyin:
Veritabanı PK değişikliğinden önce oluşturulduysa silmek için (PMC) veya
dotnet ef database drop
(.NET CLI) komutunu çalıştırınDrop-Database
.Veritabanının silinmesini onayladıktan sonra , (PMC) veya
dotnet ef migrations remove
(.NET CLI) ileRemove-Migration
ilk geçişi kaldırın.sınıfından
ApplicationDbContext
türetmek IdentityDbContext<TUser,TRole,TKey>için sınıfını güncelleştirin. içinTKey
yeni anahtar türünü belirtin. Örneğin, birGuid
anahtar türü kullanmak için:public class ApplicationDbContext : IdentityDbContext<IdentityUser<Guid>, IdentityRole<Guid>, Guid> { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } }
Önceki kodda, genel sınıflar IdentityUser<TKey> ve IdentityRole<TKey> yeni anahtar türünü kullanmak için belirtilmelidir.
Startup.ConfigureServices
genel kullanıcıyı kullanacak şekilde güncelleştirilmelidir:services.AddDefaultIdentity<IdentityUser<Guid>>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<ApplicationDbContext>();
Özel
ApplicationUser
bir sınıf kullanılıyorsa, sınıfından devralınacakIdentityUser
şekilde sınıfını güncelleştirin. Örneğin:using System; using Microsoft.AspNetCore.Identity; public class ApplicationUser : IdentityUser<Guid> { public string CustomTag { get; set; } }
Özel
ApplicationUser
sınıfa başvurmak için güncelleştirinApplicationDbContext
:public class ApplicationDbContext : IdentityDbContext<ApplicationUser, IdentityRole<Guid>, Guid> { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } }
hizmetini
Startup.ConfigureServices
içinde eklerken özel veritabanı bağlam sınıfını Identity kaydedin:services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<ApplicationDbContext>();
Birincil anahtarın veri türü, nesnesi çözümlenerek DbContext çıkarılır.
Identity sınıf kitaplığı olarak Razor sağlanır. Daha fazla bilgi için bkz. ASP.NET Core projelerinde yapı iskelesiIdentity. Sonuç olarak, yukarıdaki kod için AddDefaultUIbir çağrı gerektirir. Yapı iskelesi Identity projeye dosya eklemek Identity için kullanıldıysa çağrısı kaldırın
AddDefaultUI
.Özel
ApplicationRole
bir sınıf kullanılıyorsa, sınıfından devralınacakIdentityRole<TKey>
şekilde sınıfını güncelleştirin. Örneğin:using System; using Microsoft.AspNetCore.Identity; public class ApplicationRole : IdentityRole<Guid> { public string Description { get; set; } }
Özel
ApplicationRole
sınıfa başvurmak için güncelleştirinApplicationDbContext
. Örneğin, aşağıdaki sınıf bir özel ve özelApplicationUser
ApplicationRole
öğesine başvurur:using System; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, Guid> { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } }
hizmetini
Startup.ConfigureServices
içinde eklerken özel veritabanı bağlam sınıfını Identity kaydedin:public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"))); services.AddIdentity<ApplicationUser, ApplicationRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultUI() .AddDefaultTokenProviders(); services.AddMvc() .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
Birincil anahtarın veri türü, nesnesi çözümlenerek DbContext çıkarılır.
Identity sınıf kitaplığı olarak Razor sağlanır. Daha fazla bilgi için bkz. ASP.NET Core projelerinde yapı iskelesiIdentity. Sonuç olarak, yukarıdaki kod için AddDefaultUIbir çağrı gerektirir. Yapı iskelesi Identity projeye dosya eklemek Identity için kullanıldıysa çağrısı kaldırın
AddDefaultUI
.
Gezinti özellikleri ekleme
İlişkiler için model yapılandırmasını değiştirmek, diğer değişiklikleri yapmaktan daha zor olabilir. Yeni, ek ilişkiler oluşturmak yerine mevcut ilişkileri değiştirmek için dikkatli olunmalıdır. Özellikle, değiştirilen ilişkinin var olan ilişkiyle aynı yabancı anahtar (FK) özelliğini belirtmesi gerekir. Örneğin, ve UserClaims
arasındaki Users
ilişki varsayılan olarak aşağıdaki gibi belirtilir:
builder.Entity<TUser>(b =>
{
// Each User can have many UserClaims
b.HasMany<TUserClaim>()
.WithOne()
.HasForeignKey(uc => uc.UserId)
.IsRequired();
});
Bu ilişkinin FK değeri özellik olarak UserClaim.UserId
belirtilir. HasMany
ve WithOne
gezinti özellikleri olmadan ilişki oluşturmak için bağımsız değişkenler olmadan çağrılır.
kullanıcıdan ilişkilendirilenlere UserClaims
başvurulmasına izin veren bir gezinti özelliği ApplicationUser
ekleyin:
public class ApplicationUser : IdentityUser
{
public virtual ICollection<IdentityUserClaim<string>> Claims { get; set; }
}
TKey
içinIdentityUserClaim<TKey>
, kullanıcıların PK'sı için belirtilen türdür. Bu durumda, TKey
string
varsayılan değerlerin kullanılmasıdır. Varlık türü için UserClaim
PK türü değildir.
Gezinti özelliği var olduğuna göre, içinde OnModelCreating
yapılandırılması gerekir:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationUser>(b =>
{
// Each User can have many UserClaims
b.HasMany(e => e.Claims)
.WithOne()
.HasForeignKey(uc => uc.UserId)
.IsRequired();
});
}
}
İlişkinin daha önce olduğu gibi, yalnızca çağrısında belirtilen bir gezinti özelliğiyle yapılandırıldığına HasMany
dikkat edin.
Gezinti özellikleri veritabanında değil yalnızca EF modelinde bulunur. İlişkinin FK'sı değişmediğinden, bu tür bir model değişikliği veritabanının güncelleştirilmesi gerektirmez. Bu, değişiklik yaptıktan sonra geçiş eklenerek denetlenebilir. Up
ve Down
yöntemleri boş.
Tüm Kullanıcı gezinti özelliklerini ekleme
Aşağıdaki örnekte, yukarıdaki bölüm kılavuz olarak kullanıldığında, Kullanıcı üzerindeki tüm ilişkiler için tek yönlü gezinti özellikleri yapılandırılır:
public class ApplicationUser : IdentityUser
{
public virtual ICollection<IdentityUserClaim<string>> Claims { get; set; }
public virtual ICollection<IdentityUserLogin<string>> Logins { get; set; }
public virtual ICollection<IdentityUserToken<string>> Tokens { get; set; }
public virtual ICollection<IdentityUserRole<string>> UserRoles { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationUser>(b =>
{
// Each User can have many UserClaims
b.HasMany(e => e.Claims)
.WithOne()
.HasForeignKey(uc => uc.UserId)
.IsRequired();
// Each User can have many UserLogins
b.HasMany(e => e.Logins)
.WithOne()
.HasForeignKey(ul => ul.UserId)
.IsRequired();
// Each User can have many UserTokens
b.HasMany(e => e.Tokens)
.WithOne()
.HasForeignKey(ut => ut.UserId)
.IsRequired();
// Each User can have many entries in the UserRole join table
b.HasMany(e => e.UserRoles)
.WithOne()
.HasForeignKey(ur => ur.UserId)
.IsRequired();
});
}
}
Kullanıcı ve Rol gezinti özellikleri ekleme
Aşağıdaki örnek, yukarıdaki bölümü kılavuz olarak kullanarak Kullanıcı ve Rol'de tüm ilişkiler için gezinti özelliklerini yapılandırmıştır:
public class ApplicationUser : IdentityUser
{
public virtual ICollection<IdentityUserClaim<string>> Claims { get; set; }
public virtual ICollection<IdentityUserLogin<string>> Logins { get; set; }
public virtual ICollection<IdentityUserToken<string>> Tokens { get; set; }
public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}
public class ApplicationRole : IdentityRole
{
public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}
public class ApplicationUserRole : IdentityUserRole<string>
{
public virtual ApplicationUser User { get; set; }
public virtual ApplicationRole Role { get; set; }
}
public class ApplicationDbContext
: IdentityDbContext<
ApplicationUser, ApplicationRole, string,
IdentityUserClaim<string>, ApplicationUserRole, IdentityUserLogin<string>,
IdentityRoleClaim<string>, IdentityUserToken<string>>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationUser>(b =>
{
// Each User can have many UserClaims
b.HasMany(e => e.Claims)
.WithOne()
.HasForeignKey(uc => uc.UserId)
.IsRequired();
// Each User can have many UserLogins
b.HasMany(e => e.Logins)
.WithOne()
.HasForeignKey(ul => ul.UserId)
.IsRequired();
// Each User can have many UserTokens
b.HasMany(e => e.Tokens)
.WithOne()
.HasForeignKey(ut => ut.UserId)
.IsRequired();
// Each User can have many entries in the UserRole join table
b.HasMany(e => e.UserRoles)
.WithOne(e => e.User)
.HasForeignKey(ur => ur.UserId)
.IsRequired();
});
modelBuilder.Entity<ApplicationRole>(b =>
{
// Each Role can have many entries in the UserRole join table
b.HasMany(e => e.UserRoles)
.WithOne(e => e.Role)
.HasForeignKey(ur => ur.RoleId)
.IsRequired();
});
}
}
Notlar:
- Bu örnek, Kullanıcılardan Rollere
UserRole
çoka ilişkide gezinmek için gereken birleştirme varlığını da içerir. - Gezinti özelliklerinin türlerini, türlerin artık türler yerine
Identity{...}
kullanıldığını yansıtacakApplication{...}
şekilde değiştirmeyi unutmayın. - genel
ApplicationContext
tanımında kullanmayıApplication{...}
unutmayın.
Tüm gezinti özelliklerini ekleme
Aşağıdaki örnek, yukarıdaki bölümü kılavuz olarak kullanarak tüm varlık türlerindeki tüm ilişkiler için gezinti özelliklerini yapılandırmıştır:
public class ApplicationUser : IdentityUser
{
public virtual ICollection<ApplicationUserClaim> Claims { get; set; }
public virtual ICollection<ApplicationUserLogin> Logins { get; set; }
public virtual ICollection<ApplicationUserToken> Tokens { get; set; }
public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}
public class ApplicationRole : IdentityRole
{
public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
public virtual ICollection<ApplicationRoleClaim> RoleClaims { get; set; }
}
public class ApplicationUserRole : IdentityUserRole<string>
{
public virtual ApplicationUser User { get; set; }
public virtual ApplicationRole Role { get; set; }
}
public class ApplicationUserClaim : IdentityUserClaim<string>
{
public virtual ApplicationUser User { get; set; }
}
public class ApplicationUserLogin : IdentityUserLogin<string>
{
public virtual ApplicationUser User { get; set; }
}
public class ApplicationRoleClaim : IdentityRoleClaim<string>
{
public virtual ApplicationRole Role { get; set; }
}
public class ApplicationUserToken : IdentityUserToken<string>
{
public virtual ApplicationUser User { get; set; }
}
public class ApplicationDbContext
: IdentityDbContext<
ApplicationUser, ApplicationRole, string,
ApplicationUserClaim, ApplicationUserRole, ApplicationUserLogin,
ApplicationRoleClaim, ApplicationUserToken>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationUser>(b =>
{
// Each User can have many UserClaims
b.HasMany(e => e.Claims)
.WithOne(e => e.User)
.HasForeignKey(uc => uc.UserId)
.IsRequired();
// Each User can have many UserLogins
b.HasMany(e => e.Logins)
.WithOne(e => e.User)
.HasForeignKey(ul => ul.UserId)
.IsRequired();
// Each User can have many UserTokens
b.HasMany(e => e.Tokens)
.WithOne(e => e.User)
.HasForeignKey(ut => ut.UserId)
.IsRequired();
// Each User can have many entries in the UserRole join table
b.HasMany(e => e.UserRoles)
.WithOne(e => e.User)
.HasForeignKey(ur => ur.UserId)
.IsRequired();
});
modelBuilder.Entity<ApplicationRole>(b =>
{
// Each Role can have many entries in the UserRole join table
b.HasMany(e => e.UserRoles)
.WithOne(e => e.Role)
.HasForeignKey(ur => ur.RoleId)
.IsRequired();
// Each Role can have many associated RoleClaims
b.HasMany(e => e.RoleClaims)
.WithOne(e => e.Role)
.HasForeignKey(rc => rc.RoleId)
.IsRequired();
});
}
}
Bileşik anahtarları kullanma
Önceki bölümlerde modelde Identity kullanılan anahtar türünün değiştirilmesi gösterilmiştir. Identity Anahtar modelini bileşik anahtarları kullanacak şekilde değiştirmek desteklenmez veya önerilmez. ile Identity bileşik anahtar kullanmak, yönetici kodunun Identity modelle etkileşim kurma şeklini değiştirmeyi içerir. Bu özelleştirme, bu belgenin kapsamı dışındadır.
Tablo/sütun adlarını ve modellerini değiştirme
Tablo ve sütunların adlarını değiştirmek için öğesini çağırın base.OnModelCreating
. Ardından, varsayılanlardan herhangi birini geçersiz kılmak için yapılandırma ekleyin. Örneğin, tüm Identity tabloların adını değiştirmek için:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUser>(b =>
{
b.ToTable("MyUsers");
});
modelBuilder.Entity<IdentityUserClaim<string>>(b =>
{
b.ToTable("MyUserClaims");
});
modelBuilder.Entity<IdentityUserLogin<string>>(b =>
{
b.ToTable("MyUserLogins");
});
modelBuilder.Entity<IdentityUserToken<string>>(b =>
{
b.ToTable("MyUserTokens");
});
modelBuilder.Entity<IdentityRole>(b =>
{
b.ToTable("MyRoles");
});
modelBuilder.Entity<IdentityRoleClaim<string>>(b =>
{
b.ToTable("MyRoleClaims");
});
modelBuilder.Entity<IdentityUserRole<string>>(b =>
{
b.ToTable("MyUserRoles");
});
}
Bu örneklerde varsayılan Identity türler kullanılır. gibi ApplicationUser
bir uygulama türü kullanıyorsanız, varsayılan tür yerine bu türü yapılandırın.
Aşağıdaki örnek bazı sütun adlarını değiştirir:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUser>(b =>
{
b.Property(e => e.Email).HasColumnName("EMail");
});
modelBuilder.Entity<IdentityUserClaim<string>>(b =>
{
b.Property(e => e.ClaimType).HasColumnName("CType");
b.Property(e => e.ClaimValue).HasColumnName("CValue");
});
}
Bazı veritabanı sütunu türleri belirli modellerle yapılandırılabilir (örneğin, izin verilen uzunluk üst sınırı string
). Aşağıdaki örnek, modeldeki birkaç string
özellik için sütun maksimum uzunluklarını ayarlar:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUser>(b =>
{
b.Property(u => u.UserName).HasMaxLength(128);
b.Property(u => u.NormalizedUserName).HasMaxLength(128);
b.Property(u => u.Email).HasMaxLength(128);
b.Property(u => u.NormalizedEmail).HasMaxLength(128);
});
modelBuilder.Entity<IdentityUserToken<string>>(b =>
{
b.Property(t => t.LoginProvider).HasMaxLength(128);
b.Property(t => t.Name).HasMaxLength(128);
});
}
Farklı bir şemaya eşle
Şemalar, veritabanı sağlayıcıları arasında farklı davranabilir. SQL Server için varsayılan değer, dbo şemasındaki tüm tabloları oluşturmaktır. Tablolar farklı bir şemada oluşturulabilir. Örneğin:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.HasDefaultSchema("notdbo");
}
Geç yükleme
Bu bölümde, modeldeki yavaş yüklenen proxy'ler Identity için destek eklenmiştir. Yavaş yükleme, gezinti özelliklerinin önce yüklendiğinden emin olmadan kullanılmasına izin verdiğinden kullanışlıdır.
Varlık türleri, belgelerde açıklandığı EF Core gibi çeşitli yollarla gecikmeli yüklemeye uygun hale getirilebilir. Kolaylık olması için aşağıdakiler için gecikmeli yükleme proxy'leri kullanın:
- Microsoft.EntityFrameworkCore.Proxies paketinin yüklenmesi.
- içine AddDbContextyapılan UseLazyLoadingProxies bir çağrı.
- Gezinti özelliklerine sahip
public virtual
ortak varlık türleri.
Aşağıdaki örnekte içinde Startup.ConfigureServices
çağrı UseLazyLoadingProxies
gösterilmektedir:
services
.AddDbContext<ApplicationDbContext>(
b => b.UseSqlServer(connectionString)
.UseLazyLoadingProxies())
.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
Varlık türlerine gezinti özellikleri ekleme yönergeleri için önceki örneklere bakın.
Ek kaynaklar
ASP.NET Core