Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Saturday, October 7, 2017

ProjectBase ile Veri Tabanı İşlemleri (Transaction Örneği)

"ProjectBase" kütüphanesi otomatik transaction yönetimi ve connection yönetimi yapmaktadır. Veritabanı erişim sınıfları 3 modda çalışmaktadır. Bunlar:

* AutoConnectionManagement
* ManuelConnectionManagement
* TransactionMode

Veri tabanı erişim sınıfları ön tanımlı olarak "AutoConnectionManagement" modda çalışmaktadır. Bu modda klasik olarak her işlemde bağlantı açılıp işlem sonlandığında bağlantı kapatılmaktadır. Bu yöntem sıralı işlemlerde yavaş çalıştığından "ManuelConnectionManagement" modunda bağlantının ne zaman açılıp kapanacağı yazılımcı tarafından yönetilerek performans kazanımı yapılabilmektedir. TransactionMode ise PL/SQL tipinde kod yazımı için geliştirilmiştir.

Aşağıdaki örnekte TransactionMode kullanılarak nasıl işlem yapılacağı gösterilmiştir:

using (IDatabase2 db = DatabaseFactory.GetDbObject(DbSettings.TransactionMode))
{
    //salary = 24000

    db.ExecuteQuery("update employees set salary = 3000 where employee_id = 100 ");
    db.Commit();

    //salary = 3000 oldu

    db.ExecuteQuery("update employees set salary = 5000 where employee_id = 100 ");
    db.Commit();

    //salary = 5000 oldu

    db.ExecuteQuery("update employees set salary = 6000 where employee_id = 100 ");
    db.ExecuteQuery("update employees set manager_id = 101 where employee_id = 100 ");
    db.Commit();

    //salary = 6000 ve manager 101 oldu

    db.ExecuteQuery("update employees set salary = 10000 where employee_id = 100 ");
    db.ExecuteQuery("update employees set manager_id = null where employee_id = 100 ");
    db.RollBack();

    //salary = 6000 ve manager 101 kaldı

    db.ExecuteQuery("update employees set salary = 24000 where employee_id = 100 ");
    db.ExecuteQuery("update employees set manager_id = null where employee_id = 100 ");
    db.Commit();

    //salary = 24000 ve manager null oldu

    db.ExecuteQuery("update employees set salary = 50000 where employee_id = 100 ");

    throw new Exception("Fatal Error!");

    //Son işlem geri alındı.
}

Yukarıda görüldüğü gibi veri tabanı erişim sınıfı  transaction yönetimini otomatik olarak gerçekleştirdi. Yani yukarıdaki kod incelendiğinde 6 tane transaction otomatik olarak oluşturulmuş ve işlenmiştir. Veri tabanı erişim sınıfı ön tanımlı olarak hata olması durumunda rollback yapmaktadır. Bu yüzden son işlem geri alınmıştır.

"Bu yazıda "Oracle Managed Provider", Oracle 11g Express Edition ve HR şeması test verileri kullanılmıştır."

"https://github.com/vyigity/ProjectBase"

Veri Erişim Katmanına Giriş - Introduction to DAL (Data Access Layer)

Günümüzde yazılım projelerinde katmanlı mimari en önemli özelliklerden biridir. Katmanlı mimaride bir katman istenildiğinde başka bir projede aynen kullanılabilmekte böylece kod tekrarı azaltılmakta ve güvenilirlik büyük ölçüde artırılmaktadır.

Bir çok yazılım projesinin en önemli parçalarından biri veri erişim katmanıdır çünkü bu katman aracılığı ile veri tabanı işlemleri yürütülür. Bu yazıda kendi yazdığım "ProjectBase" (PB) isimli DAL katmanına giriş yapacağım. Proje kodlarına buradan ulaşabilirsiniz.

DAL katmanı için en önemli noktalar  tutarlılık, güvenilirlik, çok biçimlilik (Polimorfizm) ve genişletilebilirliktir. PB kütüphanesi çok biçimlilik ve genişletilebilirlik için "Interface" tabanlı bir yapıda oluşturulmuştur. PB kütüphanesi ile iş katmanında yazılan kodlarda değişiklik yapılmadan veri tabanı değişikliği kolaylıkla yapılabilmektedir. Ayrıca PB içinde tanımlı interface kullanılması ile istenildiği kadar "provider" sınıf yazılabilir ve bu sınıflar özelleştirilebilir.

Şimdi PB ile veri okuma işlemi yapalım:

* Veri tabanı olarak Oracle 11g Express Edition kullanacağım.  Veri tabanını Oracle'ın resmi sitesinden ücretsiz olarak indirebilirsiniz.

* Provider olarak Oracle "ManagedDataAccess" kullanacağım.

Veri tabanı kurulumunu yaptıktan sonra web.config içerisinde bağlantı stringi aşağıdaki gibi tanımlanmalıdır.

<connectionStrings>
      
    <add name="Context" connectionString="DATA SOURCE=XE;PASSWORD=hr;USER ID=hr" providerName="Oracle.ManagedDataAccess.Client" />
    
</connectionStrings>

Burada providerName önemlidir. Erişim sınıfları burada yazan provider bilgisine göre ilgili sınıfları seçecektir.

DAL katmanının kurulumu için "ProjectBase" kütüphanesini indirip projeye eklemek kurulum için yeterlidir.

using (IDatabase2 db = DatabaseFactory.GetDbObject())
{
    var dt = db.ExecuteQueryDataTable("select * from employees");
}

