SAP Sisteme Kayıtlı Personel Fotoğrafını Dışarı Alma

SAP sisteminde kayıtlı personel listesinde kayıtlı fotoğrafı dışarı aktarmak için aşağıdaki yol izlenebilir.

  1. OAAD transection kodu ile “ArchievedLink. Administration of Stored Documents” ekranı açılır.

     

ArchievedLink. Administration of Stored Documents

  • “Technical Search” butonu tıklanır ve ekranda, Business object alanına “PREL“, Document type alanına da “HRICOLFOTO” değerleri yazılır ve rapor çalıştırılır.
  • Açılan ekranda Personel numarasına ilgili personelin numarası yazılarak OK tıklanır.
  • Son olarak ekrana gelen grid listte satır çift tıklandığında ilgili kişinin resmi ekrana gelecektir.



  • DHCP Sunucusundan IP Silme

    IP bloklarının verebildiği IP adres sayılarının yetersiz olduğu durumda bazı IP adreslerinin DHCP’den silinmesi gerekmektedir. Adresleri tek tek silinebileceği gibi bir powershell scripti ile toplu da silinebilir. Aşağıda yer alan powershell scriprti kullanılarak belli şartları şağlayan IP adreslerini kolaylıkla silebiliriz. Script active directory kullanıcısnın yetkisye sahip olması durumunda kendi bilgisayarında da çalıştırabilir.

    Aşağıdaki örnek scripte isminde android, galaxy veya phone geçen ve rezerve olmayan IP adresleri siliniyor. 




    ST_USER_MAX_WSIZE Hatası

    ST_USER_MAX_WSIZE Hatası

    SAP GUI’de oluşan ST_USER_MAX_WSIZE hatası aşağıdaki ekran görüntüsünde görüldüğü şekildeki başlangıç parametresini değiştirerek çözülebilir.

    SAP Başlangıç Ayarları

    Parametre
    listesine /SUPPORTBIT_OFF=MAX_WSIZE eklenecek (” işareti olmadan)




    SQL Server Birden Fazla Tabloyu Beraber Sorgulama

    İlişkisel veri tabanı sistemlerinin (RDMS) hedeflerinden biri de veri tekrarını azaltmak ve performansı üst düzeyde tutmaktır. Bu sebeple tekrar eden veriler tablolara ayrılarak ilgili yerlere verilerin refensı verilir. Örneğin bir sipariş tablosunda veriler temel olarak aşağıdaki iki şekilde tutulabilir.

    • Her sipariş satırına ürünün bilgileri ve müşteri bilgilerini girmek
    • Müşteri bilgilerini ve ürün bilgilerini kendilerine has tablolarda tutup sipariş tablosuna sadece ilgili müşteri ve ürünün referans kolonlarını vermek.

    İlk seçenekte oluşacak örnek bir sipariş tablosu aşağıdaki gibi olur.

    Sipariş No Müşteri Adı Müşteri Soyadı Müşteri Tel Müşteri Adres Ürün Adı Sipariş Tarihi Sipariş Miktarı
    1 Tolga Yalçın 5539152030 İpragaz Mah. Veli Çakmak Cad. No:72 Bebek Arabası 21.10.2018 1
    2 Çetin Songur 5475245555 Mevalana Mah. İkbal Cad. No:32 Tabak 22.12.2018 1
    3 Tolga Yalçın 5539152030 İpragaz Mah. Veli Çakmak Cad. No:72 Tava 25.12.2018 1
    4 Tolga Yalçın 5539152030 İpragaz Mah. Veli Çakmak Cad. No:72 Çanta 30.12.2018 2
    5 Çetin Songur 5475245555 Mevalana Mah. İkbal Cad. No:32 Şemsiye 02.01.2019 3
    6 Tolga Yalçın 5539152030 İpragaz Mah. Veli Çakmak Cad. No:72 Kitap 05.01.2019 1

    Tabloda da görülebileceği gibi birinci seçenekte müşteri bilgisi sürekli bir tekrarda dönüyor. Bunun yerine ikinci seçenekte belirtildiği gibi müşteri bilgileri ayrı tabloda tutulursa yapı aşağıdaki gibi olur.

    No Adı Soyadı Telefon Adres
    1 Tolga Yalçın 5539152030 İpragaz Mah.
    Veli Çakmak Cad. No:72
    2 Çetin Songur 5475245555 Mevalana Mah. İkbal Cad. No:32

    Müşteri No Ürün Adı Tarih Miktar
    1 Bebek Arabası 21.10.20.18 1
    2 Tabak 22.12.2018 1
    1 Tava 25.12.2018 1
    1 Çanta 30.12.2018 2
    2 Şemsiye 02.01.2019 3
    1 Kitap 05.01.2019 1

    Görüldüğü üzere ilgili kayıtlar kendi tablolarında tutulup gerekli yerlere referans numaraları verilirse sipariş tablosunda veri tekrarı engellenmiş olur. Bu şekilde olduğunda müşteri bilgilerinde oluşacak bir değişiklik için bütün sipariş tablosunu dolaşmak yerine sadece müşteri tablosundan kaydı değiştirmek yeterli olacaktır. Referans konusunu Tablo Seviyesinde Veri Bütünlüğü isimli yazımızda bulabilirsiniz.

    Veriler tek tabloda iken bir SELECT * FROM ile alınabiliyor iken birden fazla tabloda tutulduğunda JOIN komutlarından faydalanmak gerekmektedir. JOIN komutları birden fazla tablo üzerinde sorgulama yaparak istenen sonuç kümesini sunar.

    JOIN komutları üç başlıkta toplanır. Bunlar;

    • INNER JOIN
    • OUTER JOIN
      • LEFT OUTER JOIN
      • RIGHT OUTER JOIN
      • FULL OUTER JOIN
    • CROSS JOIN

    JOIN TEMEL YAPISI

    Join işleminin temel yapısı aşağıdaki gibidir:

    SELECT kolon1, kolon2, kolon3...
    FROM Tablo1 [JOIN TÜRÜ] Tablo2 ON [JOIN şartı]

    INNER JOIN

    INNER JOIN sadece iki tabloda da eşleşen kayıtlar olması durumunda kaydı getirir. Örneğin müşteri ve sipariş tabloları INNER JOIN ile sorgulandığında siparişi olmayan müşteri, sipariş tablosunda eşleşen kaydı olmadığından sonuç ekranına gelmeyecektir. Örnek bir INNER JOIN sorgusu ve sonuç kümesi:

    SELECT m.Ad, m.Soyad, m.Telefon, m.Adres, s.UrunAd, s.Adet, s.Tarih
    FROM Musteriler m INNER JOIN Siparisler s ON m.Id = s.MusteriId

    INNER JOIN

    OUTER JOIN

    LEFT OUTER JOIN

    LEFT OUTER JOIN, join kelimesinin solunda kalan tabloyu referans alarak bütün kayıtları getiri. Join kelimesinin sağında kalan tabloda eşleşen kayıt yok ise ilgili kolona NULL değer döner.

    SELECT m.Ad, m.Soyad, m.Telefon, m.Adres, s.UrunAd, s.Adet, s.Tarih
    FROM Musteriler m LEFT JOIN Siparisler s ON m.Id = s.MusteriId

    LEFT JOIN

    Göründüğü gibi son satırda ilgili müşteriye ait sipariş olmadığından değerler NULL olarak dönüyor.

    RIGHT OUTER JOIN

    RIGHT OUTER JOIN, join kelimesinin sağında kalan tabloyu referans alarak bütün kayıtları getiri. Join kelimesinin solunda kalan tabloda eşleşen kayıt yok ise ilgili kolona NULL değer döner.

    SELECT m.Ad, m.Soyad, m.Telefon, m.Adres, s.UrunAd, s.Adet, s.Tarih
    FROM Musteriler m right JOIN Siparisler s ON m.Id = s.MusteriId

    RIGHT JOIN

    FULL OUTER JOIN

    FULL OUTER JOIN, her iki tablodan da bütün kayıtları getirir, eşleşmeyen kayıtların karşılıklarını NULL değer olarak döner.

    SELECT m.Ad, m.Soyad, m.Telefon, m.Adres, s.UrunAd, s.Adet, s.Tarih
    FROM Musteriler m FULL JOIN Siparisler s ON m.Id = s.MusteriId

    FULL JOIN

    CROSS JOIN

    CROSS JOIN, matematikteki kartezyen çarpımı gibi çalışır ve sol tabloya karşılık sağdaki bütün kayıtları getirir. Diğer join türlerinden farklı olarak ON şartı kullanılmaz. Örneğin sol tabloda üç, sağ tabloda 8 kayıt var ise sonuç kümesinde 3 * 8 = 24 kayıt döner.

    SELECT m.Ad, m.Soyad, m.Telefon, m.Adres, s.UrunAd, s.Adet, s.Tarih
    FROM Musteriler m cross JOIN Siparisler s 

    CROSS JOIN




    T-SQL Kodları ile SQL Server Şema Yapısını İnceleme

    Proje geliştirme aşamalarında olmasa da SQL Server yönetim işlemlerinde gerek server gerek veri tabanı ve tablolar düzeyinde sistemde yer alan nesnelerin listesi ve özelliklerini sorgulama ihtiyacı doğabilmektedir.

    SQL Server da çalışması sırasında üzerinde barındırdığı nesneleri ve bu nesnelere ait özellikle üzerinde ilgili tablolarda bulundurmaktadır. Bu tablolar üzerinde uygun T-SQL komutları çalıştırılarak bu bilgilere ulaşılabilir.

    Veri Tabanı Listesini Alma

    master veri tabanı üzerinde aşağıdaki kod çalıştırılarak sistemde yer alan veri tabanı bilgileri elde edilebilir. select * ile sorgu çalıştırılarak daha fazla bilgi elde edilebilir.

    select name, database_id, create_date, compatibility_level, collation_name from sys.databases

    Veri Tabanı İçerisinde Yer Alan Tablo Listesini Alma

    Tablo listesi alınacak veri tabanı üzerinde aşağıdaki iki sorgudan biri çalıştırılarak tablo listesi alınabilir.

    select * from sys.tables
    select * from INFORMATION_SCHEMA.TABLES

    Ekran görüntüsünde yer alan sonuç kümelerinde üstte sys.tables tablosudan, altta da INFRMATION_SCHEMA.TABLES görünümünden alınan sonuçlar görünmektedir.

    Tablo İçerisinde Yer Alan Kolon Listesini Alma

    Tablo içerisinde yer alan kolonlar aşağıdaki iki şekilde de alınabilir.

    • sys.all_columns tablosu üzerinden almak için sys.tables sorgusunda bulunan ilgili tabloya ait object_id değerine göre filtreleme yapılması gerekmektedir. Filtreleme yapılmazsa bütün veri tabanını içerinde yer alan bütün kolonları döndürür.
    • INFORMATION_SCHEMA.COLUMNS görüntüsü üzerinden alabilmek için TABLE_NAME ve TABLE_SCHEMA değerlerine göre sonucun filtrelenmesi gerekmektedir. Filtreleme yapılmazsa bütün veri tabanını içerinde yer alan bütün kolonları döndürür.

    Aşağıdaki sorgularda tablo sonuç ekranında da görünen tblSiparisDetay tablosu için sorgulama yapılmaktadır.

    select * from sys.all_columns where object_id = 133575514
    select * from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'tblSiparisDetay' AND TABLE_SCHEMA = 'DBO'

    Tablo Üzerinde Yer Alan Anahtar Alan ve Yabancıl Anahtarları Listeleme

    Anahtar alanları tablo üzerinde veri bütünlüğünü sağlamada en önemli unsurlar olarak karşımıza çıkmaktalar. Aşağıdaki sistem tabloları ve görüntülerinden anahtar alanlar elde edilebilir.

    • sys.key_constraints : Tablo üzerinde yer alan anahtar alanları listeler. Filtreleme olarak ilgili tablonun object_id değerini bu tablonun parent_object_id alanına filtre şartı olarak verilir.
    • sys.foreign_keys: Tablo üzerinde tanımlı yabancıl anahtarları listeler. Filtreleme olarak ilgili tablonun object_id değerini bu tablonun parent_object_id alanına filtre şartı olarak verilir.
    • INFORMATION_SCHEMA.TABLE_CONSTRAINTS: Tablo üzerinde yer alan anahtar alanları ve yabancıl anahtarları beraber listeler. Filtreleme işlemi için ilgili tablo ve şema isimlerini TABLE_SCHEMA ve TABLE_NAME alanlarına filtre şartı olarak verilir.

    select * from sys.key_constraints where parent_object_id = 133575514
    select * from sys.foreign_keys where parent_object_id = 133575514
    select * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where TABLE_SCHEMA = 'dbo' and TABLE_NAME = 'tblSiparisDetay'

    Tablo İçerisinde Kolonlar Üzerinde Yer Alan Zorlayıcı Şartların Listelenmesi

    Zorlayıcı şartlar kolon seviyesinde veri bütünlüğünü sağlayan yapılardır. Aşağıdaki kod yardımı ile tablo içerisinde yer alan zorlayıcı şartlar listelenebilir.

    select t.name tablo, ac.name kolon, dc.*
    from sys.all_columns ac
    inner join
    sys.tables t
    on ac.object_id = t.object_id
    inner join
    sys.schemas s on t.schema_id = s.schema_id
    inner join
    sys.default_constraints dc on ac.default_object_id = dc.object_id
    where t.object_id = 85575343

    Tablo Üzerinde Yer Alan Triggerların Listelenmesi

    Trigger yapıları tablo içerinde oluşan hareketlere bağlı olarak otomatik tetiklenen ve yapılan harekete bağlı olarak ilgili işlemleri otomatik yapan yapılardır. Aşağıdaki kod yardımı ile tablo üzerinde tanımlı triggerlar listelenebilir. sp_helptext stored procedürüne de ilgili trigegr adı verilerek kodları elde edilebilir.

    select * from sys.triggers t
    join sys.trigger_events te on t.object_id = te.object_id
    where t.parent_id = 85575343
    
    exec sp_helptext 'bakmadanSiparisSilinmez'

    Tablo Üzerine Tanımı Indexlerin Listelenmesi

    Indexler tablo üzerinde veri bütünlüğü ve performans sağlayan yapılardandır. Aşağıdaki kod yardımı ile tablo üzerinde tanımlanan indexler listelenebilir. Filtreleme şartı olarak ilgili tablonun object_id değeri verilir.

    select * from sys.indexes i
    join sys.index_columns ic on i.index_id = ic.index_id and i.object_id = ic.object_id
    join sys.all_columns ac on ic.column_id = ac.column_id and ic.object_id = ac.object_id
    where i.object_id = 85575343

    Temel nesne sorgularını bu şekilde gözden geçirdikten sonra yapısı tablo ile aynı olan VIEW sorguları da tablo sorguları ile aynı şekilde yapılabilmektedir. Fark olarak view listesi almak için sys.views tablosunda sorgular çalıştırılır.

    Veri tabanı yönetiminde her ne kadar küçük ayrıntı olarak görünse de yönetici ihtiyaç duyduğu bilgileri bu şekilde alabildiği sürece sistemine max düzeyde hâkim olabilmektedir.




    Sistem Yöneticileri İçin C# Kodları

    Bilgisayar biliminin yaygın alanlarından ikisi sistem yönetimi ve yazılım alanlarıdır. Her ne kadar bu iki alanda çalışan arkadaşlar bir birine karışmamaya çalışsa da tecrübelerimiz bize farklı şeyler söylüyor. Tecrübelerimiz, her sistem yöneticisi arkadaşın az da olsa yazılım, her yazılımcı arkadaşın da az da olsa sistem yönetimi konusunda tecrübe edinmesi gerektiğini söylüyor. Bu yazımızda sistem yönetimi için kullanılan bazı kodları paylaşıyor olacağız.

    Active Directory Kullanıcı ve Grup İşlemleri

    AD işlemleri için .Net Framework 4.5 ile gelen System.DirectoryServices.AccountManagement isim uzayında (Namespace) yer alan sınıfları kullanacağız. İlgili paketi Nuget’ten projemize ekledikten sonra işlemlere başlayabiliriz. Peket linki: https://www.nuget.org/packages/System.DirectoryServices.AccountManagement/

    Active Directory işlemlerinin tamamında sunucu ile bağlantıyı sağlayan PrincipalContext sınıfından nesne türetilmelidir. PrincipalContext sınıfının yedi farklı oluşturucu metodu olsa da en sık kullanılan üç metodu şunlardır;

    • PrincipalContext(ContextType): Sadece bağlanacak sunucun türünün alındığı oluşturucu metottur. ContextType enum değerinin alabileceği değerler:
      * ApplicationDirectory: Uygulama dizin sunucusu
      * Domain: Domain controllerdan verileri okumak için okunur.
      * Machine: Local makine SAM veri tabanına bağlantıda kullanılır.
    • PrincipalContext(ContextType, String): İlkinin yanında ikinci parametre olarak bağlanacak domain controller adını alır. cozumpark.local gibi…
    • PrincipalContext(ContextType, String, String, String): İlk iki metodun parametrelerinin yanında üçüncü parametre olarak bağlantıda kullanılacak kullanıcı adı ve dördüncü parametre olarak da girilen kullanıcı adının şifresini alır.

    AD Kullanıcılarının Sistemden Alınması

    AD kullanıcılarının sistemden alınabilmesi için oluşturulan PrincipalContext nesnesini parametre alan bir UserPrincipal nesnesi oluşturulur. Daha sonra bu nesne üzerinden istenen filtre değerleri girilir. Örneğin aşağıdaki kodda sadece aktif kullanıcıları istediğimizden “userPrincipal.Enabled = true;” ataması ile bunun filtreye ekliyoruz. Daha sonra oluşturulan bu UserPrincipal nesnesini parametre alan bir PrincipalSearcher nesnesi oluşturulur. Son adım olarak PrincipalSearcher nesnesinin FindAll metodu ile UserPrincipal üzerinden girilen değerlere uygun kullanıcılar sistemden alınır. Metotdan dönen değerler PrincipalSearchResult türünde olduğundan “Cast<UserPrincipal>()” metodu ile dönen sonuç UserPrincipal türüne çevrilir.

    PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "saitorhan.local", "Administrator", "123456qaZ.");
    UserPrincipal userPrincipal = new UserPrincipal(principalContext);
    userPrincipal.Enabled = true;
    PrincipalSearcher principalSearcher = new PrincipalSearcher(userPrincipal);
    List<UserPrincipal> principalSearchResult = principalSearcher.FindAll().Cast<UserPrincipal>().OrderBy(u => u.SamAccountName).ToList();

    Ekran görüntüsünde de görüldüğü üzere bu şekilde kullanıcı bilgileri AD Sunucusu üzerinden alındığında hesap ile ilgili her türlü bilgi elde edilebiliyor.

    Kullanıcının Üyesi Olduğu Grupları Bulma

    Kullanıcının gruplarını bulmak için öncelikle “UserPrincipal.FindByIdentity” metodu ile üyesi olduğu grupların sorgulanacağı kullanıcıyı sistemden alıyoruz. UserPrincipal.FindByIdentity metodu üç parametre alır. Bu parametreler sırasıyla;

    1. Yazının başında tanımını yaptığımız PrincipalContext nesnesi
    2. Kullanıcı hesabı sorgulanırken kullanılacak özellik. Biz örneğimizde SamAccountName özelliği ile sorgulama yapacağımızdan IdentityType.SamAccountName değerini kullanıyoruz.
    3. Sorgulama yapılacak özelliğe ait değer

    PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "saitorhan.local", "Administrator", "123456qaZ.");
    UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, "saitorhan");
    List<GroupPrincipal> principalSearchResult = userPrincipal.GetGroups().Cast<GroupPrincipal>().ToList();

    Dönen UserPrincipal nesnesinin GetGroups metodu ile kullanıcının üyesi olduğu gruplar alınır ve gene Cast<GroupPrincipal>() metodu ile dönen sonucu grupların temsil edildiği GroupPrincipal türüne çeviriyoruz.

    Ekran görüntüsünde de görünen enteresan bir duruma dikkatinizi çekmek istiyorum. Sonuç dönen grupların “Members” özelliğinin içinde o gruba üye olan kullanıcıları görebiliyoruz. Tabi bu kullanıcıların içerisinde de üye oldukları gruplar görünüyor. Bu iç içe sonuç kümeleri sayesinde aslında kullanıcının birinin hesabından girip aslında bütün kullanıcı ve grup bilgilerine ulaşılabilir. 🙂

    AD Gruplarının Sistemden Alınması

    AD sunucusundan grupların alınması işlemi de yazının ilk maddesi olan kullanıcı bilgilerinin alınması ile aynı adımlardan oluşmaktadır. Aradaki fark burada UserPrincipal yerine GroupPrincipal sınıfı kullanılmaktadır.

    PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "saitorhan.local", "Administrator", "123456qaZ.");
    GroupPrincipal groupPrincipal = new GroupPrincipal(principalContext);
    PrincipalSearcher principalSearcher = new PrincipalSearcher(groupPrincipal);
    List<GroupPrincipal> groupPrincipals = principalSearcher.FindAll().Cast<GroupPrincipal>().ToList();

    AD Grup Üyelerine Kullanıcı Ekleme

    AD gruplarından birine kullanıcı eklemek için öncelikle GroupPrincipal.FindByIdentity metodu ile kullanıcı eklenecek grup seçilir. Daha sonra dönen GroupPrincipal türündeki grup nesnesinin Members özelliğine Add metodu (group.Members.Add) ile kullanıcı eklenir. Add metodu üç parametre alır. Bu parametreler;

    1. Sunucu ile bağlantıyı sağlayan PrincipalContext
    2. Eklenecek kullanıcının hangi özelliği ile bulunup ekleneceği
    3. Eklenecek kullanıcının ikinci parametrede verilen özelliğinin değeri

    PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "saitorhan.local", "Administrator", "123456qaZ.");
    GroupPrincipal group = GroupPrincipal.FindByIdentity(principalContext, "Help Desk");
    group.Members.Add(principalContext, IdentityType.SamAccountName, "saitorhan");
    group.Save();
    

    AD Grup Üyelerinden Kullanıcı Silmek

    Gruptan kullanıcı silinirken de ekleme ile aynı adımlar takip edilir. Aradaki tek fark Add metodu yerine Remove metodu kullanılır.

    PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "saitorhan.local", "Administrator", "123456qaZ.");
    GroupPrincipal group = GroupPrincipal.FindByIdentity(principalContext, "Help Desk");
    group.Members.Remove(principalContext, IdentityType.SamAccountName, Username);
    group.Save();

    AD Kullanıcı Parolası Doğrulama

    PrincipalContext.ValidateCredentials metodu, parametre olarak aldığı kullanıcı adı ve parolanın eşleşip eşleşmediğini kontrol eder. İkinci parametrede verilen parola ilk parametrede verilen kullanıcıya aitse “true” yanlış şifre ise de “false” değer döner.

    PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "saitorhan.local", "Administrator", "123456qaZ.");
    bool credentials = principalContext.ValidateCredentials("bilalorhan", "Parolam1234");

    AD Kullanıcı Şifresi Değiştirme

    AD kullanıcısına ait şifreyi değiştirmek için UserPrincipal sınıfının SetPassword metodu kullanılır.

    PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "saitorhan.local", "Administrator", "123456qaZ.");
     UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, "bilalorhan");
    userPrincipal.SetPassword("Parolam1234");
    userPrincipal.Save();

    AD Kullanıcıyı İlk Oturum Açmada Parola Değiştirmeye Zorlama

    Kullanıcıyı ilk oturumda parola değiştirmeye zorlamak için öncelikle “userPrincipal.PasswordNeverExpires = false” ifadesi ile kullanıcının şifresinin süresiz geçerli olması iptal edilir. İkinci adımda “userPrincipal.ExpirePasswordNow()” metodu ile kullanıcının parolasını süresi sona ermişe çekilir.

    PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "saitorhan.local", "Administrator", "123456qaZ.");
    UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, userName);
    userPrincipal.PasswordNeverExpires = false;
    userPrincipal.ExpirePasswordNow();
    userPrincipal.Save();

    Kaynak Kodlar: https://github.com/saitorhan/CSharpForSystemAdmins




    SQL Server ve MySQL Server Destekli Yazılım Geliştirme

    Kurumsal olarak geliştirilen yazılımların özelliklerine bakıldığında hemen hemen hepsinde en az iki veri tabanı sistemini desteklediği belirtilmiştir. Bu özellik ilk bakışta her ne kadar geliştirilmesi zor bir özellik olarak görünse de aslında sadece temel kalıtım özellikleri kullanılarak geliştirilebilir. Bu yazımızda biz de herhangi bir harici kütüphane kullanmadan bu işlemi nasıl yaptığımızı inceleyeceğiz.

    Bu işle için öncelikle uygulamamızın destekleyeceği veri tabanı sistemlerinde eş yapılı bir veri tabanı yapısı kurulur. Biz örneğimizi tek tablo üzerinden götüreceğiz.

    MySQL Tablo Yapısı:

    CREATE TABLE `kisiler` (
      `id` int NOT NULL AUTO_INCREMENT,
      `isim` varchar(100) NOT NULL,
      `soyisim` varchar(100) NOT NULL,
      `telefon` char(10) NOT NULL,
      PRIMARY KEY (`id`)
    ) 

    SQL Server Tablo Yapısı

    CREATE TABLE Kisiler2(
    Id int PRIMARY KEY IDENTITY(1,1) NOT NULL,
    Isim nvarchar(100) NOT NULL,
    Soyisim nvarchar(100) NOT NULL,
    Telefon char(10) NOT NULL
    )

    Veri tabanı yönetim sistemi üzerinde tablolar oluşturulduktan sonra bu tablolara karşılık gelen C# sınıfları yazılır. Bu sınıfların yazılasının sebebi veri tabanı yönetim sistemlerimiz ile uygulamamızı ortak bir yapı altında konuşturabilmektir.

    Tablolara Karşılık C# Sınıfı

     class Kisi
        {
            public int Id { get; set; }
            public string Isim { get; set; }
            public string Soyisim { get; set; }
            public string Telefon { get; set; }
        }

    Sınıfımızı da oluşturduktan sonra artık veri tabanı işlemleri için yapımızı kurmaya başlayabiliriz. Yapımızın temelinde interface (ara yüz) kavramı olduğundan burada interface kavramına değinmek lazım.

    Interface

    Interface tanımlanırken herhangi bir sınıf tanımlanır gibi tanımlanır ancak türüne class yerine interface yazılır.

    Interface içerisinde neler bulunabilir neler bulunamaz:

    • Interface içerisinde propertyler bulunabilir.
    • Interface içerisinde tanımlanan metotların sadece başlık bildirimi yapılır, gövdesi tanımlanmaz.
    • Interface içerisinde tanımlanan property ve metotlar public olduğundan ayrıca erişim belirteci belirtilmez.

    Bu bilgilerden sonra şimdi tanımlanan tablomuz üzerinde yapılacak olan işlemlerin metotlarını barındıran bir interface tanımlayalım.

    interface IKisi
    {
       int KisiEkle(Kisi yeniKisi);
       List<Kisi> KisileriGetir();
    }

    İncelememizi iki metot üzerinden ilerleteceğiz. Tanımlanan interface içerisinde de göründüğü üzere metotların sadece başlık bilgileri girilmiş ancak gövdeleri tanımlanmamış. Gövdeleri yani bu metotların yapacakları işleri bu interfaceden türetilen sınıflar yapacak.

    Interface tanımı da yaptığımıza göre şimdi de sıra SQL Server ve MySQL Server işlemlerini yapacak sınıfları tanımlamaya.

    SQL Server Veri Tabanı İşlemleri

        class MsSqlKisiIslemleri : IKisi
        {
            public int KisiEkle(Kisi yeniKisi)
            {
                SqlConnection sqlConnection = new SqlConnection("Data Source=.\\egitim;Initial Catalog=OgretmenBilgi;Integrated Security=True");
                SqlCommand sqlCommand = new SqlCommand("INSERT INTO Kisiler([Isim], [Soyisim], [Telefon]) values(@i, @s, @t)", sqlConnection);
    
                sqlCommand.Parameters.AddWithValue("@i", yeniKisi.Isim);
                sqlCommand.Parameters.AddWithValue("@s", yeniKisi.Soyisim);
                sqlCommand.Parameters.AddWithValue("@t", yeniKisi.Telefon);
    
    
                sqlConnection.Open();
                int i = sqlCommand.ExecuteNonQuery();
                sqlConnection.Close();
    
                return i;
            }
    
            public List<Kisi> KisileriGetir()
            {
                List<Kisi> kisiler  = new List<Kisi>();
                SqlConnection sqlConnection = new SqlConnection("Data Source=.\\egitim;Initial Catalog=OgretmenBilgi;Integrated Security=True");
                SqlCommand sqlCommand = new SqlCommand("select Id, Isim, Soyisim, Telefon from Kisiler", sqlConnection);
                
                sqlConnection.Open();
                SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
    
                while (sqlDataReader.Read())
                {
                    Kisi kisi = new Kisi();
                    kisi.Id = sqlDataReader.GetInt32(0);
                    kisi.Isim = sqlDataReader.GetString(1);
                    kisi.Soyisim = sqlDataReader.GetString(2);
                    kisi.Telefon = sqlDataReader.GetString(3);
                    kisiler.Add(kisi);
                }
    
    
                sqlConnection.Close();
                return kisiler;
            }
        }

    MySQL Server Veri Tabanı İşlemleri

        class MySqlKisiIslemleri : IKisi
        {
            public int KisiEkle(Kisi yeniKisi)
            {
                MySqlConnection sqlConnection = new MySqlConnection("server=localhost;user id=root;database=egitim;pwd=123456qaZ.");
                MySqlCommand sqlCommand = new MySqlCommand("INSERT INTO Kisiler(isim, soyisim, telefon) values(@i, @s, @t)", sqlConnection);
    
                sqlCommand.Parameters.AddWithValue("@i", yeniKisi.Isim);
                sqlCommand.Parameters.AddWithValue("@s", yeniKisi.Soyisim);
                sqlCommand.Parameters.AddWithValue("@t", yeniKisi.Telefon);
    
    
                sqlConnection.Open();
                int i = sqlCommand.ExecuteNonQuery();
                sqlConnection.Close();
    
                return i;
            }
    
            public List<Kisi> KisileriGetir()
            {
                List<Kisi> kisiler = new List<Kisi>();
                MySqlConnection sqlConnection = new MySqlConnection("server=localhost;user id=root;database=egitim;pwd=123456qaZ.");
                MySqlCommand sqlCommand = new MySqlCommand("select id, isim, soyisim, telefon from Kisiler", sqlConnection);
    
                sqlConnection.Open();
                MySqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
    
                while (sqlDataReader.Read())
                {
                    Kisi kisi = new Kisi();
                    kisi.Id = sqlDataReader.GetInt32(0);
                    kisi.Isim = sqlDataReader.GetString(1);
                    kisi.Soyisim = sqlDataReader.GetString(2);
                    kisi.Telefon = sqlDataReader.GetString(3);
                    kisiler.Add(kisi);
                }
    
    
                sqlConnection.Close();
                return kisiler;
            }
        }

    İlgili işlem sınıflarımızı da tanımladıktan sonra şimdi de aralarında ki benzerlik ve farklılıklarına göz atalım.

    Benzerlikler:

    • Her iki sınıf da IKisi interfacesinden türetilmiştir ve interface özelliği gereği aynı metot tanımlarını barındırırlar
    • Metotların aldıkları parametre türleri ve dönüş türleri aynıdır.

    Farklılıklar:

    • Metotların gövdelerinde yer alan veri tabanı işlemleri sınıfların sorumlu oldukları veri tabanı sisteminin kodlarıdır.

    Ve geldik son işleme: Hem SQL Server hem MySQL Server için gerekli sınıflar ve kodlar yazıldığına göre uygulamamızda ilgili veri tabanı yönetim sistemine nasıl ulaşacağız?

    Öncelikle uygulamamızın hangi veri tabanı sisteminde çalışacağını bir sistem parametresi olarak kaydetmek gerekiyor. Bu kayıt işlemi Properties -> Settings altında veya app.config içerinde olabilir. Yazımız içerisinde bu parametreye “dbType” ismini vereceğiz.

    İlk işlemimizi olan kişi ekleme metodunu çağırmak için gerekli kodları yazalım.

    IKisi iKisi = null;
    
    if (dbType == SQLServer)
    {
        iKisi = new MsSqlKisiIslemleri();
    }
    
    else if(dbType == MySQL)
    {
        iKisi = new MySqlKisiIslemleri();
    }
    
    Kisi kisi = new Kisi
    {
        Isim = textBoxAd.Text,
        Soyisim = textBoxSoyad.Text,
        Telefon = textBoxTelefon.Text
    };
    
    int kisiEkle = iKisi.KisiEkle(kisi);

    Öncelikle veri tabanı türüne göre ilgili sınıfı barındıracak olan IKisi interfacesinden bir tanımlama yapıyoruz. Daha sonra dbType isimli sistem parametresinin değerine göre bu interfaceye ilgili sınıfın bir örneği atanıyor. Bu adımdan sonra metotlar interface üzerinden çağrıldığında artık kendisine atanan sınıfın içeriğini çalıştırır. Dolayısı ile bu adımdan sonra uygulamamız artık çoklu veri tabanı yönetim sistemi desteğine sahip olmuş oluyor.

    Kodlamada son olarak kişileri listeleme işlemi metotlarını çağıralım.

     IKisi iKisi = null;
    
    if (comboBoxDb.SelectedIndex == 0)
    {
        iKisi = new MsSqlKisiIslemleri();
    }
    
    else if (comboBoxDb.SelectedIndex == 1)
         {
              iKisi = new MySqlKisiIslemleri();
          }
    
    List<Kisi> kisiler = iKisi.KisileriGetir();

    Kişi ekleme işleminde olduğu gibi burada da oluşturulan interface ve ona atanan sınıflar üzerinden işlemler yapılıyor.

    Yazımızın sonucunu mini bir öz eleştiri ile kapatacak olursak; Eğitimlerde, okulda gördüğümüz her yeni bilginin muhakkak surette pratik hayatta profesyonel kullanımda nasıl kullanıldSQL Server ve MySQL Server Destekli Yazılım Geliştirmeığını sorgulayalım. Kendi adıma ilk olarak çoklu veri tabanı destekli yazılım geliştirme konusunu gördüğümde “çok zor bir işlem” demiştim ancak işlemi yaptığımda gördüm ki aslında çok iyi bildiğim bir konuymuş.

    Hepinize bol ve bugsız bir kodlama yaşamı diliyorum 🙂