8 Mart 2014 Cumartesi

Linq

Linq kullanırken aldığım bazı notlar aşağıda.

Linq ve Lambda
Linq lambda ile iç içe geçmiş olduğu için lambda kullanımı konusunda bir kaç örnek vermek lazım diye düşündüm
Expression Lambda
Basit expression'lar için kullanılır. Örnek:
(input parameters) => expression

Statement Lamda
Expression Lambda ile aynı sadece statement'lar curly brace içine alınır. Örnek:
(input parameters) => {statement;}
Anonymous Method
delegate kelimesi kullanılır.
delegate(input parameters) => {statement;}

Linq ve Deferred Execution (Ertelenmiş Çalışma)
Linq ile kullanılan SQL benzeri sorgu hemen çalıştırılmaz. Buna ertelenmiş çalışma (deferred execution) denilir. Bu sorgu ilk başta bir expression tree olarak saklanır. Sorgu IQueryable veya IEnumerable dışında başka bir şey döndüğünde veya bu iki arayüz üzerinde yüründüğü zaman gerçekten çalıştırılır

Linq ve Kullanım Şekli
Linq iki farklı tarzda kullanılabiliyor. İlkinde SQL benzeri "Query Expression"  kullanılıyor.  İkincisinde ise "Extension Methods" kullanılıyor. Şekilde fark görülebilir.
Extension Methods Nedir?
Bir sınıfa method eklemek anlamına geliyor. Metod'un ilk parametresi "this" kelimesi, ikinci parametresi ise metodun ekleneceği sınıf oluyor. Örnek:

Extension metodları overload edilen metodlar ile aynı isimler taşımamalı. Eğer metod isimleri çakışırsa overload edilen metodlar extension metodlara göre daha yüksek önceliğe sahip oldukları için, extension metodları çağırılmazlar.

DataSetExtensions
Linq normalde sadece IEnumerable ile çalışır. Eğer DataRowCollection ile de çalışmak istersek System.Data.DataSetExtensions'ı projeye eklemek gerekir.

Aggregate
Tüm elemanlara bir işlem uygulayarak birleştirmek için kullanılır. En çok verilen örnek dizinin toplamını bulmak şeklinde ancak aşağıdaki csv satırını oluşturma örneği daha güzel.
var chars = new []{"a","b","c", "d"};
var csv = chars.Aggregate( (a,b) => a + ',' + b);
Console.WriteLine(csv); // Output a,b,c,d
Any
Herhangi bir elemanın koşulu yerine getirip getirmediğini boolean olarak döndürür. Örnek:
İki listenin contains koşulu için kullanılabilir. JobList ve MasterDataList isimli iki listemiz olsa, ve Master liste içinde bulunan işleri çekmek istesek aşağıdaki gibi yapabiliriz.
jobList.Where(job => masterDataList.Any(m => m.Id == job.MasterDataId));
Average
Average Min ve Max gibi istatistiki metodlar kullanılabiliyor. Örnek:
var startIndex = 10; // zero-based, say
var max = temp.Skip(startIndex).Max();
var min = temp.Skip(startIndex).Min();
var avg = temp.Skip(startIndex).Average();
Count
List sınıfında Count property'si de var, ancak Linq ile gelen Count() bir metod!

Distinct
Distinct aynı değelere sahip iki nesneden sadece birisini seçer. Aşağıdaki örnekte Distinc'in çalışmasını gösteren temsili kod var.
Set<TSource> set = new Set<TSource>(comparer);

foreach (TSource tSource in source)
{
if (!set.Add(tSource))
continue;

yield
return tSource;
}
Nesnelerin birbirlerinden farkını anlamak için 2 yöntem var. İlkinde IEqualityComparer kullanılıyor.
IEqualityComparer bir sınıfın bazı özelliklerine göre disctinct almak için kullanılır.

Diğer yöntemde ise nesnelerin Equals ve HashCode metodlarını gerçekleştirmiş olması bekleniyor. Konu için Equals İşlemleri başlıklı yazıya göz atabilirsiniz.

