Asp.Net Core'a Giriş

.Net Core Microsoft tarafından open-source olarak geliştirilmiş  modüler bir framework'dür. Asp.Net Core ise klasik bildiğimiz Asp.Net kütüphanesinin open-source olarak microsoft tarafından release edilmiş halidir.

Asp.Net yaklaşık 15 yıl önce Microsoft tarafından geliştirilmiş olup günümüz web teknolojileri arasından oldukça popüler olan bir kütüphanedir. Microsoft open-source dünyanın önlenemez yükselişi ile birlikte daha fazla dayanamadı ve en base de bildiğimiz .Net çatısı altında olan bütün teknolojilerini yeniden yapılandırıp open-souce olarak bütün dünya ile paylaşacağını bizlere 3 yıl önce duyurmuştu. Akabinde sırayla .Net çatısı altındaki framework'ler git-hub üzerinde yayınlanmaya başlandı.

Ms'in web için geliştirdiği kütüphanelerin kronolojik sırasına bakacak olursak

  • 2002 - ASP.Net 
  • 2008 - ASP.Net MVC 
  • 2012 - ASP.Net Web API and SignalR

son olarak ise 2016 yilinda .Net Core 1.0 release oldu ve bunula birlikte Asp.Net Core hayatımıza girdi.

Asp.Net Core Asp.Net'in daha sade ve modern bir yüzü olarak karşımıza çıkıyor. Microsoft'un Zamarin'i satın alması sonrası sahip olduğu cross-platform deneyiminide işin içine katarak Asp.Net Core'u bir Cross Platform kütüphane olarak bizlere sundu. Framework'ü kullanarak IoT uygulamaları, back-end service uygulamaları ve web projeleri geliştirebiliriz.


.Net Standart 2.0

Ms ilk olarak .Net Core 1.0 versiyonunu release etti ancak bu sürüm biz .net developer'lar için biraz alışkın olduğumuzdan farklı bir mimariye sahipti ve geliştirme yaparkende bazı zorluklarıda bulunuyordu. Microsoft 1.0 dan sonra yayınladığı 2.0 versiyonu ile birlikte .Net Standart 2.0 adında bir yenilik daha getirdi. .Net standart microsoft için şu demekti ben bütün .net teknolojilerini, dillerini vs hepsini bir standart altında topluyorum ve bunun adınıda .Net standart 2.0 koyuyorum dedi. Bu standart ile birlikte bütün .net platformlarının base'i .Net Standart olmuş oldu ve CoreCLR adında yeni bir ortak iletişim dili geliştirildi.

Asp.Net Core'un getirdiği yenilikleri ve faydaları sıralayacak olursak

  • Cross platform
  • High performance
  • Flexible deployment
  • Open source
  • Support for built-in dependency injection
  • Light-weight and modular
  • Side by side support
  • Faster development


Mac ve Linux işletim sistemlerinde çalışır hale getirildi ve cross platfrom coverage'ını yükseltmiş oldu.


Geliştirme Yaparken

İlk olarak bilgisayarınızda Vs 2015 update 3 yada vs2017 .Net Core SDK ile birlikte yüklü olması gerekmekte.
Proje oluşturuken ise klasik herzaman yaptığımız gibi new aşağıdaki gibi new project diyerek geliştirmek istediğimiz proje türünü seçerek solution'ımızıo yaratabiliriz.


Bu yazıda Asp.Net Core'a küçük bir giriş yaptık. Diğer yazılarımızda framework'ü örnek uygulamalar ile incelemeye devam edeceğiz.

Parallel LINQ Nedir

Linq(Language Integrated Query), heralde .Net framework'e ait en önemli 4-5 özellikten birisidir desek kimsenin itirazı olmaz. .NET 3.5 ile hayatımıza giren linq temelde; senkron bir biçimde veri üzerinde çeşitli query'ler yazıp filtreler oluşturabildiğimiz çok zengin içeriği olan bir .Net teknolojisidir. 

Parallel Linq (PLINQ), IEnumerable yada Enumerable<T> türündeki data-source'lar üzerinde linq işlemlerini paralel bir şekilde async olarak yapıalbilmesini sağlayan yapıdır. Bu işlemler PLinq'e ait bazı extension metotlar üzerinden yapılabilmektedir ve bu metotlar sayesinde eşzamanlı olarak işlem process edilebilmektedir. 

Örnek üzerinden ilerleyecek olursak, console'a 0-100 arası 4'e bölünebilen sayıları önce linq sonrada plinq kullanarak yazdıralım. İlk olarak aşağıdaki gibi kullanacağımız veriyi hazırlayalım.

    var source = new List<int>();
    for (int i = 0; i <= 100; i++)
    {
        source.Add(i);
    }

Linq kullanarak aşağıdaki kod bloğunu yazıp projeyi run edelim.

    Console.WriteLine("Non Parallel Result\n");
    var nonParallelResults =
                     from item in source
                     where item % 4 == 0
                     select item;

    foreach (int item in nonParallelResults)
    {
        Console.Write(item + " ");
    }
    Console.WriteLine("\n");
    Console.WriteLine("\n");

Projemizi run ettiğimizde aşağıdaki gibi sırasıyla sayıları ekrana display edecektir.

Şimdi ise aynı işlemi plinq kullanarak paralel olarak yaptıralım.

    Console.WriteLine("Parallel Result\n");
    var parallelResults =
                     from item in source.AsParallel()
                     where item % 4 == 0
                     select item;
    foreach (int item in parallelResults)
    {
        Console.Write(item + " ");
    }

Tekrardan projeyi run ettiğimizde ekran çıktısı aşağıdaki gibi olacaktır.

 Yukarıdaki işlemi paralel biçimde yapmamızı sağlayan şey .AsParallel() extension metodu dur. Linq kullanarak baktığımızda 4'e bölüne bilen sayıları küçükten büyüğe sıralayarak ekrana print ettiğini görürken PLinq kullanarak sayıların herhangi bir sıraya uymadan paralel bir şekilde print edildiğini gördük.

Source üzerinde Linq mu yoksa PLinq mu kullanılacağı tamamiyle yapacağınız iş ile ilgili bir durum yani "it depends on the business". Eğer sırasıyla devam etmesini istediğiniz bir process değilse ve process edilen işlemler arası herhangi bir bağımlılık vs. bulunmuyorsa PLinq çok rahat bir şekilde kullanabiliriz. 

Dapper ORM Nedir

