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:

  1. Kodda veri modeli tanımlama veya güncelleştirme.
  2. Bu modeli veritabanına uygulanabilecek değişikliklere çevirmek için bir Geçiş ekleyin.
  3. Geçiş işleminin amacınızı doğru şekilde temsil ettiğini denetleyin.
  4. Veritabanını modelle eşitlenecek şekilde güncelleştirmek için Geçişi uygulayın.
  5. 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 Core 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ü Tanım
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çok UserClaimsolabilir.
  • Her User birinde birçok UserLoginsolabilir.
  • Her User birinde birçok UserTokensolabilir.
  • Her Role birinde birçok ilişkili RoleClaimsolabilir.
  • Her User birinde birçok ilişkili Rolesolabilir ve her Role birinin birçok Usersile ilişkilendirilebilir. Bu, veritabanında birleştirme tablosu gerektiren çoka çok ilişkisidir. Birleştirme tablosu varlık tarafından UserRole 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'siniOnModelCreating 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. Örnek:

// 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 OnModelCreatingbase.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 IdentityDbContextAddEntityFrameworkStoresDbContext, , TUserLoginve TUserTokeniçin TUserClaimdoğ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 IdentityUserdevralınarak desteklenir. Bu türü ApplicationUseradlandı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 OnModelCreatingApplicationDbContext 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 ApplicationUserdeğ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 ApplicationUserdeğ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:

  1. Veritabanı PK değişikliğinden önce oluşturulduysa silmek için (PMC) veya dotnet ef database drop (.NET Core CLI) komutunu çalıştırın Drop-Database .

  2. Veritabanının silinmesini onayladıktan sonra ile (PMC) veya dotnet ef migrations remove (.NET Core CLI) ilk geçişi Remove-Migration kaldırın.

  3. sınıfından ApplicationDbContext türetmek IdentityDbContext<TUser,TRole,TKey>için sınıfını güncelleştirin. için TKeyyeni anahtar türünü belirtin. Örneğin, bir Guid 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>();
    
  4. Özel ApplicationUser bir sınıf kullanılıyorsa, sınıfından devralınacak IdentityUserşekilde sınıfını güncelleştirin. Örnek:

    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.ConfigureServicesiç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.

  5. Özel ApplicationRole bir sınıf kullanılıyorsa, sınıfından devralınacak IdentityRole<TKey>şekilde sınıfını güncelleştirin. Örnek:

    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 özel ApplicationUserApplicationRoleöğ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.ConfigureServicesiç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, TKeystring 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 OnModelCreatingyapı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 HasManydikkat 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ıtacak Application{...} ş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 ApplicationUserbir 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. Örnek:

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:

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