Yukarıdaki kod bloğu ile "Employees" tablosunda yer alan bütün veriler çekilip "DataTable" nesnesi olarak döndürülmektedir. Oracle veri tabanı içinde "HR" şemasında test için küçük bir veri tabanı servis edilmektedir. "Employees" tablosu bu veri tabanının içindedir.

ProjectBase kütüphanesi Oracle ve SQL veri tabanlarını ve OleDb erişimini desteklemektedir.

Tuesday, March 29, 2016

Angularjs ve ASP.NET MVC ile Javascript Diziler Kullanılarak Dinamik Çoklu Veri Gönderimi - Sending Dynamic Multi Post Data Using Javascript Arrays With Angularjs and ASP.NET MVC

Bu yazıda ASP.NET MVC üzerinde angularjs kullanılarak kullanıcıdan alınan çoklu veri girişlerinin bir dizi içinde tutularak AJAX ile sunucuya gönderilmesi ve sunucuda işlenmesi sağlanacaktır. Bu amaçla oluşturacağımız giriş kontrolünün CSS kodlarını tanımlayalım.

<style>

    .mainContainerAngularExample {

        width:300px;
        margin:10px;
    }

    .detailAngularExample {

        margin-top:10px;
    }

    .detailAngularExample input:focus {

        background-color:lightblue;
    }

    .footerAngularExample {

        margin-top:10px;
        text-align:right;
    }

    .arrayContainerAngularExample {

        margin-top:10px;
        color:coral    
    }

</style>

Sonraki aşamada DOM elementleri ve veri katmanı arasındaki bağlantıyı tanımlamak için angularjs kodlarını yazalım. Aşağıdaki kodlarda "myApp" modulü altında "MainCtrl" kontrolcüsü tanımlanmaktadır. Scope (Kapsam) içinde yer alan "addItem" fonksiyonu ile diziye elemen eklenmekte ve "removeItem" ile diziden eleman silinmektedir. Bu amaçla diziler üzerinde tanımlı "splice" fonksiyonu kullanılmıştır. Scope içinde yer alan "id" değişkeni ile dizi elemanlarının isimlendirilmesi yapılmaktadır. Ayrıca eğer gerekli olursa (dizi içinde yer alan elemanların tekrar ekmesi durumunda) "id" eşsiz anahtar olarak da kullanılabilir. Burada en önemli nokda dizi içinde nesne(object) kullanılmasıdır. "np-repeat" işlemi gerçekleştirirken kendi scope (kavramı) nesnesini yaratmaktadır. Bu sırada javascript prototype yapısından dolayı "primitive (ilkel)" değişkenlerin değeri programlama dillerindeki fonksiyonlara parametre gönderilirken ki durumla benzer olarak kopyalanmaktadır. Bu sebeple dizi içindeki değişikliğin "parentScope" üzerinde geçerli olabilmesi için dizi içinde referans olarak JSON nesnesi kullanılmıştır.

var app = angular.module('myApp', []);

app.controller('MainCtrl', ['$scope','$http',function ($scope, $http) {

    $scope.pages = [
        { val: 'Item 1' }
    ];

    $scope.id = 1;

    $scope.addItem = function (index) {

        $scope.id++;
        $scope.pages.splice(index + 1, 0, { val: 'Item ' + $scope.id });
    }

    $scope.removeItem = function (index) {

        if (index != 0)
            $scope.pages.splice(index, 1);
    }

    $scope.saveData = function () {

        $http.post("./Home/SaveData", $scope.pages).success(function () {

            alert("Veriler Başarıyla Kaydedildi.");

        }).error(function () {
            
            alert("Veriler Kaydedilirken Bir Hata Oluştu!");
        });
    }
}]);

Sonraki aşamada HTML kodlarını tanımlayalım. Aşağıdaki kodlarda "ng-model" niteliği kullanılarak giriş elementiyle dizi elemanı arasındaki ilişki tanımlanmıştır. "ng-click" kullanılarak kontrolcü içinde yer alan ilgili fonksiyonların tıklanma durumunda çalıştırılması sağlanmaktadır. "ng-hide" ile ilk elemandaki sil tuşunun görünmemesi sağlanmaktadır. "saveData" fonksiyonu kullanılarak üzerinde çalıştığımız dizi AJAX POST isteğiyle sunucuya gönderilmektedir.

<div class="mainContainerAngularExample" ng-app="myApp" ng-controller="MainCtrl">
<div class="detailAngularExample" ng-repeat="page in pages">
<input ng-model="page.val" type="text" />
        <button class="btn btn-default btn-xs" ng-click="addItem($index)" type="button"><span class="glyphicon glyphicon-plus"></span>EKLE</button>
        <button class="btn btn-default btn-xs" ng-click="removeItem($index)" ng-hide="$index === 0" type="button"><span class="glyphicon glyphicon-minus"></span>SİL</button>
    </div>
<div class="footerAngularExample">
<button class="btn btn-success" ng-click="saveData()" type="button"><span class="glyphicon glyphicon-save"></span>KAYDET</button>
    </div>
<div class="arrayContainerAngularExample">
CurrentArray = {{pages}}
    </div>
</div>

Sunucu tarafında "postTemplate" ile gelen verinin bağlanacağı yapı tanımlanmaktadır. Son olarak "SaveData" fonksiyonu ile aşağıdaki gibi AJAX ile gönderilen dizi işlenebilmektedir.

public struct postTemplate
{
     public string val { get; set; }
}

[HttpPost]
public ActionResult SaveData(List<postTemplate> Datas)
{
    return Json("OK");
}

Yukarıdaki kodların çalıştırılması sonucunda aşağıdaki sonuç elde edilmektedir:

CurrentArray = {{pages}}

Friday, March 25, 2016

C# ile Zip Formatında Dosya Sıkıştırma - Zip Formatted File Compression with C#

Bu yazıda .NET framework 4.5 ve üzeri için nasıl zip sıkıştırması yapılacağı anlatılacaktır. Bu yazı kapsamında zip dosyasının içinde yer alan sıkıştırılacak dosya ve zip dosyası hafızada oluşturulacaktır. Elde edilen byte dizisi "File" sınıfı kullanılarak dosya sistemine yazılacaktır. Örnek olarak bir text dosyası oluşturulacak ve bu dosya ziplenecektir.

Zip dosyasının oluşturulması için "ZipArchive" sınıfı kullanılacaktır. Bu sınıfın kullanılabilmesi için  "System.IO.Compression" ve "System.IO.Compression.FileSystem" dll dosyalarına referans verilmelidir. Ayrıca "System.IO.Compression" dll dosyasının versiyonunun eski olmamasına dikkat edilmelidir. Referanslar eklendikten sonra aşağıdaki tanımlama kod sayfasına eklenmelidir.

using System.IO.Compression;

Text dosyasının oluşturulması amacıyla "StringBuilder" sınıfını kullanarak aşağıdaki gibi yazı içeriği oluşturalım:

StringBuilder builder = new StringBuilder();  
builder.AppendLine("Veli");
builder.AppendLine("Yigit");
builder.AppendLine("Yolcu");

Aşağıda yer alan ZipThat fonksiyonuyla zip dosyasının byte dizisi elde edilmektedir. Fonksiyon kullanılarak bir zip arşivi oluşturulmakta ve daha önce hazırladığımız yazı içeriği "ZipArchiveEntry" olarak zip arşivine eklenmektedir. Bu fonksiyon zip verisini "MemoryStream" içinde biriktirmekte ve işlem tamamlandığında sıkıştırılmış içeriği byte dizisi olarak döndürmektedir.

byte[] ZipThat(string FileName, byte[] TxtData)
{
    using (MemoryStream mst = new MemoryStream())
    {
        using (ZipArchive arc = new ZipArchive(mst, ZipArchiveMode.Create))
        {
            var zipEntry = arc.CreateEntry(FileName);

            using (Stream st = zipEntry.Open())
            {
                st.Write(TxtData, 0, TxtData.Length);
            }
        }

        return mst.ToArray();
    }
}

"Encoding" sınıfı kullanılarak StringBuilder" içinde yer alan yazının byte dizisi elde edilebilmektedir:

byte[] txtData = Encoding.Default.GetBytes(builder.ToString());

Son olarak oluşturulan zip verisi "File" sınıfı kullanılarak dosya sistemine yazılmaktadır.

File.WriteAllBytes(string.Format(@"C:\Deneme\{0}.zip", "ZipFile"), ZipThat("FileThatInZipArchive.txt"));

Sunday, March 20, 2016

Angularjs ve ASP.NET MVC ile Döviz Kurları Uygulaması - Exchange Rates Application With Angularjs and ASP.NET MVC

Bu yazıda TCMB (Türkiye Cumhuriyeti Merkez Bankası) tarafından yayınlanan ve kur bilgilerini içeren XML dosyasını kullanarak döviz kurlarını gösteren bir uygulama geliştireceğiz. Bu uygulama içinde gerekli TCMB verileri sunucu üzerinde çekilip AJAX ile tarayıcıya gönderilecektir. Neden direk tarayıcı üzerinden verileri çekmiyoruz diyen arkadaşlar varsa eğer öncelikle "same-origin policy" adı verilen kuralı incelemeleri gerekir. Bu kurala göre bir tarayıcı üzerinden değişik bir kaynaktaki (domaindeki) veriye ulaşım güvenlik endişesiyle engellenmektedir. Bu durum sadece AJAX için değil "iframe" için de geçerlidir.

Öncelikle TCMB kaynağından veriyi alacak sunucu kodunu tanımlayalım:

[HttpGet]
public ActionResult GetData()
{
     XDocument doc = XDocument.Load("http://www.tcmb.gov.tr/kurlar/today.xml");
     var dox = doc.Descendants()
         .Where(r => r.Name == "Currency")
         .Select(r => new {
             Isim = r.Element("Isim").Value,
             Kod = r.Attribute("Kod").Value,
             AlisKur = r.Element("BanknoteBuying").Value,
             SatisKur = r.Element("BanknoteSelling").Value
          });

      return Json(dox, JsonRequestBehavior.AllowGet);
}

Kod yukarıdan aşağıya incelendiğinde öncelikle dikkat çeken nokta [HttpGet] tanımlamasıdır. Bu tanımlama ile "GetData" fonksiyonuna ulaşılırken "Get" isteği kullanılması gerektiği belirtilmektedir. Yani fonksiyon "Post" veya "Delete" isteklerine cevap vermeyecektir.

Bir diğer önemli nokta ise "XDocument" sınıfıdır. Bu sınıf, XML verisini üzerinde LINQ sorgularının çalıştırılmasına olanak sağlayacak bir biçimde kullanmaktadır. Bilindiği üzere aynı işlemi yapan bir diğer sınıf da "XmlDocument" sınıfıdır. Bu sınıf XML verisini eski usül XML DOM olarak kullanmakta ve veri içindeki aramaları "XPath" ile yapmaktadır. LINQ arayüzünün daha basit olması sebebiyle bu uygulamada "XDocument" sınıfını kullandım.