Object relational mappers (ORMs); ilişkisel veritabanları ile programlama dillerinin nesne modelleri arasındaki uyumsuzluğu ortadan kaldırmak, kod ile database arasındaki uyumu %100 sağlamak için yazılım dünyasında uzun süredir kullanılmaktadırlar. Daha önceki ORM yazımızda Fluent NHibernate Nedir ve Kullanımı konusuna değinmiştik. Bu yazımızda ise birçok kişi tarafından en hızlı ORM olarak kabul edilen Dapper'ı inceleyeceğiz.

Dapper, Stack Overflow ekibi tarafından open-source geliştirilen lightweight bir ORM'dir. Lightweight olması sebebiyle diğer ORM'lere kıyasla çok daha hızlıdır.

Dapper, performans ve kullanım kolaylığı sağlaması düşünülerek geliştirilmiş bir ORM dir. Transaction, stored procedure yada bulk insery kullanarak static ve dynamic object binding yapabilmemizi sağlar.

Dapper Kullanımı

Dapper kullanımı için örnek basit bir app. geliştirelim. İlk olarak Vs'da Dapper_Sample adında bir ConsoleApp oluşturalım. Sonrasında nuget üzerinden Dapper'ı projemize indirip kuralım.

 Install-Package Dapper -Version 

Kurulum işlemi tamamlandıktan sonra örneğimiz şu şekilde olsun; ContosoCorp adında bir db ve bu db de Customer adında bir tablomuz olsun ve dapper kullanarak repository class ile bu tablo üzerinde CRUD işlemleri yapalım.

Öncelikle ContosoCorp db si için table create script'ini aşağıdaki gibi yazıp execute edelim ve Customer tablomuz oluşturalım.

create table Customer
(
 Id uniqueidentifier,
 FirstName nvarchar(50) not null,
 LastName nvarchar(50) not null,
 Email nvarchar(50) not null
)

İlk olarak tablomuza karşılık gelen Customer entity'sini aşağıdaki gibi oluşturalım.

    public class Customer
    {
        public Guid Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
    }

Şimdi ise CRUD işlemleri için CustomerRepository adında bir class oluşturalım ve içerisini CRUD metotlarını tanımlayalım.

    public class CustomerRepository
    {
        protected SqlConnection GetOpenConnection()
        {
            var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ContosoCorpDbConn"].ConnectionString);
            connection.Open();
            return connection;
        }
    }

Config dosyamızda kullanacağımız db için gerekli olan conn. string'inin ContosoCorpDbConn adıyla yazılı olduğunu varsayalım ve GetOpenConnection() metodu ile repository metotlarında kullanacağımız SqlConnection yaratacağız.

Dapper'da bulunan Query() metodu veritabanından retrieve data işlemini yani veri almamızı sağlayan ve model mapping'i yaparak modellerimizi dolduran metoddur. Aşağıda yazacağımız All() metodu ile Customer tablosunda bulunan bütün kayıtları select edeceğiz. 

        public IEnumerable<Customer> All()
        {
            using (var conn = GetOpenConnection())
            {
                return conn.Query<Customer>("Select * From Customer").ToList();
            }
        }

İkinci metot olarak Id parametresi alarak geriye tek bir Customer objesi return eden Get() metodunu yazalım.

        public Customer Get(Guid id)
        {
            using (var conn = GetOpenConnection())
            {
                return conn.Query<Customer>("Select * From Customer WHERE Id = @Id", new { id }).SingleOrDefault();
            }
        }

Dapper'da bulunan Execute() metodu ise db de insert, update veya delete işlemlerinde kullanılır. Aşağıda yazacağımız metot ile parametre olarak verilen customer nesnesini insert edeceğiz.

        public void Insert(Customer customer)
        {
            using (var conn = GetOpenConnection())
            {
                string sqlQuery = "INSERT Customer(FirstName,LastName,Email) Values(@FirstName,@LastName,@Email)";
                conn.Execute(sqlQuery, customer);
            }
        }

Yukarıda görüldüğü üzre ado.net'e aşinalığı olan kişiler aslında bir nevi ado.net yazdığımızı göreceklerdir çünkü dapper'ın temelinde AdoçNet vardır. Son metot olarak dapper ile yukarıda yazdığımız All() metodunu birde stored-procedure kullanarak yazalım. İlk olarak db üzerinden aşağıdaki gibi GetAllCustomersSP adında stored-procedure'ü tanımlayalım.

CREATE PROCEDURE GetAllCustomersSP
AS
BEGIN
    SELECT * FROM Customer
END

Sonrasında bu procedure'ü execute eden repository metodunu yazalım.

        public IEnumerable<Customer> AllUsingSp()
        {
            using (var conn = GetOpenConnection())
            {
                return conn.Query<Customer>("GetAllCustomersSP", commandType: CommandType.StoredProcedure).ToList();
            }
        }

 Repository metotlarını tanımladık sırada bu metotları kullanmak var. Program.cs içerisinde bu metotları call ederek yazdığımız kodları test edelim.

        static void Main(string[] args)
        {
            var custRepo = new CustomerRepository();

            var customer1 = new Customer { Id = Guid.NewGuid(), FirstName = "Caner", LastName = "Tosuner", Email = "info@canertosuner.com" };
            var customer2 = new Customer { Id = Guid.NewGuid(), FirstName = "Berker", LastName = "Sönmez", Email = "info@berkersonmez.com" };

            custRepo.Insert(customer1);
            custRepo.Insert(customer2);

            //returns 2 records
            var allCustomersUsingQuery = custRepo.All();

            //returns 2 records
            var allCustomersUsingSp = custRepo.AllUsingSp();

            Console.ReadLine();
        }

Projemizi run ettiğimizde Customer tablosuna sırasıyla 2 kayıt atacaktır ve sonrasında All() ve AllUsingSp() metotlarını kullanarak tabloya select sorgusu yaptığımızda bize yukarıda kaydettiğimiz 2 kaydı return edecektir.

Dapper aynı zamanda transactional işlemleri de destekler. UnitOfWork pattern'i BeginTransaction() ve EndTransaction() metotlarını kullanarak uygulanabilir.

 

Not : Nuget de bulunan DapperExtensions kütüphanesi kullanarak gerekli mapping işlemlerini yaptıktan sonra repository metotları içerisinde sql komutları yerine aşağıdaki gibi de kullanabiliriz. Not: Bu mapping üzerinden table/column auto generate işlemi olmamakta sadece mapping işlemini sağlamakta.

Install-Package DapperExtensions 

    public class CustomerMapper : ClassMapper<Customer>
    {
        public CustomerMapper()
        {
            base.Table("Customer");
            Map(f => f.Id).Key(KeyType.Guid);
            Map(f => f.FirstName);
            Map(f => f.LastName);
            Map(f => f.Email);
        }
    }
        public IEnumerable<Customer> All()
        {
            using (var conn = GetOpenConnection())
            {
                return conn.GetList<Customer>().ToList();
            }
        }

        public Customer Get(Guid id)
        {
            using (var conn = GetOpenConnection())
            {
                return conn.Get<Customer>(id);
            }
        }

