Asp.NET Core Identity – Kullanıcı ve Rol Modellerinde Custom Property Tanımlamak – IV

Merhaba,

Asp.NET Core Identity yazı dizimizin bu 4. içeriğinde “IdentityUser” sınıfından türeyen “AppUser” isimli kullanıcı modelimize custom property ekleyerek özel kolonlar oluşturmayı inceleyeceğiz ve bunun yanında “IdentityRole” sınıfından türeyen bir kullanıcı rollerini modellediğimiz sınıf tasarlayarak benzer mantıkta o model içerisinde custom propertyler ile nasıl özel kolonlar oluşturulduğunada ekstradan değinmiş olacağız. Ayriyetten önceki içeriklerimiz neticesinde gördüğümüz primary key (Id) yapılanmasının varsayılan olarak nvarchar olarak değil de istediğimiz bir tipte ayarlanmasının (int, string, long vs.) nasıl yapıldığını inceleyeceğiz. O halde buyrun başlayalım…

IdentityUser’dan Türeyen “AppUser” Sınıfına Custom Property Eklemek

Uygulamadaki kullanıcılarımızı modellediğimiz “IdentityUser” sınıfından türetilen “AppUser” sınıfını önceki makalelerde gerçekleştirdiğimiz gibi salt bir şekilde aşağıdaki gibi inşa edersek direkt olarak bir kullanıcıyı temsil eden genel geçer propertylerle veritabanına migrate edilecektir.

    public class AppUser : IdentityUser
    {
    }

Asp.NET Core Identity - Kullanıcı Modelinde Custom Property Tanımlamak - IV
Eğer ki, uygulamamızda kullanıcılarımıza dair daha fazla bilgi tutacaksak ilgili model içerisine aşağıdaki gibi custom propertyleri yerleştirebiliriz.

    public class AppUser : IdentityUser
    {
        public string Memleket { get; set; }
        public bool Cinsiyet { get; set; }
    }

Bu işlem migrate neticesinde oluşturulacak fiziksel tabloya aşağıdaki gibi yansıyacaktır;
Asp.NET Core Identity - Kullanıcı Modelinde Custom Property Tanımlamak - IV

Evet… Görüldüğü üzere kullanıcı tablolarında kendimize özel kolonlar tanımlayabilmek bu kadar basit.

Şimdi ise bir rol modeli oluşturmayı inceleyelim.

IdentityRole’den Türeyen “AppRole” Sınıfını Oluşturmak ve Uygulamaya Dahil Etmek

Bir rol modeli tanımlayabilmek için “Models” -> “Authentication” klasörü içerisine “AppRole” isminde sınıf oluşturunuz ve bu sınıfı aşağıdaki gibi IdentityRole sınıfından türetiniz.

    public class AppRole : IdentityRole
    {
        public DateTime OlusturulmaTarihi { get; set; }
    }

Artık bu rol modelinin uygulamada kullanılacağını belirtmemiz gerekmektedir. Bunun için DbContext sınıfımıza gelip aşağıdaki gibi çalışma gerçekleştiriyoruz;

    public class AppDbContext : IdentityDbContext<AppUser, AppRole, string>
    {
        public AppDbContext(DbContextOptions<AppDbContext> dbContext) : base(dbContext) { }
    }

Yukarıdaki kod bloğunu incelersek eğer, “IdentityDbContext” sınıfına generic olarak user modelinde “AppUser” sınıfının, role modelinde ise “AppRole” sınıfının kullanılacağını belirtmiş oluyoruz. 3. parametrede ise bu yapılanmanın primary key (Id) kolonlarının “string” tipte değerlerle tutulacağını ifade etmiş oluyoruz. Keza makalemizin ileriki satırlarında bu değeri hangi hususlara dayanarak değiştirebiliyoruz kritik yaparak ele alacağız.

Velhasıl bu işlemden sonra “Startup.cs” dosyasındaki “ConfigureServices” metodu içerisinde uygulamaya Identity servisini dahil ettiğimiz “AddIdentity” metodunda oluşturduğumuz “AppRole” sınıfını generic olarak belirtmemiz gerekmektedir.

        public void ConfigureServices(IServiceCollection services)
        {
            .
            .
            services.AddIdentity<AppUser, AppRole>().AddEntityFrameworkStores<AppDbContext>();
            .
            .
        }