Son aşamada "Json" fonksiyonu kullanılarak bir önceki LINQ işleminden dönen ön tanımsız nesneler JSON formatına dönüştürülüp istemciye gönderilmektedir. "JsonRequestBehavior.AllowGet" kullanılarak fonksiyonun "GET" isteklerine müsaade etmesi sağlanmıştır. Aksi durumda dönüşümü yapmayacaktır.

Sonraki aşamada AngularJs kodlarını tanımlayalım:

var currencyapp = angular.module('currencyapp', []);

currencyapp.controller('currencyListController', ['$scope', '$http',

  function ($scope, $http) {

      $http.get('./Home/GetData').success(function (data) {
          $scope.kurs = data;
      });

  }]);

Yukarıdaki kodlarda öncelikle "root scope" yani genel tanımlama amacıyla "currencyapp" modülü tanımlanmaktadır. Bu modülün altında "currencyListController" adında "$scope" ve "$http" servislerine bağımlı bir kontrolcü tanımlanmaktadır. Bu nesne aracılığıyla AJAX sorgusu gerçekleştirilmekte ve döviz verisi kapsam (scope) içine alınmaktadır. AJAX işlemi için "$http" servisinin "get()" fonksiyonu kullanılmaktadır.

AngularJs ile veri modeli oluşturduktan sonra son olarak bunu görüntü (View) ile ilişkilendirelim:

<div ng-app="currencyapp">
    <table ng-controller="currencyListController" class="table table-striped table-condensed">

        <thead>
            <tr>
                <th>Döviz Adı</th>
                <th>Döviz Kodu</th>
                <th>Alış</th>
                <th>Satış</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="kur in kurs">
                <td>{{kur.Isim}}</td>
                <td>{{kur.Kod}}</td>
                <td>{{kur.AlisKur}}</td>
                <td>{{kur.SatisKur}}</td>
            </tr>
    </table>
</div>

Burada "ng-app" niteliği ile ilgili DOM nesnesinin altında yer alan ögelerin "currencyapp" uygulamasına dahil olduğu belirtilmektedir. "Table" nesnesi "ng-controller" niteliği ile "currencyListController" kontrolcüsü ile ilişkilendirilmektedir. Bu kontrolcünün kapsamı dahilinde yer alan "kurs" listesinin içindeki "kur" JSON nesneleri kullanılarak tablo oluşturulmaktadır. "{{kur.Isim}}" tanımlaması ile kur nesnesinin "Isim" değeri ilgili tablo kısmına yazılmaktadır. "tr" etiketinde "ng-repeat" niteliği kullanılarak ilgili listedeki tüm nesneler için tablo satırlarının oluşturulması sağlanmaktadır. Yani listede yer alan her bir nesne için bir tablo satırı oluşturulmaktadır.

Uygulama sonunda aşağıda gösterilen tablo elde edilmektedir:




Friday, February 19, 2016

Yazı İçinde Yer Alan Türkçe Karakterlerin İngilizce Karakterlere Dönüştürülmesi

Bazı ingilizce kökenli uygulamalarda kullanıcı ismi vb. bilgiler ingilizce karakter kullanılarak oluşturulmaktadır. Örneğin isim kısaltması yapılacaksa Adnan Göktürk olan bir kişinin kullanıcı kodu A-GOKTURK olarak kullanılabilmektedir. Bu ve benzeri durumlarda giriş verisi içinde yer alan tükçe karakterler ingilizce karşılıkları ile değiştirilmesi gerekir. Bu gereksinimi karşılayan C# kodu aşağıdadır.

IsNull fonksiyonu parametrenin null veya DBNull olup olmadığını kontrol etmektedir.
        
public static string GetEnglishLocalizedString(string SearchString)
{
if (!IsNull(SearchString))
{
char[] turkishChars = { 'ı', 'ğ', 'İ', 'Ğ', 'ç', 'Ç', 'ş', 'Ş', 'ö', 'Ö', 'ü', 'Ü' };
char[] englishChars = { 'i', 'g', 'I', 'G', 'c', 'C', 's', 'S', 'o', 'O', 'u', 'U' };
for (int i = 0; i < turkishChars.Length; i++)
{
SearchString = SearchString.Replace(turkishChars[i], englishChars[i]);
}
return SearchString;
}
else
return null;
}

Düzenli İfadeleri Kullanarak Karakter Dizisi İçindeki Örüntüleri Bulma - Finding Patterns in Strings with Using Regular Expressions

Regex (Regular Expression) bir karakterler dizisi içinde düzenli bir parçayı bulmak için kullanılan bir yöntemdir. Düzenli yapının ifadesi Regex tanımlama kuralları kullanarak tanımlanır ve string içindeki bu kurala uyan kısımlar ayrıştırılıp elde edilebilir. Örnek olarak karmaşık bir string içinde yer alan tarih kısmını bulalım:

* Bulmak istediğimiz tarih formatı:

19.02.2016

* Örüntüyü ifade eden RexExp :

(0[1-9]|[12][0-9]|3[01]|[1-9])[- /.](0[1-9]|1[012]|[1-9])[- /.](19|2)\d\d\d

* Test Verisi 1:

dafffas1319.02.2016daq12341515

* Test Verisi 2:

-*daf/fa.*19.2.20169a1341qwca12.1.1

* Çalıştıracağımız C# kodu:

public static DateTime? findDateInString(string SearchString)
{
Regex ex = new Regex(DateInStringRegEx);
var match = ex.Matches(SearchString);
if (match.Count > 0)
return DateTime.Parse(match[0].Value);
else
return null;
}

SONUÇLAR:

* Sonuç 1 (Test Verisi 1):

19.02.2016