DapperExtensions kütüphanesi ile kolayca bir Generic Repository Pattern infrastructure'ı geliştirebilirsiniz. Yazının sadeliği açısından bu ben değinmedim ancak sonraki yazılarımızda bir IoC kütüphanesi kullanarak Dapper ile basitçe bir api projesi geliştireceğiz.

Dapper son derece geliştirmesi kolay ve kullanışlı bir ORM dir. NHibernate ve EntityFramework'de olduğu gibi model mapping'inizden table/column generate etmez ancak sql sorgularını oldukça hızlı bir şekilde execute eder ve result'larını POCO class'larınıza map'ler. Bu özelliğiyle developer'lar arasında oldukça popülerdir.

Nhibernate IPreInsertEventListener ve IPreUpdateEventListener Kullanımı

Server-side bir projede geliştirme yapıyorsanız ve db de bolca CRUD işlemleri için query'ler çalıştırmanız gerekiyorsa sizden db de kaydedilen o row için sizden insert veya update anında bazı bilgileri otomatik bir şekilde o row için kaydetmeniz istenebilir. Örnek olarak; CreatedDate veya update edilen değer için ModifiedDate gibi alanlar tutmanız muhakkak istenir istenmese dahi bu bilgileri ilgili colum'lar da tutmak muhakkak bir gün işinize yarayacaktır.

Eğer CRUD işlemlerini Ado.Net kullanarak yapıyorsanız query'nin sonuna bu değerleri ekleyebilir yada stored-procedure kullanıyorsanız da bu işlemleri sp içerisinde de yapabiliriz.

Bu yazımızda bu ve benzeri işlemleri Fluent-Nhibernate kullanarak nasıl yapabiliriz konusuna değineceğiz. 

Her defasında yeni kayıt geldi modeli initialize ederken CreatedDate alanına DateTime.Now set et, yada her update işlemi geldiğinde ModifiedDate alanına DateTime.Now alanını set et. Pek de hoş durmuyor sanki. 50'ye yakın db de tablonuz olduğunu düşünün her bir entity için gidip bu işlemleri heralde yapmak istemeyiz .

Eğer proejenizde NHibernate'i kullanıyorsanız Nhibernate bu işlemler için bizlere aşağıdaki interface'leri sunmakta.

  • IPreInsertEventListener
  • IPreUpdateEventListener

IPreInsertEventListener; adında da anlaşılacağı üzre entity'niz insert edilirken bir interceptor gibi araya girmemizi sağlayan ve insert query execution'dan OnPreInsert adındaki metoduna invoke edilerek entity'niz üzerinde işlemler yapmanızı sağlar.

IPreUpdateEventListener; ise bir update listener'ı dır ve içerisinde implement edebildiğimiz OnPreUpdate  metodu çağrılır update query'sinin execution'dan önce call edilerek yine entity üzerinde değişiklikler yapabilmemizi sağlar.

Örnek olarak bir BaseModel'miz olsun ve projemizde bulunan her bir entity için tablolarda ortak bulunan alanları bu class içerisinde tanımlayabiliriz.

    public abstract class BaseModel
    {
        public virtual Guid Id { get; set; }
        public virtual DateTime? CreatedDate { get; set; }
        public virtual DateTime? ModifiedDate { get; set; }
    }

Db de bulunan tablolarımıza karşılık gelen entity'lerimiz ise yukarıda tanımladığımız BaseModel class'ından inherit olacaklar. Örnek olarak Customer adında aşağıdaki gibi bir entity tanımlayalım.

    public class Customer : BaseModel
    {
        public virtual string FirstName { get; set; }
        public virtual string LastName { get; set; }
        public virtual string Email { get; set; }
    }

Şimdi ise CustomerMap class'ını oluşturacaz ancak öncesinde BaseModel içerisinde bulunan proeprty'ler için BaseMapping adında bir class tanımlayalım. Customer ve diğer db modellerimizde bu BaseMapping'i kullanarak map işlemlerini yapacağız. Bunu yapmamızdaki amaç her bir entity için ayrı ayrı gidip BaseModel içerisinde bulunan alanların map'ini yapmamak. 

    public class BaseMapping<T> : ClassMap<T> where T : BaseModel
    {
        public BaseMapping()
        {
            Id(x => x.Id);
            Map(x => x.CreatedDate);
            Map(x => x.ModifiedDate);
        }
    }

 

Artık BaseMapping 'i kullanarak CustomerMap class'ını oluşturabiliriz. 

    public class CustomerMap : BaseMapping<Customer>
    {
        public CustomerMap()
        {
            Map(x => x.FirstName);
            Map(x => x.LastName);
            Map(x => x.Email);
        }
    }

Sırada Listener class'ını oluşturmak var. Aşağıda NHInsertUpdateListener adında bir class tanımlayalım. Yazının başında bahsettiğimiz her tablomuzda bulunan CreatedDate ve ModifiedDate tarih alanlarını NHInsertUpdateListener içerisinde set edeceğiz.

    public class NHInsertUpdateListener : IPreInsertEventListener, IPreUpdateEventListener
    {
        public bool OnPreUpdate(PreUpdateEvent @event)
        {
            var audit = @event.Entity as BaseModel;
            if (audit == null)
                return false;

            var time = DateTime.Now;

            Set(@event.Persister, @event.State, "CreatedDate", time);

            audit.CreatedDate = time;

            return false;
        }

        public bool OnPreInsert(PreInsertEvent @event)
        {
            var audit = @event.Entity as BaseModel;
            if (audit == null)
                return false;


            var time = DateTime.Now;

            Set(@event.Persister, @event.State, "ModifiedDate", time);

            audit.ModifiedDate = time;

            return false;
        }

        private void Set(IEntityPersister persister, object[] state, string propertyName, object value)
        {
            var index = Array.IndexOf(persister.PropertyNames, propertyName);
            if (index == -1)
                return;
            state[index] = value;
        }
    }

Artık son adım olarak FluentNHibernate'i ayağa kaldırmak var. Nh configuration'ı aşağıdaki gibi tanımlayabiliriz.