Tüm bu işlemler neticesinde uygulamayı derleyip, tekrar migrationları oluşturduktan sonra update edersek eğer aşağıdaki gibi rol mekanizmasının uygulamaya dahil edildiğini görebileceksiniz…
Asp.NET Core Identity - Kullanıcı Modelinde Custom Property Tanımlamak - IV

Bu adımdan da sonra sıra veritabanındaki primary key (Id) kolonları üzerinde manuel tip değişikliğine gelmiştir.

Primary Key(Id) Kolonlarının Tipini Belirleme

Bu işlem için DbContext sınıfımızdaki base class olan “IdentityDbContext” sınıfının sonuncu generic parametresine istediğimiz tipi vermemiz yeterli olacaktır.
Asp.NET Core Identity - Kullanıcı Modelinde Custom Property Tanımlamak - IV
Tabi yeterli olacaktır ama gidişatınız bu şekildeyse yukarıdaki olası hatada kaçınılmaz olacaktır. Yapılanmada tüm sistemin tipini string dışında belirleyebilmek istiyorsanız “AppUser” ve “AppRole” sınıflarınında id yapılanmasının tipini generic olarak belirtmeniz gerekmektedir ve bu context sınıfındaki tip ile tutarlı olmalıdır.
Asp.NET Core Identity - Kullanıcı Modelinde Custom Property Tanımlamak - IV

“Hoca önceki örneğimizde bu tip string iken bir hata almıyorduk! Neden string dışında yapınca alıyoruz?” sorunuzu duyar gibiyim… Evet, almıyorduk. Çünkü varsayılan tüm yapılanma string olarak tasarlanmıştır. Aksi durumdaki tüm tipleri bu şekilde belirtmemiz gerekmektedir.

Nihai olarak bu noktada migrate edilen veritabanındaki tüm primary key kolonlar belirtilen tipte oluşturulmuş olacaktır.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Not : Örnek projeyi indirmek için buraya tıklayınız.

Bunlar da hoşunuza gidebilir...