IEqualityComparer örneği
public class MovieEqualityComparer : IEqualityComparer<Movie>
{

public bool Equals(Movie x, Movie y)
{
...

}

public int GetHashCode(Movie obj)
{
...

}
}
GetHashCode metodunda nesne null ise hash code aşağıdaki gibi döndürülebilir.
//Check whether the object is null
if (Object.ReferenceEquals(obj, null)) return 0;

Kullanımı ise aşağıda
ist<Movie> myMovies = new List<Movie>
{
// ...
};

myMovies.Distinct(new MovieEqualityComparer()).ToList();

Distinct Alternatifleri
Buradaki örnekte GroupBy ve First kullanarak Distinct ile aynı sonucu elde edebileceğimiz gösterilmiş.
distinctCustomers = customers.GroupBy(s => s.FirstName)
                                                 .Select(s => s.First())
Bir diğer seçenek ise lambda kullanarak DistinctBy metodunu yazmak. Örnek:

Kullanımı ise çok basit.
IEnumerable<Contact> collection = //retrieve list of Contacts here
IEnumerable<Contact> distinctEmails = collection.DistinctBy(c => c.EmailAddress);

FirstOrDefault
Eğer aranılan kriterde eleman yoksa, default(T) değerini döner. Reference type'lar için default değer null'dır. Örnek:
Bu metod SQL kullanırken "select top 1 ..." şeklinde bir cümle üretilmesini sağlar.
ForEach
Burada anlatıldığı gibi Linq verilen veriyapısını değiştirmez. Dolayısıyla foreach döngüsü mevcut değil ancak yazmadı da zor değil. Örnek:

GroupBy
SQL'deki groupby ile aynı şekilde çalışıyor. Eşit değerlere sahip elemanları grupluyor. Gruplama sonucunda Key ve Count alanlarına sahip bir nesne listesi oluşturuluyor. Aşağıdaki örnekte GroupBy'ın çalışma şeklini gösteren temsili kod var.
Func<TSource, TElement> elementSelector = x => x;

<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
foreach (TSource tSource in source)
{
TKey key = keySelector(tSource);

// simplified pseudo-code
if (!lookup.Contains(key))
lookup
.Add(new Grouping(key));

lookup
[key].Add(elementSelector(tSource));
}

foreach(IGrouping<TKey, TElement> grouping in lookup)
yield
return grouping;
Gerçek kullanım örneği:

GroupBy ile iki boyutlu bir liste oluşturuluyor gibi düşünülebilir. Buradaki örnekte ise her grubun ilk elemanına erişiliyor.

Intersect
İki listenin kesişimini alır. Default equality comparer veya kendi tanımladığımız metod kullanılabilir.

Inner Join
SQL söz dizimi daha kolay. Örnek'te ID değeri 1 olan parent'lar ile bunlara ait child'ların kesişimi alınıyor.

var id = 1;
var query =
from parent in database.Parent
join child
in database.Children on parent.ID equals child.Parent_ID
where parent.ID == id
select new { Parent = parent, Child = child };
Lambda örneği