Fluently.Configure()
               .Database(MsSqlConfiguration.MsSql2012.ConnectionString(c => c.FromAppSetting("dbConnectionString")).ShowSql())
               .Mappings(m => m.FluentMappings.AddFromAssemblyOf<CustomerMap>())
               .ExposeConfiguration(cfg => new SchemaUpdate(cfg).Execute(false, true))
               .ExposeConfiguration(cfg =>
               {
                   cfg.SetProperty(
                      NHibernate.Cfg.Environment.CurrentSessionContextClass,
                       "web");
                   cfg.AppendListeners(ListenerType.PreUpdate, new IPreUpdateEventListener[] { new NHInsertUpdateListener() });
               })
               .BuildSessionFactory();

 

Sırasıyla yazmak gerekirse neler yaptık;

  1. Vs da bir tane proje oluşturduk. (Console veya Api),
  2. FluentNHibernate paketini nuget'ten indirip kurduk,
  3. Bir db miz olduğunu ve connection string bilgisinin web config'de tanımlı olduğunu varsaydık,
  4. Tablolarda ortak kullanılan propert'leri BaseModel adında ki class da topladık,
  5. Daha sonra BaseMapping adında bir mapping tanımlaması yaparak entity içerisindeki property'leri map ettik,
  6. CustomerMap class'ını oluşturarak mapping işlemini tanımladık,
  7. NHInsertUpdateListener'ı oluşturduk ve CreatedDate - ModifiedDate alanları için değerleri set ettik.
  8. Fluent Nhibernate konfigurasyonunu oluşturduk.

 Listener'lar biraz az bilinen bir özellik gibi görünse de oldukça faydalıdırlar. Örnekte olduğu gibi benzer case'lerde kullanarak bizleri satırlarca tekrar eden kodlardan uzaklaştırır.

C# Compare Two Objects and Get Differences

Db de kayıtlı bulunan bir nesne için Update işlemi yaparken bazen öyle denk gelir ki sizden sadece ilgili objede değişen alanların gönderilmesi veya değişen alan var mı yok mu diye bir takım can sıkıcı validasyonlar yapmanız istenir ki hele bir de işin içine javascript girerse yemede yanında yat. İşte bu gibi durumlar için gidip sürekli olarak mevcut objedeki alanla yeni değer compare edilip değişmiş mi değişmemiş mi diye bir sürü logic yazmayı tabii ki de pek istemeyiz.

Örnek bir case üzerinden anlatmak gerekirse; aşağıdaki gibi User diye bir modeliniz ve sizden UpdateUser adından bir end-point yazmanız isteniyor ve analizde objede bulunan hangi alan kullanıcı tarafından değiştirilmiş bunlarla ilgili log tutmanız veya bilgilendirme emaili atmanız gerektiği yazılmış.

    public class User
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string EMail { get; set; }
        public DateTime BirthDate { get; set; }
        public int ZipCode { get; set; }
        public bool IsPublic { get; set; }
    }

Gidip db de kayıtlı bulunan objedeki property ile kullanıcıdan aldığınız değeri teker teker compare etmek istemeyiz elbette  if(dbUserModel.FirstName == newUserModel.FirstName) . Bu gibi bir durum için Reflection'dan faydalanabiliriz. Aşağıdaki gibi bir MemberComparisonResult adında bir model tanımlayalım ve generic tanımlayacağımız CompareObjectsAndGetDifferences  adından ki metottan bu modeli döndürelim.

    public class MemberComparisonResult
    {
        public string Name { get; }
        public object FirstValue { get; }
        public object SecondValue { get; }

        public MemberComparisonResult(string name, object firstValue, object secondValue)
        {
            Name = name;
            FirstValue = firstValue;
            SecondValue = secondValue;
        }

        public override string ToString()
        {
            return Name + " : " + FirstValue.ToString() + (FirstValue.Equals(SecondValue) ? " == " : " != ") + SecondValue.ToString();
        }
    }

Şimdi ise CompareObjectsAndGetDifferences adındaki metodumuzu aşağıdaki yazalım.

        public static List<MemberComparisonResult> CompareObjectsAndGetDifferences<T>(T firstObj, T secondObj)
        {
            var differenceInfoList = new List<MemberComparisonResult>();

            foreach (var member in typeof(T).GetMembers())
            {
                if (member.MemberType == MemberTypes.Property)
                {
                    var property = (PropertyInfo)member;
                    if (property.CanRead && property.GetGetMethod().GetParameters().Length == 0)
                    {
                        var xValue = property.GetValue(firstObj, null);
                        var yValue = property.GetValue(secondObj, null);
                        if (!object.Equals(xValue, yValue))
                            differenceInfoList.Add(new MemberComparisonResult(property.Name, xValue, yValue));
                    }
                    else
                        continue;
                }
            }
            return differenceInfoList;
        }
    }

Son olarak da yazdığımız metodu aşağıdaki gibi bir ConsoleApplication'da test edelim.

        static void Main(string[] args)
        {
            var existingUser = new User
            {
                FirstName = "Mestan",
                LastName = "Tosuner",
                BirthDate = DateTime.Today.AddYears(23),
                EMail = "mestan@mestanali.com",
                ZipCode = 34000,
                IsPublic = false
            };

            var existingUserWithNewValue = new User
            {
                FirstName = "Mestan Ali",
                LastName = "Tosuner",
                BirthDate = DateTime.Today.AddYears(23),
                EMail = "mestan@mestanali.com",
                ZipCode = 55400,
                IsPublic = true
            };

            var changes = CompareObjectsAndGetDifferences(existingUser, existingUserWithNewValue);
            foreach (var item in changes)
            {
                Console.WriteLine(item.ToString());
            }
        }

Projenizi çalıştırdıktan sonra ekran çıktısı aşağıdaki gibi olacaktır.

Gördüğünüz gibi existingUserWithNewValue ismindeki modeldeki değerler kullanıcıdan yeni alınan değerlere sahip. Yukarıdaki ekran görüntüsünde de bize FirstName, ZipCode ve IsPublic alanlarının güncellendiğini söylemekte ve ilk değerleri ile ikinci değerlerini ekrana display etmekte.

Tuples Nedir - C# 7.0

Tuple custom bir class oluşturmadan üzerinde birden fazla specific değer tutabilen bir veri yapısıdır. Diğer bir değişle; geriye birden fazla parametre döndürmek istediğimiz bir metot var diyelim ve bu parametreler için normalde gidip custom bir nesne oluşturup sonra gidip bu nesneyi initialize edip property'lerini set'leyip metottan return ederdik veya bu bahsettiğimizi yeni bir object tanımlamadan out parametresini kullanarak da geriye döndürebilirdik ancak bir çok kişiye göre hem biraz maliyetli olarak kabul edilir hemde out async metotlarda kullanılamamaktadır. Bunun yerine daha basit ve anlaşılır olan tuple kullanarak çok rahat bir şekilde metottan geriye birden fazla parametre return edebiliyoruz.