* Sonuç 2 (Test Verisi 2):

19.02.2016



Wednesday, February 17, 2016

GUID (Evrensel Eşsiz Tanımlayıcı Nedir) - What is GUID (Globally Unique Identifier) or UUID (Universally Unique Identifier)?

GUID (Globally Unique Identifier) X.667 dökümanında tanımlı, genellikle nesneler için eşsiz tanımlayıcılar kullanılması gerektiği durumlarda tanımlayıcı olarak kullanılan ikili bir sayıdır. UUID (Universally Unique Identifier) ve GUID aynı şeyi ifade etmektedir.

Otomatik artırılan sayılar tablo içinde PK (Primary Key) olarak kullanıldığında tablo içindeki eşsizliği garanti ederken tablolar arasındaki eşsizliği sağlayamaz. Yani 1 değeri Personel tablosunda Ali'yi tanımlarken aynı 1 değeri Şehir tablosunda Ankara'yı belirtebilir. Ayrıca otomatik sayıların kullanılması bir yönetim maliyeti ortaya çıkarır.

GUID'ler yapısı gereği teoride genel olarak eşsizlik sunarlar. Yani bir veritabanı nesnesine atanan GUID sadece o nesnenin tanımlayıcısı olmakta ve veri tabanında başka bir eşi olmamaktadır. Bu durum insanlardaki parmak izinin sağladığı eşsizlikle de benzerdir.

GUID 128 bit (16 oktet - 16 byte) ikili bir sayı olarak tanımlanmaktadır.  Ayrıca GUID URN (Uniform Resource Name) olarak hexadecimal formatta string olarak da aşağıdaki gibi ifade edilebilmektedir.

f81d4fae-7dec-11d0-a765-00a0c91e6bf6

GUID tanımı hexadecimal sayılardan oluştuğu için sadece aşağıdaki karakterleri içerebilmektedir:

A B C D E F a b c d e f 0 1 2 3 4 5 6 7 8 9

GUID aşağıdaki alanlardan oluşmaktadır:

a) "TimeLow" Alanı: 4 oktet;
b) "TimeMid" Alanı: 2 oktet;
c) "VersionAndTimeHigh" Alanı: 2 oktet;
d) "VariantAndClockSeqHigh" Alanı: 2 oktet;
e) "ClockSeqLow" Alanı: 1 oktet;
f) "Node" Alanı: 6 oktet.

Bu alanlar GUID oluşturulurken GUID içinde aşağıda gösterilen formatta yerleştirilmektedir.

 

Node alanı görüldüğü üzere 6 sekizliden yani 48 bitten oluşmaktadır. Genellikle Node olarak MAC (Media Access Control) adresi kullanılmaktadır. Bilindiği üzere MAC adresleri teoride Dünya geneli eşsizlik sağlamaktadır. Genel eşsizlik MAC üzerinden sağlanırken aynı makinenin oluşturduğu sayılar arasındaki eşsizlik ise zaman ve ClockSeq alanları kullanılarak sağlanmaktadır.

GUID içinde yer alan zaman alanı bir başlangıç noktasından itibaren (15 Ekim 1582) 100 nanosaniye aralıklı sayılan şimdiki zamanı ifade etmektedir. Bu değer .NET framework içince "Tick" olarak adlandırılmaktadır.

ClockSeq alanı GUID'lerin birbiriyle çok yakın zamanda oluşturulması, makine zamanının geriye alınması veya node değerinin değişmesi durumunda eşsizliğin sürdürülebilmesi amacıyla kullanılmaktadır. Bu değer eğer makine içinde sıralı tutuluyorsa sıradaki sayı, eğer tutulmuyorsa rastgele bir sayı olarak kullanılabilmektedir.

Versiyon alanı GUID çeşidini belirtmektedir. GUID'ler aşağıdaki versiyonlarda olabilmektedir.

* Zaman Tabanlı
* İsim Tabanlı
* Rastgele Sayı Tabanlı

GUID alanlarının hangi oktetlerde olduğu aşağıdaki tabloda gösterilmektedir:




C# kullanılarak GUID'ler aşağıdaki kod ile oluşturulabilmektedir:

Guid g = Guid.NewGuid()

Monday, February 1, 2016

Entity Framework CRUD İşlemleri - CRUD with Entity Framework

Bir yazılımın en önemli kısımlarından biri CRUD (Create, Read, Update, Delete) işlemleridir. CRUD işlemlerinin kalitesi veri kalitesine doğrudan etki eder. Bu yüzden CRUD uygulamaları özentili ve sert protokolle oluşturulmalıdır. Bu yazıda EF ile ilgili fonksiyonların nasıl olması gerektiği anlatılmıştır. Bu fonksiyonlar şunlardır:

public MyObject SelectObj(Decimal? ID)
     {
         if (ID != null)
         {
             DataBaseContext con = new DataBaseContext();
             return con.MyObjects.Include(r => r.MyObjectRelation).Single(r => r.ID == ID);
         }
         else
             return new MyObject();
     }

     public void InsertObj(MyObject Obj)
     {
         DataBaseContext con = new DataBaseContext();
         var a = con.MyObjects.Attach(Obj);
         con.Entry(a).State = EntityState.Added;
         con.SaveChanges();

     }

     public void UpdateObj(MyObject Obj)
     {
         DataBaseContext con = new DataBaseContext();
         var a = con.MyObjects.Attach(Obj);
         con.Entry(a).State = EntityState.Modified;
         con.SaveChanges();

     }

     public void DeleteObj(MyObject Obj)
     {
         DataBaseContext con = new DataBaseContext();
         var a = con.MyObjects.Attach(Obj);
         con.Entry(a).State = EntityState.Deleted;
         con.SaveChanges();
     }