List<Parent> list1;
List<Child> list2;
var id = 1;
list1.Join (list2 //source
                p => Parent.ID,
                c => Child.Parent_ID,
                (parent,child) => new {(Parent = parent, Child = child}) //End of Join
       //where for selecting from inner join result
      .Where (parentAndChild => parentAndChild.Parent.ID == id);

OrderBy
Birden fazla alana göre sıralamak için OrderBy().ThenBy(). şeklinde yapmak lazım.
Örnek:

SQL sözdiziminde sıralama yapılacak alanların virgül ayrılır. Örnek'te p.DESC ve p.Code alanlarına göre sıralama yapılmış.
from p in listData
orderby p.DESC ascending, p.Code ascending
OrderByDescending
Herhangi bir alana göre büyükten küçüğe sıralama yapmak için kullanılır. Örnek:

RemoveAll
RemoveAll aslında bir Linq metodu değil ancak kullanım örneğini not almak istedim. Eğer elimizde bir arayüzden türeyen farklı sınıfların listesi var, örnekte gösterildiği gibi bazılarını silmek mümkün.

SequenceEqual
Örnekte iki diziyi kolayca karşılaştırma gösterilmiş.
Select
Elde edilen nesnenin bir başka nesneye dönüştürülmesini sağlar (projection). Örnek:

Select liste için kullanılıyorsa dönüştürülen nesnenin kaçıncı indekste olduğu da bilinebilir. Örnek'te bir liste Dictionary'e dönüştürülüyor ve he kelimenin kaçıncı konumda olduğu saklanıyor.
var map = words
.Select((word, index) => new { Word = word, Index = index })
.ToDictionary(x => x.Word, x => x.Index);

SelectMany
Parametre olarak verilen bir array ya da benzeri veri yapısını düzleştirerek, IEnumerabla haline getirir. Örnek  girdiyi satırlara ayırı daha sonra da virgülden itibaren ayırır .
string numbers = "1,2,3\n4,5,6\n7,8,9";
IEnumerable<int> list =
numbers.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)
.SelectMany(s => s.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
.Select(s => int.Parse(s));
Skip
Bazı elemanları atlamamızı sağlar. Örnekte ilk 3 eleman atlanıp sonraki 5 eleman alınıyor.
values.Skip(3).Take(5).Average();
Sum
GroupBy ve Sum beraber kullanılabiliyor. Örnek:
ToLookup
ToList(), ToDictonary() metodları gibibir veri yapısı döndürür. Döndürülen veri yapısı bir multimap'tir. Örnek:


Where
Verilen listeyi where koşuluna göre filtrelemek için kullanılır. Filtre'nin true döndürdüğü elemanlar sonuca dahil eder.  Örnek:

Linq akıllı olduğu için, arka arkaya gelen Where koşullarını birleştirir deniliyor.

Linq ve XML
Linq to XML System.Linq.XML namespece'i içindeki sınıflardan oluşuyor. Şu sınıflardan oluşuyor.

XDocument sınıfı

Descendants metodu
Descendants metodu IEnumerable döndüğü için IEnumerable ile kullanılan tüm metodlar hizmetimize amadedir.

Arama yapma
Aşağıdaki xml'in içinde arama yapma örneği. Namespace aranılan tag'e dahil edilmezse arama default namespace içinde yapıldığı için sonuç boş döner. Bu yüzden namespace'i de aramaya dahil etmek gerekir.


<?xml version="1.0" encoding="UTF-8"?>
<MyDocument xmlns ="http://www.mycompany.com/MyNamespace"
....
</MyDocument>

XDocument document = XDocument.Load ("path");
XNamespace ns = document.Root.Name.Namespace;
var list = document.Descendant (ns + "MyTag")
                                .Where (x => (string)x.Attribute("MyAttribute") == "Value");


Silme
XML'de X düğümlerini silmek için örnek:
<A>
<B id="ABC">
<C name="A" />
<C name="B" />
</B>
<X>
<B id="ZYZ">
<C name="A" />
<C name="B" />
</B>
</X>
</A>

XDocument doc = XDocument.Load("D:\\parsedXml.xml");
doc
.Descendants("A").Descendants("X").Remove();
yapılır. Böylece XML aşağıdaki gibi olur
<A>
<B id="ABC">
<C name="A" />
<C name="B" />
</B>
<B id="ZYZ">
<C name="A" />
<C name="B" />
</B>
</A>

Elements metodu
Elements ile Descendants arasındaki fark var. Descendants verilen yoldan itibaren tüm alt düğümleri dolaşır. Elements ise sadece ilk alt düğümleri dolaşır. Örnek'te XDocument türünden bir değişken olan doc'tan summary/accounts bilgileri çekiliyor.

var accounts = doc.Root.Elements("summary").Elements("account");



Hiç yorum yok:

Yorum Gönder