Tuple ilk olarak .net 4.0 ile hayatımıza girdi. C#7.O ile birlikte kullanım olarak çok daha basit bir hale getirilmiş ve sanki ilerleyen günlerde projelerimizde biraz daka sık kullanacağız gibi duruyor. 

Tuple System.ValueTuple namespace'i altında yer almakta ve ilgili namespace'i nuget üzerinden bulup projemize indirelim.

Örnek olarak aşağıdaki gibi 3 tane integer değer alan ToplamlariCarpimlari adında Tuple özelliği olan bir metot tanımlayalım ve bu metot geriye ilk değer olarak toplamlarını ikinci değer olarak bu sayıların çarpımlarından elde dilen sayıyı return ediyor olsun.

	public static void Main()
	{
		var sonuc = ToplamlariCarpimlari(2,5,7);
		
		Console.WriteLine(sonuc.toplami);
		Console.WriteLine(sonuc.carpimi);
	}
	
	public static (int toplami, int carpimi) ToplamlariCarpimlari (int x,int y,int z)
	{
	   var t = x + y + z;
	   var c = x * y *z;
		
	   return (t,c);
	}

Yukarıda olduğu gibi main function içerisinde metodumuzu çağırdıktan sonra return ettiği değeri sanki içerisinde toplami, carpimi adında iki property barındıran bir custom nesneymiş gibi rahatça kullanabiliyoruz ve intellisense de direkt olarak nokta "." operatörü kullanarak bu return değerlerini algılayabilmekte.

Tuple kısaca bu şekilde. Basit bir özellik gibi görünsede bizleri fazladan nesneler oluşturmaktan ve async metotlar out parametresini kullanamıyorken çok rahat bir şekilde yukarıdaki metodu async olarak yazmamıza olanak sağlamakta.

Moq Library Kullanarak Unit Test Yazma

Daha önceki yazımızda Unit Test Nedir Nasıl Yazılır konusuna değinmiştik ve basit bir console uygulaması ve onun unit test metotlarının bulunduğu test projemizi yazmıştık. O örneğimizde herhangi bir database veya kendi oluşturduğumuz data modelleri vs yoktu 4 işlem yapan bir projeydi. Bu yazımızda Db operasyonları olan bir projede unit test yazmak istesek ne yapardık bu soruya cevap arıyor olacağız.

Bir UserRepository class'ımız olsun ve bu repository için unit test metotları yazıyor olalım. Peki ama test metotlarını yazarken nasıl bir yol izleyeceğiz ? Her bir test case'i için gidip database saçma sapan fake kayıtlar atıp CRUD işlemleri yapmamamız gerekir. Bu gibi durumlar için mocking dediğimiz "alaycı" veya "sahte" kayıtlar oluşturmamızı sağlayan library'ler bulunmakta. Bu library'lerden Moq'u kullanarak sahte nesneler üreterek UserRepository için basit bir test projesi yazacağız.

Moq

Moq .Net tarafında unit test yazmada kullanabildiğimiz bir mocking kütüphanesidir. Testlerimiz için sahte nesneler üreterek normal projemizde ki case'leri test etmemizi sağlar.

Örnek projemiz için öncelikle bir tane UserSample adımda Console Application oluşturalım ve içerisine User.cs ve IUserRepository.cs class'larını aşağıdaki gibi tanımlayalım.

    public class User
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    public interface IUserRepository
    {
        IList<User> GetAll();
        User GetById(int userId);
        void Insert(User user);
        void Update(User user);
        void Delete(int Id);
    }

Şimdi ise UserSample.Test adında test projemizi oluşturalım ve UserSample projemizi referans olarak test projemize ekleyelim. Sonrasında test projemize Nuget üzerinden Moq kütüphanesini kuralım.

Tools > Nuget Package Manager > Package Manager Console > PM> Install-Package Moq

 Kurulum işlemi tamamlandıktan sonra UserRepositoryTest adında bir class oluşturalım.

İlk olarak User Repository için gerekli olan setup işlemlerini yapalım. Setup işlemi kısaca repository'nin içerisindeki metotların sahte objelerle işlemleri yapmasını sağlayacak kodları yazmak diyebiliriz. Mocking setup ile ilgili kodlarımız aşağıdaki gibi olacaktır.

 [TestClass]
    public class UserRepositoryTest
    {
        public readonly IUserRepository MockUserRepository;

        public UserRepositoryTest()
        {
            // Test metotları genelinde kullanacağımız User listesi
            var userList = new List<User>
            {
                new User {Id=1,FirstName="User1",LastName="User1LastName" },
                new User {Id=2,FirstName="User2",LastName="User2LastName" },
                new User {Id=3,FirstName="User3",LastName="User3LastName" }
            };

            // Mock the Products Repository using Moq
            var mockUserRepository = new Mock<IUserRepository>();

            // GetAll metodu için setup işlemi
            mockUserRepository.Setup(mr => mr.GetAll()).Returns(userList);

            // GetById metodu için setup işlemi
            mockUserRepository.Setup(mr => mr.GetById(It.IsAny<int>())).Returns((int i) => userList.Single(x => x.Id == i));

            // Insert için setup işlemi
            mockUserRepository.Setup(mr => mr.Insert(It.IsAny<User>())).Callback(
                (User target) =>
                {
                    userList.Add(target);
                });

            // Update için setup işlemi
            mockUserRepository.Setup(mr => mr.Update(It.IsAny<User>())).Callback(
                (User target) =>
                {
                    var original = userList.Where(q => q.Id == target.Id).Single();

                    if (original == null)
                    {
                        throw new InvalidOperationException();
                    }

                    original.FirstName = target.FirstName;
                    original.LastName = target.LastName;

                });

            // Test metotlarından erişilebilmesi için global olarak tanımladığımız MockUserRepository'e yukarıdaki setup işlemlerini atıyoruz
            this.MockUserRepository = mockUserRepository.Object;
        }
}

Yukarıda bulunan kodlar kısaca şunları söylemekte;

Arkadaş senin IUserRepository diye CRUD işlemlerinin yapıldığı bir class'ın var ve bu class içerisinde bulunan GetAll, GetById, Insert, Update, Delete metotları için tanımlanan mocking veya kandırmaca işlemleri yukarıdaki gibidir. Sen Database üzerinden bu işlemleri yapmak yerine rahatça userList array'i üzerinden bu işlemleri yapabilirsin.

Buraya kadar her şey OK ise aşağıdaki gibi sırasıyla test metotlarımızı yazalım.