Burada dikkat edilmesi gereken bir unsur ilişkili tablonun verilerinin "eargerly loading" yaklaşımıyla yapılmasıdır. Bunun direk olarak CRUD kalitesine etkisi olmamakta birlikte tarafımca performans kaygısı sebebiyle bu yöntem kullanılmaktadır.

Aşağıdaki kod satırları nesne durumunu EF'ye tanıtmaktadır.

con.Entry(a).State = EntityState.Added;
con.Entry(a).State = EntityState.Modified;
con.Entry(a).State = EntityState.Deleted;

Bu satırlardan Added nesnenin yeni eklendiğini belirtmekte ve INSERT DML (Data Manipulation Language) komutunu ima etmekte, Modified nesnenin güncellendiğini ve UPDATE DML komutunu ima etmekte, Deleted ise nesnenin silindiğini ve DELETE DML komutunu ima etmektedir.

Direk nesne üzerinden yapılan durum belirtimleri nesnenin tüm propertyleri için geçerlidir. Örneğin Modified durumu sonucu oluşan SQL (Structured Query Language) tüm property'leri içerecektir. Eğer ilgili nesnenin belirli property'leri güncellenmek isteniyorsa aşağıdaki kod satırı kullanılmalıdır:

con.Entry(a).Property(r => r.MyProperty).EntityEntry.State = EntityState.Modified;

veya

con.Entry(a).Property(r => r.MyProperty).IsModified = true;

Burada MyProperty güncellenmiş olarak işaretlenmiş ve güncellemede sadece gösterilen property dikkate alınacaktır. 

Bir diğer husus ise "using" kullanımıdır. "Context" nesneleri yüksek maliyetli nesneler oldukları için kaynakların çabuk bırakılması yararlı olacaktır. Bu yüzden "Context" nesnelerinin "using" bloğu kullanılarak kullanılması yararlı olacaktır.

Son olarak yukarıdaki işlemlerde nesne tanımlayıcısının yani "primary key" alanlarının kesinlikle tam olması şarttır.



Friday, January 15, 2016

Metot İptal Etme (Overriding) vs Metot Gizleme - Method Overriding vs Method Hiding

Metot iptal etme veya üzerinde yazma kalıtım bırakmada bir metodun daha gelişmiş özelliklerle genişletilmesi gerektiğinde kullanılır. Metot gizleme ise iptal etmeye müsait olmayan bir metot türetilen sınıfta aynı isimde tanımlandığında devreye girer. "new" anahtar kelimesi kullanılarak gizleme yapıldığına kesinlik kazandırılabilir. Gizleme yapıldığı konusunda kesinlik kazandırılmaz ise gizleme geçerlidir fakat derleyici tarafından uyarı yapılır. Aşağıdaki Class2 sınıfı Class1 sınıfından türemiştir. "getName" metodu türetilen sınıfta iptal edilmiştir.

public class Class1
    {
        public Class1() { }

        public virtual void getName()
        {
            Console.WriteLine("Class1");
        }

    }

    public class Class2 : Class1
    {
        public Class2() { }

        public override void getName()
        {
            Console.WriteLine("Class2");
        }
    }

Bu sınıflar aşağıdaki kod ile çağrıldığında şu sonuçlar elde edilmiştir:

Class1
Class2
Class2
 
    class Program
    {
        static void Main(string[] args)
        {
            Class1 c1 = new Class1();
            c1.getName();

            Class1 c2 = new Class2();
            c2.getName();

            Class2 c3 = new Class2();
            c3.getName();

            Console.ReadLine();
        }
    }

Görüldüğü üzere ilk c1 nesnesi hafıza alanında Class1 sınıfı referans alınarak oluşturulduğu için iptal etme işlemi uygulanması. Fakat diğer ikisinde Class2 nesnesi referans alınarak oluşturulduğu için iptal etme işlemi geçerli oldu.

Bazı durumlarda, özellikle de ebeveyn sınıfının eski versiyonunun kaybedilmesinin istenmediği durumlarda gizleme kullanılabilir.

public class Class1
    {
        public Class1() { }

        public void getName()
        {
            Console.WriteLine("Class1");
        }

    }

    public class Class2 : Class1
    {
        public Class2() { }

        public new void getName()
        {
            Console.WriteLine("Class2");
        }
    }

Main metodu tekrar çalıştırıldığında aşağıdaki sonuçlar elde edilir:

Class1
Class1
Class2

Sonuçtan da anlaşılabileceği gibi iptal etme işlemi artık geçerli olmadığı için c2 nesnesi üzerinde Class1 tipindeki referans değişkeni üzerinden erişim yapıldığında Class1 üzerindeki fonksiyon kullanılmıştır.






Wednesday, January 13, 2016

Sealed (Mühürlü) Başvurusu - Sealed Keyword

Sealed başvurusu isminden de anlaşılabileceği bir ögenin mühürlendiğini yani herhangi bir değişikliğe maruz kalamayacağını belirtir. Sealed kullanılan sınıftan başka bir sınıf türetilemez veya sealed kullanılan virtual (sanal) bir metot override (üstüne yazma) edilemez. Örnek kullanımı şöyledir:

public sealed class A {}

C# Erişim Belirliyecileri - C# Access Modifiers

Nesne yönelimli programlama (NYP)'de öz-kapsülleme (encapsulation) yapılabilmesini sağlayan araçlardır. Bu araçlar kullanılarak duruma göre ögeler gizlenebilir veya dışarı sunulabilir. Erişim belirliyecileri şunlardır:

1. Public: Ögenin erişimine herhangi bir kısıt getirilmeyeceği zaman kullanılır.

2. Private: Ögeye dışardan erişimin engelleneyeceği zaman kullanılır. C#'da eğer öge hakkında bir erişim değiştiricisi tanımlanmazsa default olarak öğenin erişim değiştiricisi private kabul edilir.

3. Protected: Ögenin erişiminin aynı sınıf içindeki diğer ögelere ve ögenin içinde bulunduğu sınıftan türeyen diğer sınıf ögelerine açık olması gerektiği zaman kullanılır.

4. Internal: Ögenin erişiminin sadece aynı Assembly içinde bulunduğu diğer ögelere açık olması gerektiğinde kullanılır.

Örnek kullanımları şunlardır:

public int variable1;
private double variable2;
protected string variable3;


Monday, January 11, 2016

ASP.NET Uygulamalarından Elektronik Posta Göndermek - Sending E-Mail from ASP.NET Applications

Müşteri ihtiyaçlarına göre bazı durumlarda uygulamadan e-posta gönderilmesi gerekebilmektedir.Bu durumda .NET üzerinde tanımlı "System.Net.Mail" ad alanı içindeki "SmtpClient" sınıfı kullanılarak e-posta gönderilebilmektedir. Örnek olarak aşağıdaki kod bloğu verilebilir:

MailMessage mail = new MailMessage(pfrom, pto);
mail.IsBodyHtml = IsHtmlBody;

mail.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;

SmtpClient client = new SmtpClient();
client.Credentials = new NetworkCredential(UserName, Password);
client.Port = Port;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Host = Host;
mail.Subject = psubject;
mail.Body = pmessage;
client.Send(mail);

Eğer e-posta bir HTML mesajı içeriyorsa MailMessage nesnesinin IsBodyHtml özelliği "true" yapılmalıdır.

Bunun dışında bazen eski e-posta sunucuları kullanılarak e-posta gönderilirken yukarıda kullanılan "System.Net.Mail" ad alanını içindeki sınıf sıkıntı çıkarabilmektedir. Bu durumda "System.Web.Mail" içinde yer alan SmtpMail sınıfı kullanılarak e-posta gönderim işlemi yapılabilmektedir. Aşağıda bu durum için örnek kod bloğu verilmiştir:

MailMessage mail = new MailMessage();
mail.To = pto;
mail.From = pfrom;
mail.Subject = psubject;
mail.Body = pmessage;

mail.Subject = psubject;
mail.Body = pmessage;

SetMailConfiguration(mail);

SmtpMail.Send(mail); 

Bu yöntem kullanıldığında doğrulama (Authentication) bilgisi aşağıdaki şekilde eklenmelidir:

mail.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", "1"); //basic authentication
mail.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", UserName); //set your username here
mail.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", Password); //set your password here

Eğer mesaj HTML içeriyorsa ayarlamalara aşağıdaki kod eklenmelidir:

mail.BodyFormat = MailFormat.Html;


C# ile Nesnelerin XML Formatına Dönüştürülmesi - Transform of Objects into XML Coding

Nesneler veri tabanında saklanırken bazı durumlarda insanların anlayabileceği, hatta içerik sorgulayabileceği bir formata çevrilmesi gerekebilir. Bu durumumda "XmlSerializer" sınıfı kullanılarak nesneler XML formatına dönüştürülebilmektedir. Aşağıdaki örnekte "SerializeObjectXml" fonksiyonu kullanılarak nesne XML formatlı string değerine dönüştürülmektedir. "DeSeriliazeObjectXml" fonksiyonu kullanılarak da XML formatından geri dönüş yapılabilmektedir.

 public static string SerializeObjectXml(T Obj)
 {        
      StringWriter swriter = new StringWriter();
      XmlSerializer sxml = new XmlSerializer(typeof(T));
      sxml.Serialize(swriter, Obj);
      return swriter.ToString();
 }

 public static T DeSeriliazeObjectXml(string XmlString)
 {
      XmlSerializer sxml = new XmlSerializer(typeof(T));
      return (T)sxml.Deserialize(new StringReader(XmlString));
 }

C# ile Nesnelerin Serileştirilmesi - Object Serialization

Bazı durumlarda nesnelerin serileştirilip yanı byte dizisi (byte[]) haline getirilip veritabanında saklanması gerekebilmektedir. Bu durumda "BinaryFormatter" sınıfı kullanılarak nesneler serileştirilebilmektedir. Aşağıdaki örnekte "SerializeObjectBinary" fonksiyonu nesneyi serileştirmek için kullanılmakta ve "DeSerializeObjectBinary" fonksiyonu ile nesne tekrar elde edilebilmektedir.

public static byte[] SerializeObjectBinary(object Obj)
{
     MemoryStream stream = new MemoryStream();
     BinaryFormatter formatter = new BinaryFormatter();
     formatter.Serialize(stream, Obj);

     return stream.ToArray();
}

public static object DeSerializeObjectBinary(byte[] ObjBinary)
{
     MemoryStream stream = new MemoryStream();
     stream.Write(ObjBinary, 0, ObjBinary.Length);
     stream.Position = 0;
     BinaryFormatter formatter = new BinaryFormatter();
     return formatter.Deserialize(stream); ;
}


C# Jenerik Fonksiyonlar - C# Generic Functions