13 Cevaplar

  1. Mehmet Fatih Gök dedi ki:

    Merhabalar Hocam,
    Öncelikle ders ve emeğiniz için çok teşekkürler ederim.Örnek olarak StokYeri diye bi entitymiz var ve bu entity’ye bir user değeri verilip(sorumlu kişi) AspNetUsers tablosuna foreignkey olarak atama istiyoruz. Tabloya direkt erişimimiz yok. AppUser sınıfı üzerinden foreignKey yapınca AppUser diye yeni bir tablo oluşturuyor.
    Sorum şu ki, Identity’yi sadece login işlemlerinde mi kullanalım.Diğer kullanıcı bilgilerine kolay erişmek için ayrı bir kullanıcı tablosu mu oluşturalım.

    public int Id { get; set; }
    public string StokYeriAdi { get; set; }
    public string UserId { get; set; }//SatisTemsilcisi
    public virtual AppUsers User { get; set; }
    public string SatisTemsilcisiAdi { get; set; }

    • Gençay dedi ki:

      Merhaba,

      AppUser sınıfına foreign key oluşturduğunuz taktirde ilgili tablo otomatik olarak AppUser entitysinin karşılığı olarak generate edilecek olan AspNetUsers tablosuyla ilişkilendirilmesi gerekmektedir. Muhtemelen gözden kaçan bir hata söz konusudur.

      Sorunuza cevap olarak hayır diyebiliriz. Tabi kullanıcının kompleks bilgilerini daha hiyerarşik tutmak ve bir düzen oluşturmak istiyorsanız ilişkisel olarak başka bir tabloda bunu gerçekleştirebilirsiniz lakin tüm bu verileri AppUser entitysi üzerinden ilgili tabloda tutmanında hiçbir sakıncası yoktur. Önerim, optimum seviyede bir kolon söz konusuysa AppUser nesnesi üzerinden generate edilecek olan AspNetUsers tablosunda ilgili verileri tutmanızdır.

      Sevgiler.

  2. Mahmut dedi ki:

    Hocam merhabalar, ASPNETUSER tablomuzdaki bazı kolonları kaldırmak istiyorum. Mümkün müdür acaba ?

    • Gençay dedi ki:

      Denemedim lakin şöyle bir fikir verebilirim. İstediğiniz kolonu override edip ardından [NotMapped] ile işaretleyerek deneyiniz. Neticeyi bizimle paylaşırsanız sevinirim.
      Kolay gelsin.

      • Gençay dedi ki:

        Dayanamayıp denedim 🙂
        Evet bu şekilde istediğiniz kolonları kaldırabilirsiniz.
        Örnek kod;

            public class AppUser : IdentityUser<int>
            {
                [NotMapped]
                public override string PhoneNumber { get => base.PhoneNumber; set => base.PhoneNumber = value; }
                [NotMapped]
                public override bool PhoneNumberConfirmed { get => base.PhoneNumberConfirmed; set => base.PhoneNumberConfirmed = value; }
            }
        

        Migrate ettiğimizde yukarıda belirtilen kolonlar kaldırılmış olacaktır.
        Sevgiler.

        • Mahmut dedi ki:

          Cevabı bulunca buraya tekrar bakmak aklıma gelmedi 🙂 Ben şu şekilde buldum:

          protected override void OnModelCreating(ModelBuilder modelBuilder)
                  {
                      base.OnModelCreating(modelBuilder);
          
                      modelBuilder.Entity<IdentityUser>()
                          .Ignore(p => p.PhoneNumber)
                          .Ignore(p => p.PhoneNumberConfirmed)
                          .Ignore(p => p.EmailConfirmed)
                          .Ignore(p => p.TwoFactorEnabled);
                  }
          

          Zaten aynı işlemi yapıyor ama sizin yönteminiz daha okunaklı ve anlaşılır geldi. Sizinde yorumunuzu alırsam daha anlaşılır olabilir benim açımdan. Bir küçük hatırlatma farkı şöyle var ben context içerisinde yazdım. Migrate yaptığımda farklı bir tablo ismiyle oluşturmuştu. Siz IdentityUser içerisinde yapmışsınız bu işlemi. Sizin yönteminiz aynı şekilde mi sonuçlandı acaba.

          • Gençay dedi ki:

            Nasıl yani? Migrate neticesinde tabloyu farklı isimde mi oluşturdu? Öyleyse eğer oluşturulan ismi yazar mısınız?

            Bu arada geri dönüşünüz ve farklı bir çözüm yolu kazandırdığınız için çok teşekkür ederim.

          • Mahmut dedi ki:

            Rica ederim bizde kendi çapımızda bir şeyler yapmaya çalışıyoruz.

            Evet migrate sonrasında tablo ismimiz 5. satırdaki AppUser ismiyle oluşturuldu. Ama bi düzeltme geçeyim ben yanlış kodu atmışım. AppUser yerine IdentityUser olacak orası ve tablo ismini de aşağıdaki şekilde “ToTable” şeklinde veriyoruz. Eğer tablo ismini vermezseniz tablomuzun ismi varsayılan “IdentityUser” olarak gelecektir.

            protected override void OnModelCreating(ModelBuilder modelBuilder)
                    {
                        base.OnModelCreating(modelBuilder);
            
                        modelBuilder.Entity<IdentityUser>().ToTable("DenemeTablo")
                            .Ignore(p => p.PhoneNumber)
                            .Ignore(p => p.PhoneNumberConfirmed)
                            .Ignore(p => p.EmailConfirmed)
                            .Ignore(p => p.TwoFactorEnabled);
                    }
            

            Ama aklımdaki soru şu acaba AspNetUser tablosunu silsem bir sıkıntı olur mu? Çünkü 2 tablo aynı anda olması bize bir avantaj yada dezavantaj sağlar mı? Yada sizin yaptığınız yolu kullanıp varolan tablo üzerinden mi işlem yapmalıyım ? Yani burada nasıl bir yol izlemeliyim onu düşünüyorum.

          • Gençay dedi ki:

            .ToTable fonksiyonunu kullanmadan veritabanını komple silip tekrar migrate eder misiniz?

  3. Umut dedi ki:

    Konfigürasyonu tamamladıktan (Update-database) yaptıktan sonra DB tarafında User ve Role’ın ID Kısımlarını int’e elle başarılı bir şekilde çeviriyorum. Fakat Modeller üzerinde…. yaptığım zaman hata alıyorum.

  4. raddo dedi ki:

    selam. anlatim isime baya yaradi. tesekkurler.

  1. 11 Ağustos 2019

    […] Asp.NET Core Identity – Kullanıcı ve Rol Modellerinde Custom Property Tanımlamak – IV […]

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

*