GetAll metodunu çağırarak bize veri döndüğünü gösteren test metodu.

        [TestMethod]
        public void GetAll_Than_Check_Count_Test()
        {
            var expected = this.MockUserRepository.GetAll().Count;

            Assert.IsNotNull(expected);// Test not null
            Assert.IsTrue(expected > 0);// Test GetAll returns user objects
        }

GetById metodu için doğru objeyi return edip etmediği durumu için test metodu.

        [TestMethod]
        public void GetById_Than_Check_Correct_Object_Test()
        {
            var actual = new User { Id = 2, FirstName = "User2", LastName = "User2LastName" };

            var expected = this.MockUserRepository.GetById(2);

            Assert.IsNotNull(expected); // Test is not null
            Assert.IsInstanceOfType(expected, typeof(User)); // Test type
            Assert.AreEqual(actual.Id, expected.Id); // test correct object found
        }

Insert işleminden sonra GetAll metodundan dönen object sayısı doğrumu testi

        [TestMethod]
        public void Insert_User_Than_Check_GetAll_Count_Test()
        {
            var actual = this.MockUserRepository.GetAll().Count + 1;

            var user = new User { Id = 4, FirstName = "User4", LastName = "User4LastName" };

            this.MockUserRepository.Insert(user);

            var expected = this.MockUserRepository.GetAll().Count;

            Assert.AreEqual(actual, expected);
        }

GetById metoduna hatalı bir Id ile çağrım yapıldığında Exception döneceği durumu için test metodu.

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]//Eğer beklediğimiz bir exception var ise bu şekilde tanımlayabiliriz
        public void GetyId_With_Undefined_Id_Than_Exception_Occurred_Test()
        {
            var expected = this.MockUserRepository.GetById(It.IsAny<int>());
        }

Update işlemi sonrasında GetById yapılarak dönen nesnede bulunan değerler doğrumu test metodu.

        [TestMethod]
        public void Ipdate_User_Than_Check_It_Is_Updated_Test()
        {
            var actual = new User { Id = 2, FirstName = "User2_Updated", LastName = "User2LastName_Updated" };

            this.MockUserRepository.Update(actual);

            var expected = this.MockUserRepository.GetById(actual.Id);

            Assert.IsNotNull(expected);
            Assert.AreEqual(actual.FirstName, expected.FirstName);
            Assert.AreEqual(actual.LastName, expected.LastName);
        }

Test metotlarını yazdıktan sonra Run All Tests diyerek testlerimizi çalıştırıp success fail durumlarını görebiliriz.

Bu yazımızda bir Mocking kütüphanesi olan Moq kullanarak basitçe bir Unit Test projesi hazırladık ve halen daha çok fazla önemsenmese de unit Test dev-ops süreçlerinin olgunlaşmasıyla artık bir çok firma için "IsMust" zorunlu hale gelmiş bir kuraldır ve daha önceki yazılarda da bahsettiğim üzre Unit Test yazıyor olmak artık interview'larda beklenen bir durum haline gelmiştir.

Unit Test Nedir

Unit Test günümüz yazılım dünyasında artık olmazsa olmaz bir kural olarak bütün projelerde yazılması zorunlu hale gelmekte ve mülakatlarda Unit Test yazabiliyorum diyebilmek bile biz developer lar için zamanla ciddi bir bonus oluyor. DevOps açısından düşündüğümüzde Continuous Integration ve Continuous Deployment tool'ları yazmış olduğumuz kodları build edip deploy etmeden önce ilk olarak test metotlarını çalıştırır ve metotlardan herhangi biri fail verdiğinde deploy'u durdurup developer'ı bilgilendirir. Bu akış . Kısaca Unit Test artık Nice to Have olmaktan çıkıp Is Must hale gelmektedir. Bu yazımızda Unit Test nedir, nasıl yazılır gibi sorulara cevap arıyor olacağız.

Unit Test Nedir ?

Unit test geliştirmiş olduğunuz kodu test etmek için yazdığınız kod dur ve esas olarak kodun veya fonksiyonun belirli bir biriminin davranışını kontrol eder ve geliştirmeyi yapan developer tarafından yazılır.

Unit test aynı zamanda kodlarınızı kullanacak diğer developer'lar tarafından okunduğunda ise onların kodları nasıl kullanması gerektiğini anlatması açısından da önemli bir göreve sahiptir. Nasıl çalıştığını öğrenmek için testleri çalıştırıp okuyabilirler.

Bazı Unit Test Frameworkleri

  1. MSTest
  2. NUnit
  3. xUnit
  4. MBunit

 

Örnek Proje

Şimdi küçük bir unit test örneği yapalım. Eft işlemi yapan bir modül için bir Console Application ve bu modülü basitçe test etmek için bir unit test projesi oluşturalım.

İlk olarak VS da EftSample adında bir console projesi oluşturalım ve sonrasında solution'a sağ tıklayıp yeni bir proje ekle diyerek ismi EftSample.Test adında bir UnitTest projesi oluşturalım.

Eft işleminde kullanılacak olan TransferRequest ve TransferResponse adında class'larını console uygulamamıza aşağıdaki gibi oluşturalım.

       public class TransferRequest
       {
           public decimal Amount { get; set; }
           public string SenderIBAN { get; set; }
           public string ReceiverIBAN { get; set; }
       }
 
       public class TransferResponse
       {
           public bool IsSuccess { get; set; }
           public string Message { get; set; }
       }

Daha sonra transfer işlemini yapacak olan metodu Transfer adında bir class içerisine TransferMoney adında bir metot aşağıdaki gibi tanımlayalım.

Transfer.cs

    public class Transfer
    {
        public TransferResponse MoneyTransfer(TransferRequest request)
        {
            var response = new TransferResponse();
            
            //Aşağıdaki validasyonlar için farklı yöntemler, frameworkler kullanılması daha doğrudur ancak açık görünmesi açısından bu şekilde yapalım
            if (request.Amount < 1)
            {
                response.IsSuccess = false;
                response.Message = "Amount must be greater Then 1";
                return response;
            }
            if (string.IsNullOrEmpty(request.SenderIBAN))
            {
                response.IsSuccess = false;
                response.Message = "Sender Account IBAN must not be null or empty.";
                return response;
            }
            if (string.IsNullOrEmpty(request.ReceiverIBAN))
            {
                response.IsSuccess = false;
                response.Message = "Receiver Account IBAN must not be null or empty.";
                return response;
            }

            //TODO do process
            response.IsSuccess = true;
            response.Message = "Transfer operation is successful.";

            return response;
        }
    }

Şimdi sıra test metotlarını yazmaya geldi. EftSample.Test adında ki test projemize gidip EftSample projemizi referans olarak ekleyelim. Sonrasında TransferMoneyTest.cs adında test metotlarımızı yazacağımız class'ı oluşturalım.