Jenerik fonksiyonlar kodlama içinde fonksiyonun tipe göre reaksiyon gösterebilmesini sağlamaktadır. Kavram olarak çok biçimlilik (polymorphism) konusunun örneklerindendir. Aşağıdaki örnek fonksiyonda iki sınıfın ortak "property" değerleri diğerine kopyalanmaktadır ve fonksiyon üzerine kopyalama yapılan nesneyi kendi tipinde döndürmektedir.

public static T CopyObject < T >(object From, T To) where T:class
{
     Type tfrom = From.GetType();
     Type tto = typeof(T);

     foreach (PropertyInfo to_property in tto.GetProperties())
     {
          foreach (PropertyInfo from_property in tfrom.GetProperties())
          {
              if (from_property.Name == to_property.Name)
              {
                  to_property.SetValue(To, from_property.GetValue(From));
                  break;
              }
          }
     }

     return To;          
}

Entity Framework 6 Veri Tabanı Fonksiyonu Haritalama (Önce Kod Örüntüsü) - Entity Framework 6 Database Function Mapping (Code First Pattern)

Entity Framework 6 (EF) ile beraber yeni genel "Conventions" özelliği ile artık "Code First" örüntüsü kullanarak EF meta bilgisine müdahele edilebilmektedir. Aşağıdaki örnekte Oracle içinde yer alan TO_CHAR ve TO_NUMBER fonksiyonları haritalanmıştır.

public class FunctionConvention : IStoreModelConvention
{
        public void Apply(EdmModel item, DbModel model)
        {
            AddToCharFunc(model);
            AddToNumberFunc(model);
        }

        public void AddToCharFunc(DbModel dbModel)
        {
            var edmType = PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String);
            var payload =
                new EdmFunctionPayload
                {
                    Schema = "SYS.STANDARD",
                   
                    ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion,
                    IsComposable = true,
                    IsNiladic = false,
                    IsBuiltIn = true,
                    IsAggregate = false,
                    IsFromProviderManifest = true,
                    StoreFunctionName = "TO_CHAR",
                    ReturnParameters =
                        new[]
                    {
                        FunctionParameter.Create("ReturnType", edmType, ParameterMode.ReturnValue)
                    },
                    Parameters =
                new[]
                {
                    FunctionParameter.Create("Val", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), ParameterMode.In)
                }
                };

            var function = EdmFunction.Create("TO_CHAR", "EntityLayer.Utility", DataSpace.SSpace, payload, null);
            dbModel.StoreModel.AddItem(function);
        }

        public void AddToNumberFunc(DbModel dbModel)
        {
            var edmType = PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Decimal);
            var payload =
                new EdmFunctionPayload
                {
                    Schema = "SYS.STANDARD",
                    ParameterTypeSemantics = ParameterTypeSemantics.AllowImplicitConversion,
                    IsComposable = true,
                    IsNiladic = false,
                    IsBuiltIn = true,
                    IsAggregate = false,
                    IsFromProviderManifest = true,
                    StoreFunctionName = "TO_NUMBER",
                    ReturnParameters =
                        new[]
                    {
                        FunctionParameter.Create("ReturnType", edmType, ParameterMode.ReturnValue)
                    },
                    Parameters =
                new[]
                {
                    FunctionParameter.Create("Val", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String), ParameterMode.In)
                }
                };

            var function = EdmFunction.Create("TO_NUMBER", "EntityLayer.Utility", DataSpace.SSpace, payload, null);
            dbModel.StoreModel.AddItem(function);
        }  
    }


FunctionConvention sınıfı ilgili fonksiyonların haritalanması için gerekli meta bilgilerin oluşturulmasını sağlayan bir Convention sınıf oluşturulduktan sonra Context sınıfı içinde yer alan "OnModelCreating" fonksiyonu içinde tanımlanmaktadır.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
       modelBuilder.Conventions.Add(new FunctionConvention());
}


Yukarıdaki işlemler yapıldıktan sonra LINQ sorgularında kullanılabilmesi için aşağıdaki gibi bir sınıf içinde ilgili fonksiyonların karşılıkları tanımlanmalıdır:

public class CommonFunctions
{
     [DbFunction("EntityLayer.Utility", "TO_CHAR")]
     public static string TO_CHAR(int Val)
     {
         throw new NotSupportedException();

     }

     [DbFunction("EntityLayer.Utility", "TO_NUMBER")]
     public static decimal TO_NUMBER(string Val)
     {
         throw new NotSupportedException();
     }
}





ASP.NET Üzerinde Jquery ile AJAX İşlemleri - AJAX Processes with JQUERY on ASP.NET

ASP.NET'de ihtiyaç duyulabilecek en önemli şeylerden biri AJAX işlemleridir. AJAX işlemleri web sayfası üzerinden "postback" olmadan bilgi alışverişi yapılmasını sağlar. Jquery'nin ajax fonksiyonu ile aşağıdaki kod parçası kullanılarak sunucuda yer alan "FonksiyonAdi" fonksiyonuna  "KullaniciAdi" parametresi veya JSON nesnesi gönderilmekte ve kullanıcı soy ismi geri dönmektedir.

$.ajax({

       type: 'POST',
       url: './SayfaAdi.aspx/FonksiyonAdi',
       data: '{ KullaniciAdi:"Yigit" }',
       contentType: 'application/json; charset=utf-8',
       dataType: 'json',
       success: function (result) {

                 alert(result.d);
                     
                },
                error: function (e) {
                         
                  alert('Hata Oluştu');

                }
      });

Sunucu tarafında sayfanın kod kısmında yer alan kod parçacığı aşağıdaki gibidir.

[System.Web.Services.WebMethod]
public static string FonksiyonAdi(string KullaniciAdi)
{
    return "YOLCU";
}