Not - 1: Unit test yazarken naming oldukça önemli bir konudur. Ortak kabul görmüş bir standart olan MethodName_StateUnderTest_ExpectedBehavior şeklinde bir isimlendirme önerilir ancak her yiğidin yoğurt yiyişi farklıdır tezinden yola çıkarak developer anlaşılır yazdığı sürece isimlendirmeyi istediği gibide yapabilmektedir. 

Not - 2: Test metotlarını yazdığımız class'ların başında [TestClass] adında bir attribute tanımlaması yapılması zorunludur. Bu attribute ile sistem o class'ın bir test class'ı olduğunu anlamakta.

Not - 3: Yazılmış olan test metotlarının başında [TestMethod] attribute'ü yazılması gerekir. Bu attribute o metodun bir test metodu olduğunu işaret etmekte.

1- Amount Less Then One Test

İlk test metodumuz Amount = 0 olarak eft işlemi yapmaya çalıştığımızda ki case'i test ediyor olsun.

        [TestMethod]
        public void TransferMoney_With_Zero_Amount_Then_Transfer_Failed_Test()
        {
            var expected = new TransferResponse
            {
                IsSuccess = false,
                Message = "Amount must be greater Then 1"
            };

            var transfer = new Transfer();

            var transferRequest = new TransferRequest
            {
                Amount = 0,
                ReceiverIBAN = "TR806541651616516416541",
                SenderIBAN = "TR13216498468465416"
            };

            var actual = transfer.MoneyTransfer(transferRequest);

            Assert.AreEqual(expected.IsSuccess, actual.IsSuccess);
            Assert.AreEqual(expected.Message, actual.Message);
        }

2- Sender IBAN Empty Test

İkinci test metodu ise sender iban alanı boş bırakıldığında ki case'i test ediyor olsun.

        [TestMethod]
        public void TransferMoney_With_Empty_Sender_IBAN_Then_Transfer_Failed_Test()
        {
            var expected = new TransferResponse
            {
                IsSuccess = false,
                Message = "Sender Account IBAN must not be null or empty."
            };

            var transfer = new Transfer();

            var transferRequest = new TransferRequest
            {
                Amount = 60,
                SenderIBAN = string.Empty,
                ReceiverIBAN = "TR13216498468465416"
            };

            var actual = transfer.MoneyTransfer(transferRequest);

            Assert.AreEqual(expected.IsSuccess, actual.IsSuccess);
            Assert.AreEqual(expected.Message, actual.Message);
        }

3- All Pramters Are Ok Test

Son metodumuz da doğru bilgilerle transfer işlemi yapılmaya çalışıldığında ki case'i test ediyor olsun.

        [TestMethod]
        public void TransferMoney_With_Correct_Request_Parameter_Then_Transfer_OK_Test()
        {
            var expected = new TransferResponse
            {
                IsSuccess = true,
                Message = "Transfer operation is successful."
            };

            var transfer = new Transfer();

            var transferRequest = new TransferRequest
            {
                Amount = 60,
                ReceiverIBAN = "TR806541651616516416541",
                SenderIBAN = "TR13216498468465416"
            };

            var actual = transfer.MoneyTransfer(transferRequest);

            Assert.AreEqual(expected.IsSuccess, actual.IsSuccess);
            Assert.AreEqual(expected.Message, actual.Message);
        }

Test metotlarımızı yazdıktan sonra aşağıdaki görselde olduğu gibi VS'da bulunan Test > Run > All Tests dedikten sonra Test Explorer açılır ve solution da bulunan test metotları çalıştırılıp success ve fail durumlarını görebiliriz.

TransferMoneyTest.cs içerisi son olarak aşağıdaki gibidir.

    [TestClass]
    public class TransferMoneyTest
    {
        [TestMethod]
        public void TransferMoney_With_Zero_Amount_Then_Transfer_Failed_Test()
        {
            var expected = new TransferResponse
            {
                IsSuccess = false,
                Message = "Amount must be greater Then 1"
            };

            var transfer = new Transfer();

            var transferRequest = new TransferRequest
            {
                Amount = 0,
                ReceiverIBAN = "TR806541651616516416541",
                SenderIBAN = "TR13216498468465416"
            };

            var actual = transfer.MoneyTransfer(transferRequest);

            Assert.AreEqual(expected.IsSuccess, actual.IsSuccess);
            Assert.AreEqual(expected.Message, actual.Message);
        }

        [TestMethod]
        public void TransferMoney_With_Empty_Sender_IBAN_Then_Transfer_Failed_Test()
        {
            var expected = new TransferResponse
            {
                IsSuccess = false,
                Message = "Sender Account IBAN must not be null or empty."
            };

            var transfer = new Transfer();

            var transferRequest = new TransferRequest
            {
                Amount = 60,
                SenderIBAN = string.Empty,
                ReceiverIBAN = "TR13216498468465416"
            };

            var actual = transfer.MoneyTransfer(transferRequest);

            Assert.AreEqual(expected.IsSuccess, actual.IsSuccess);
            Assert.AreEqual(expected.Message, actual.Message);
        }

        [TestMethod]
        public void TransferMoney_With_Correct_Request_Parameter_Then_Transfer_OK_Test()
        {
            var expected = new TransferResponse
            {
                IsSuccess = true,
                Message = "Transfer operation is successful."
            };

            var transfer = new Transfer();

            var transferRequest = new TransferRequest
            {
                Amount = 60,
                ReceiverIBAN = "TR806541651616516416541",
                SenderIBAN = "TR13216498468465416"
            };

            var actual = transfer.MoneyTransfer(transferRequest);

            Assert.AreEqual(expected.IsSuccess, actual.IsSuccess);
            Assert.AreEqual(expected.Message, actual.Message);
        }
    }

Çok farklı frameworkler kullanarak çok farklı test yapıları oluşturabilirsiniz. Yaptığımız örnekte basitçe unit test nasıl yazılır göstermeye çalıştık. Unit test ile ilgili daha fazla bilgiyi burada bulunan linkten bulabilirsiniz. 

Redis Server Windows Üzerinde Kurulumu ve Kullanımı

Bu yazıda Distributed Caching sistemlerinden biri olan Redis'i inceliyor olacağız.

Redis Nedir ?

Redis için kısaca open source bir NOSQL Memcached veritabanı sistemidir diyebiliriz. Her ne kadar ilk olarak Linux için tasarlanmış olsada ihtiyaç doğrultusunda Windows işletim sistemlerinde de kullanılabilir hale getirildi. Çalışma şekli olarak Key-Value şeklinde gönderilen bilgileri store etmektedir. 

 

Veri Tipleri

Redis verileri String, Hashe, List, Set ve Sorted List olarak saklayabilir.

 Veri tipleri ile ilgili daha ayrıntılı bilgiyi bu linkte bulabilirsiniz. 

Kurulum ve Kullanımı

Öncelikle Redis'i indirip service olarak bilgisayarımıza kuruyoruz. Bunun için bu linkten sizin için uygun olan .rar uzantılı sürümü bulup bilgisayarımıza indiriyoruz. Sonrasında indirmiş olduğunuz dosyalardan redis-server.exe adlı exe'yi çalıştırıp kurulumu yapıyoruz. Default olarak 6379 port'unu hizmete sokar ancak istersek bunu değiştirebiliriz de. Exe çalıştıktan sonra aşağıdaki gibi bir ekran gördüyseniz kurulum OK dir.

Redis çalışıp çalışmadığına dair kontrol için redis-cli.exe'yi çalıştıralım ve aşağıdaki resimde olduğu gibi test amaçlı bir key-value tanımlayıp sonrasında get set işlemi yapalım

Bu yazımızda Windows üzerinde Redis Server nasıl kurulur ve kullanılır bunu gördük. Bir sonraki Redis yazımızda StackExchange.Redis redis client kullanarak NET dilleri için (C# etc) örnek proje yapıyor olacağız.

Fluent NHibernate Nedir ve Kullanımı

ORM Nedir ?

ORM (object relational mappers) uygulamalarınızda CRUD (Create, Read, Update, and Delete) işlemleri için basit bir şekilde data'ya erişimlerimizi sağlayan yapılardır. Çeşitli ORM framework'leri uzun zamandan beri data-model arasındaki veri alış verişini sağlamak için kullanılmakta ve ORM ler sql scriptleri execute etmeden CRUD işlemlerini doğrudan yapabilmemiz için kod yazmamıza olanak sağlarlar. Özetle, ORM kullanarak uygulamalarımızdaki data-model ilişkisini(database modellemesini) object-model ilişkisine dönüştürebiliriz.

Neden Fluent NHibernate ?

Klasık NHinernate, database de bulunan her bir tablo için class mapping bilgilerini .hbm uzantılı  XML formatındaki dosyalarda saklıyordu ve aslına bakılırsa biraz zahmetli bir işlemdi. Fluent NHibernate'de ise artık .hbm uzantılı mapping bilgilerini içeren XML formatındaki dosyalar kaldırıldı ve bu işlem code-behind'a taşındı ve diğer ORM'lere göre daha hızlı olduğu kabul edilir.

Kısaca özelliklerini sıralamak gerekirse;

  • Easy data-access and data-mapping,
  • Compile-time name- and type-safety,
  • IntelliSense to show you which fluent methods are available at any point,
  • Automapper impl.

Fluent NHibernate ile kolayca Linq sorguları yapabilir ve böylelikle Fluent bir Api oluşturmada kullanabiliriz. Şimdi ise projemize nasıl Fluent NHibernate entegre edip geliştirme yapabiliriz bunu incelicez.

Fluent NHibernate Kurulum

İlk olarak Visual Studio üzerinde yeni bir Console Application projesi açalım. Daha sonra Nuget üzerinden Fluent NHibernate referanslarını projemize indirip kuralım. Install-Package FluentNHibernate

Database Tablo Oluşturulması

Fluent NHibernate kullanabilmek için öncelikle bir database'e ihtiyacımız var. SQL üzerinde FNH_Db adında adında bir database'imiz olsun ve bu db'ye ait aşağıda bulunduğu gibi User adında bir tablo oluşturalım.

CREATE TABLE dbo.Users  
(
    Id int PRIMARY KEY NOT NULL,  
    Name varchar(25) NOT NULL,  
    SurName varchar(25) NOT NULL
)  

User Tablosuna Karşılık Gelen User.cs Oluşturulması

Yukarıda tanımlamış olduğumuz User tablosuna karşılık gelen User.cs aşağıdaki gibi oluşturuyoruz.

public class User
   {
       public virtual int Id { get; set; }
       public virtual string Name { get; set; }
       public virtual string SurName { get; set; }
   }

Mapping Class'ının Oluşturulması

Database tablomuz ve buna karşılık gelen class'ımız hazır ancak halen User objesinde bulunan hangi alan tabloda bulunan hangi alana karşılık geliyor bunu belirtmedik. Bunun için Fluent NHibernate'e ait olan ClassMap adında bir class bulunmakta ve gerekli mapping işlemlerini yapacağımız class ClassMap<T>'den inherit olmuş şekilde oluşturulacak. Burda ki T bizim User class'ımız oluyor.

UserMap.cs adındaki mapping class'ı aşağıdaki gibi olacak şekilde tanımlıyoruz.

   public class UserMap : ClassMap<User>
   {
       public UserMap()
       {
           Id(x => x.Id);
           Map(x => x.Name);
           Map(x => x.SurName);
           Table("User");
       }
   }

DB Connection Sağlanması

Şimdiki işlem ise Fluent Nhibernate kullanarak yukarıda tanımlamış olduğumuz FNH_Db isimli database'e bağlanmak. Bunun için OpenSession adında bir metot oluşturalım.

       public static ISession OpenSession()
       {
           string connectionString = "FNH_Db conn string";
           var sessionFactory = Fluently.Configure()
               .Database(MsSqlConfiguration.MsSql2012
                .ConnectionString(connectionString).ShowSql()
               )
               .Mappings(m =>m.FluentMappings.AddFromAssemblyOf<User>())
               .ExposeConfiguration(cfg => new SchemaExport(cfg)
               .Create(false, false))
               .BuildSessionFactory();
           return sessionFactory.OpenSession();
       }

Tablo'da Bulunan Verileri Alma

Aşağıda yer alan kod bloğu ise db de bulunan tablodaki verileri query etmemizi sağlar.

using (var session = OpenSession())
     {
          var users = session.Query<User>().ToList();
     }

Yukarıda bulunan geliştirmeleri yaptığınızda db bulunan bir proje geliştirmede basitçe connection sağlayarak data-model ilişkisini kurabilirsiniz.  

Not: Yazıyı basit tutmak adına herhangi bir design pattern den bahsetmedim ancak Db olan yerde Crud işlemleri vardır, Crud olan yerde Ado.Net veya ORM vardır, ORM varsa Fluent NHibernate vardır ve Fluent NHibernate de Repository Design Pattern ile birlikte fıstıklı baklava gibi gider :) 

Fluent NHibernate ile ilgili daha detaylı bilgi almak ve geliştirmeleri takip edebilmek için bu linke göz atabilirsiniz.