EĞİTİM : LINQ to SQL Bölüm : LINQ’e Genel Bakış Konu : LINQ Nedir? Page 1 of 25 LINQ, program ve veri arasındaki ilişkiyi başka bir boyuta taşıyan devrimsel bir programlama metodolojisidir. LINQ, bir programalama arayüzü sunar. C# diline getirdiği eklentilerle SQL benzeri tek bir söz dizimi ile farklı tiplerdeki verilerin sorgulanmasını sağlar. C# ile sorgu yazmak, tip güvenli çalışma, ifadelerin otomatik olarak tamamlanması ve IntelliSense gibi özelliklerle geliştiricinin üretkenliğini artırmayı sağlar. Farklı LINQ uygulamaları mevcuttur. Bunlardan en temel olanlar şöyle özetlenebilir. Bellek üzerindeki nesnelerden oluşan koleksiyonları sorgulamak (LINQ to Objects), SQL Server veritabanlarındaki tabloları sorgulamak (LINQ to SQL), ADO.NET DataSet tiplerini sorgulamak (LINQ to DataSets), Xml verilerini sorgulamak (LINQ to XML) ADO.NET Entity Framework tarafından oluşturulan varlıkları sorgulamak (LINQ to Entity) Bu sayılan LINQ uygulamaları aynı söz dizimini kullanır ancak farklı veri kümelerini hedeflemektedir. Çoğu SQL komutlarına benzer yada aynı olan C# anahtar kelimelerinden oluşan ifadeler ile .NET koleksiyonlarına LINQ sorguları yazarsın. Bu anahtar kelimeler, LINQ Standart Sorgu Operatörleri olarak anılır (LINQ Standart Query Operators). Bu operatörler, System.Linq isim alanı altında yer alan Enumerable sınıf tarafından tanımlanır. C# derleyicisi (compiler), sorgu ifadelerini, çalıştırılmak üzere CIL ortak ara diline dönüştürür. Aşağıda temel bir LINQ sorgusunun genel yapısını inceleyebilirsin : var sorgu = from eleman in koleksiyon where kriterler orderby sıralamaKıstası [ascending|descending] select [takmaAd = ]kolonIfadesi [ , [takmaAd2 = ] kolonIfadesi2] var anahtar kelimesi, yukarıdaki LINQ sorgu sonucunun atandığı sorgu isimli lokal değişken için tip çıkarsaması yapar. var, bir veri tipi değildir. var, eşitliğin sağ tarafındaki veriye ait tipin, derleyici tarafından otomatik olarak tespit edilmesini ve CIL koduna yazılmasını sağlar. Aşağıdaki resimde LINQ mimarisi özet olarak yer almaktadır. 2/25 3/25 NESNE YÖNELİMLİ PROGRAMLAMA (OBJECT ORIENTED PROGRAMMING) Konu : Metotlar ve Yapıcı Metot (Constructor) 4/25 Yapıcı Metot’ların Rolü (Constructor) Sınıf nesne örnekleri oluşturulurken tanımlamanın sonunda kullanılan metot parantezlerinin aslında bir anlamı vardır: Sınıfa ait yapıcı metodu çağırmak! Oyuncu o1 = new Oyuncu(); C# gibi nesne yönelimli dillerin en büyük avantajlarından birisi, bir sınıf nesne örneği oluşturulduğu anda otomatik olarak çağrılan özel bir metodun tanımlanabilmesidir. Bu metoda yapıcı metot (constructor) adı verilir. Varsayılan yapıcı metot, nesne içerisinde belleğe çıkarılacak olan bütün alanların doğru varsayılan değerleri almasını sağlar. (Bu bütün yapıcı metotlar için geçerlidir) Peki nesne oluşturulduğu anda çağrılan yapıcı metoda isim olarak ne verilir de derleyicinin bu işi otomatik olarak yapması sağlanır? Bu konuda C++ dilinin tasarımcısı Stroustrup takip edilmiştir. C# dilinde kullanılan yapıcı metotlar, bulundukları sınıfla aynı isimdedir. Aşağıda basit bir yapıcı metodu ile birlikte basit bir sınıf yer almaktadır: namespace YapiciMetotKullanimi { class YapiciliSinif { public YapiciliSinif() { Console.WriteLine("Yapıcı metot çalıştı..."); } } class Program { public static void Main(string[] args) { YapiciliSinif ctor = new YapiciliSinif(); } } } Yukarıda, içerisinde yapıcı metodu olan bir sınıf ve Main metodu içerisinde sadece bu sınıftan bir nesne örneğinin oluşturulduğu kodlar yer almaktadır. Yapıcı metotların nesne örneklendiği anda çalışması bu kod bloğunun çıktısından anlaşılabilir. Yapıcı metotlar nesne örneklendiği anda otomatik olarak çalışır Yapıcı metot, geriye void dahil değer döndürmeyen, parametre alabilen özel bir çeşit metottur. Her sınıf mutlaka en az bir adet yapıcı metoda sahip olmak zorundadır. Eğer sınıf içerisine yukarıdaki gibi bilinçli olarak yazılmazsa, derleyici bizim için varsayılan bir yapıcı metot üretir. Derleyici tarafından üretilen varsayılan yapıcı metodun parametresi olmaz ve içerisinde alanların varsayılan değerleri verilir, bunun dışında hiçbir şey yoktur. Geliştirici olarak kendin yapıcı bir metot yazmak istediğinde bunu kolaylıkla gerçekleştirebilirsin. Geriye değer döndürmeyen (yani herhangi bir geri dönüş tipi belirtilmeyen), public erişim belirleyicisi ile işaretlenmiş ve içinde bulunduğu sınıf ile aynı isimde bir metot yazman yeterli olur. Metot içerisine, ilgili sınıftan bir nesne 5/25 oluştuğu anda çalışması istenen C# kodu yazılabilir. Sınıf içerisine bilinçli olarak yazılmadığı durumlarda her sınıfın varsayılan yapıcı metodu aşağıdaki gibi oluşturulmaktadır. namespace YapiciMetotKullanimi { class Oyuncu { public Oyuncu() { //Sınıfa ait alanların varsayılan değerleri otomatik olarak verilir. } public string adi; public string takimi; public byte formaNo; public string BilgiVer() { return string.Format("{0} {1} - {2}", formaNo, adi, takimi); } public void TakimDegistir(string yeniTakim) { takimi = yeniTakim; } } } Yapıcı Metotları Aşırı Yüklemek Nesne kullanıcısı nesne ile çalışmaya başladığında (yani nesne örneği oluşturulmasının hemen ardından) genellikle ilk iş sınıf içerisinde tanımlanmış olan alanların değerlerinin verilmesidir. Oyuncu sınıfı gibi birçok sınıf ile çalışılırken bir tane nesne için değeri gerekli bazı alanlara atama yapılmadan o nesne ile çalışmanın fazla bir anlamı olmayabilir. Bu sebeple nesne referansı üzerinden ilgili değişkenler çağrılır ve sırayla değerleri verilir. Öyleyse, daha nesne örneği oluşturulurken bu alanların alacağı değerlerin belli olması yerinde bir hareket olacaktır. Bu durumda nesne, alanlarının varsayılan değerleri ile değil, çalışılacak gerçek değerleri ile belleğe çıkar. Sınıflar bu iş için, varsayılan yerine kendi yapıcı metotlarımızın yazılması imkanını sunarlar. Bu şekilde nesne kullanıcısına nesneyi oluşturma anında durum verilerine başlangıç değerlerinin verilmesi için kolay bir yol sunulmuş olur. namespace YapiciMetotKullanimi { class Oyuncu { //Kendi yazdığımız yapıcı metot, nesnenin durum verilerine kullanıcıdan alınan parametre değerlerini aktarıyor public Oyuncu(string ad, string takim,byte formaNumarasi) { adi = ad; takimi = takim; formaNo = formaNumarasi; Console.WriteLine("Parametrik yapıcı metot çalıştı"); } //Varsayılan yapıcı metot 6/25 public Oyuncu() { Console.WriteLine("Varsayılan yapıcı metot çağrıldı..."); } public string adi; public string takimi; public byte formaNo; public string BilgiVer() { return string.Format("{0} {1} - {2}", formaNo, adi, takimi); } public void TakimDegistir(string yeniTakim) { takimi = yeniTakim; } } } Yukarıda kendi yazdığımız yapıcı metot ve yeniden tanımlanan varsayılan yapıcı metot ile düzenlenmiş Oyuncu sınıfı yer almaktadır. Bir sınıf içerisinde parametreli bir yapıcı metot tanımlandığında varsayılan yapıcı metot derleyici tarafından üretilmez. Çünkü alanların değerleri, yeni tanımlanan yapıcı metot içerisinde, sınıfın tasarlayıcısı tarafından verilmiştir. Ancak çalışma zamanı, nesne oluşturulduğu anda çağrılan özel yapıcı metodu yine de takip eder. Bunun sebebi sınıfı tasarlayan geliştiricinin yazdığı yapıcı metot içerisinde sınıfa ait bütün alanların başlangıç değerlerini bir şekilde atamak zorunda olmamasıdır, hatta istenirse alanlarla ilgili hiç kod yazılmayabilir. Kullanıcıdan parametre olarak alınan ya da kod bloğu içerisinde geliştirici tarafından değeri verilen alanların dışında kalanlara varsayılan değerlerini atamak özel yapıcı metodun görevidir. Parametrik yapıcı metodun yanında nesne kullanıcısına alanların değerleri verilmeden nesnenin tanımlanması imkanı verilmek istenirse, varsayılan yapıcı metot bilinçli olarak yazılmalıdır. Çünkü sınıf içerisine yazılan parametrik metot, derleyici tarafından üretileni ezmektedir. Son haliyle Oyuncu sınıfının kullanımı ve ekran çıktısı aşağıdaki gibidir: namespace YapiciMetotKullanimi { class Program { public static void Main(string[] args) { //Varsayılan yapıcı metot (constructor) çağrılır. Oyuncu o1 = new Oyuncu(); Console.WriteLine(o1.BilgiVer() + "\n"); //Parametreli yapıcı metot çağrılır. Oyuncu o2 = new Oyuncu("Tuncay", "Middlesbrough", 9); Console.WriteLine(o2.BilgiVer()); Console.ReadLine(); } } } 7/25 Parametrik yapıcı metot kullanımı Yapıcı metotlar aşırı yüklenebilirler. Yani farklı parametre sayıları ya da tipleri ile istenilen sayıda yazılabilirler. Bunun amacı nesne kullanıcısına farklı alan kümeleri içerisinden ihtiyaç duyduklarının değerlerini vererek nesneyi oluşturma esnekliğini sunmaktır. Aşağıda farklı parametre kombinasyonları ile yapıcı metodu üç defa aşırı yüklenmiş Oyuncu sınıfı yer almaktadır : namespace YapiciMetotKullanimi { class Oyuncu { public string adi; public string takimi; public byte formaNo; public Oyuncu(string ad) { adi = ad; } public Oyuncu(string ad, string takim) { adi = ad; takimi = takim; } public Oyuncu(string ad, string takim, byte formaNumarasi) { adi = ad; takimi = takim; formaNo = formaNumarasi; } public string BilgiVer() { return string.Format("{0} {1} - {2}", formaNo, adi, takimi); } public void TakimDegistir(string yeniTakim) { takimi = yeniTakim; } } } 8/25 EĞİTİM : LINQ to SQL Bölüm : LINQ’e Genel Bakış Konu : LINQ Sorguları 9/25 Bir LINQ sorgusu, veri kaynağından istenen veriyi elde etmek için kullanılır. Bir LINQ sorgu süreci 3 ayrı parçadan oluşmaktadır. 1. Veri kaynağını elde et. 2. Sorguyu oluştur. 3. Sorguyu çalıştır. Aşağıdaki örneği bu ayrımı göz önünde bulundurularak incele. Örnekte veri kaynağı olarak bir int dizisi kullanılmıştır. // 1) Veri Kaynağı int[] sayilar = new int[5] { 1, 2, 3, 4, 5 }; // 2) Sorgu Oluşturma var tekSayilar = from s in sayilar where (s % 2) == 1 select s; // 3) Sorgunun Çalıştırılması. foreach (int s in tekSayilar) { Console.WriteLine(s); } LINQ mimarisinde sorgunun çalıştırılması, sorgunun kendisinden ayrı bir süreçtir. Yani sorgu oluşturulurken, veri elde edilmez. Veri Kaynağı Örnekteki veri kaynağı int dizisi, IEnumerable<T> generic tipini desteklemektedir. Dolayısıyla sorgulanabilir bir tiptir. Bir sorgu foreach döngüsü ile çalıştırılır ve foreach IEnumerable yada IEnumerable<T> arayüzlerini uygulamış tiplere ihtiyaç duyar. Sorgu Sorgu, veri kaynağı yada kaynaklarından hangi bilgilerin elde edileceğini belirtir. Dilenirse bir sorgu aynı zamanda veri kaynağından elde edilen bilginin nasıl sıralanacağını, gruplanacağını ve elde edilmeden önce nasıl bir forma gireceğini belirtebilir. Bir sorgu, sorgu değişkeninde saklanır. Burada önemli olan nokta, sorguyu saklayan değişken tek başına her hangi bir aksiyon alamaz ve üzerinde veri saklamaz. Sadece ileri bir noktada sorgu çalıştırıldığında sonucu üretmek için gereken bilgileri saklar. Sorgunun Çalıştırılması Sorgunun çalıştırması, sorguyu saklayan değişkenin foreach döngüsüne sokulması ile gerçekleşir. Bu konsepte ertelenmiş çalıştırma (deffered execution) adı verilir. Örnekte foreach döngüsü ile sorgu kullanıldığında, sorgu çalıştırılmış ve veri kaynağında yer alan tek sayılar filtrelenmiştir. Bir sorgunun hemen çalıştırılması ve sonuç kümesinin elde edilmesi istenirse sorgu cümleleri ToList() yada ToArray() metotları ile birlikte kullanılabilir. List<int> tekSayilar = (from s in sayilar where (s % 2) == 1 select s).ToList(); 10/25 Bu durumda hem sorgu cümlesinin hemen çalıştırtılması sağlanır; hem de sonuç kümesi bellekte bir koleksiyon üzerinde saklanmış olur. 11/25 EĞİTİM : LINQ to SQL Bölüm : LINQ’e Genel Bakış Konu : Generic Koleksiyonlar İle LINQ 12/25 LINQ sorgu değişkenleri IEnumerable<T> arayüzünden türeyen bir tip olmalıdır. Örneğin IEnumerable<Ogrenci> tipinde bir sorgu değişkeni gördüğün zaman şu anlama gelir : Bu sorgu çalıştırıldığında sıfır yada daha fazla sayıda Ogrenci sınıfından nesne üretecektir. Örnek için öncelikle basit bir Ogrenci sınıfı kodla. public class Ogrenci { public string Adi; public DateTime DogumTarihi; public int Numarasi; public Ogrenci(string adi, DateTime dogumTarihi, int numarasi) { this.Adi = adi; this.DogumTarihi = dogumTarihi; this.Numarasi = numarasi; } } Main metodu içerisine 4 tane Ogrenci nesnesi içeren bir List<T> koleksiyonu oluştur. Ogrenci o1 = new Ogrenci("Ali Yılmaz",new DateTime(1982, 2 ,2),7823482); Ogrenci o2 = new Ogrenci("Kerim Ak", new DateTime(1975, 10, 23), 9288763); Ogrenci o3 = new Ogrenci("Can Çelik", new DateTime(1990, 7, 30), 1372426); Ogrenci o4 = new Ogrenci("Halil Ata", new DateTime(1987, 1, 13), 9126343); List<Ogrenci> ogrenciler = new List<Ogrenci>() { o1, o2, o3, o4 }; Şimdi LINQ sorgusu ile bu koleksiyonda arama yapalım : 1985 yılı öncesinde doğan öğrencilerin isimleri ve numaraları, aralarında “/” işareti olacak şekilde yan yana tek bir string tipli veri olarak elde edilsin. Aşağıdaki sorgu bu işi görecektir : var sorgu = from o in ogrenciler where o.DogumTarihi.Year <= 1985 select o.Adi + " / " + o.Numarasi.ToString(); Bu sorgu cümlesinde dikkat çekmesi gereken 1-2 önemli nokta vardır. Birincisi generic koleksiyon üzerinden LINQ sorgusu yazarken Visual Studio editörünün otomatik kod tamamlayıcı özelliği Intellisense sana yardım eder. Örneğin where operatöründen sonra “o.” yazdığında Ogrenci sınıfının public üyeleri listelenir ve sen filtrelemede kullanmak istediğin DogumTarihi alanını listeden seçebilirsin. Böylece hızlı ve minimum hatayla sorgu yazarsın. Sorgu sonucunu görmek için sorguyu çalıştırman lazım; dolayısıyla foreach döngüsü yazman gerekiyor. foreach (var o in sorgu) { Console.WriteLine(o); } Kod parçası çalıştırıldığında aşağıdaki çıktı elde edilir : 13/25 var Anahtar Kelimesi : Derleyicinin Tip Çıkarsaması Yapması Örnekte hem sorgu değişkeni olarak hem de foreach döngüsünde döngü değişkeni olarak var anahtar kelimesi kullanılmıştır. sorgu isimli sonuç kümesi değişkeni incelendiğinde, generic koleksiyonun içerdiği nesnelerin veri tipine bakarak çıkarsama yapılır ve CIL koduna veri tipi olarak IEnumerable<Ogrenci> yazılır. Benzer şekilde foreach döngüsünde var ile tanımlanan döngü değişkeninin veri tipi, derleyici tarafından sorgu değişkeninin elemanlarından tespit edilir. Böylece çalışma zamanında işlemler Ogrenci tipinde gerçekleştirilir. 14/25 EĞİTİM : LINQ to SQL Bölüm : Veri Tabanı İşlemlerinde LINQ: LINQ to SQL Konu : ORM Aracı Olarak LINQ to SQL 15/25 .NET ile yazılan ticari uygulamaların %90’ından fazlası ilişkisel veritabanı yönetim sistemi üzerindeki tablolarda saklanan verilerle çalışmaktadır. Halen artan bir yüzdeyle yazılım mimarileri ve geliştiriciler nesne yönelimli programlamaya adapte olmaktadırlar. Aynı şekilde veritabanları, iş nesnelerini saklamak ve diğer uygulamalar ile paylaşmak için tercih edilen saklama ortamı olmaktadır. Bu süreçte, veritabanları özellikle nesne modellerini saklamak ve elde etmek üzere dizayn ediliyor, veri nesne olarak oluşturuluyor, aynı zamanda sınıflar, özellikler, metotlar ve hatta kalıtım ile alt sınıflara destek veriyor. Veritabanları ve iş nesneleri arasındaki bu doğal yakınlığa rağmen program içinde ve veritabanında ayrı ayrı dizayn yapma maliyeti söz konusuydu. Nesnelerin saklanması için ilişkisel veritabanlarının kullanılması, CRUD kısaltması ile anılan create, retrieve, update ve delete işlemleri için programlama dili olarak SQL kullanılması anlamına gelmektedir. Bu işlemlerin program içinden belli bir uyumluluk ile yapılmasını sağlamak için O/RM (Object / Relation Mapping) araçları kullanılmaya başlandı. LINQ to SQL, Microsoft’un Visual Studio ile birlikte sunduğu bir O/RM aracıdır. LINQ to SQL, hafif ve yüksek performanslı bir nesne saklama platformu sunar. Bunu kolay kullanılan grafik bir arayüz ile gerçekleştirir. Bu araç, iş nesnelerini oluşturmak, elde etmek, güncellemek ve silmek için stored procedure sql nesnesini de desteklemektedir. Bu görsel araç, SQL Server veritabanlarından seçeceğin tablolardan entity class denen sınıfların oluşturulmasını sağlar. Tablolar sınıf, tablodaki kolonlar birer özellik (property) olacak şekilde otomatik olarak üretilir ve bu sınıf tasarımları Visual Studio içerisinde saklanır. Araç, aynı zamanda, tablolar arasındaki ilişkileri de association olarak saklar. Bu sayede, LINQ sorguları yazarken join yapmana gerek kalmadan IntelliSense yardımıyla ilişkili nesnelere ve onun üyelerine erişebilirsin. Tablolar, kayıtlar ve anahtarlardan oluşan ilişkisel modeli entity sınıfları, entity nesneleri ve ilişkilere taşımanın avantajı, entity modelinin müşteriler, çalışanlar, ürünler vb. iş nesnelerini temsil edebilmesidir. Böylece LINQ to SQL, küçük ve orta ölçekli projelerin için hızlı uygulama geliştirme metodolojisi sunarak sana yardımcı olur. 16/25 EĞİTİM : LINQ to SQL Bölüm : Veri Tabanı İşlemlerinde LINQ: LINQ to SQL Konu : LINQ to SQL Dizayn Ekranı 17/25 LINQ to SQL'i VERİ ERİŞİM KATMANI OLARAK KULLANMAK LINQ to SQL Classes, Visual Studio ile açılan bir C# projesindeki şablonun adıdır. Projene yeni bir LINQ to SQL Classes eklediğinde, boş bir O/R dizayn ekranı açılır. Bu, veritabanından ekleyeceğin sql nesneleri ile ilgili metadataları tutan xml tabanlı ve dbml uzantılı bir dosyadır. Soldaki büyük alana tablo ve view, soldaki küçük alana ise stored procedure ve fonksiyon ekleyebilirsin. Veritabanına bağlanıp sql nesnelerini görüntülemeni sağalayacak araç ise “Server Explorer”dır. Bu araca menüden View Server Explorer sekmelerinden erişebilirsin. Bu araçta yer alan Data Connections kalemine sağ tıklayıp Add Connection seçilerek bağlanılacak veritabanı ile ilgili bilgiler girilebilir. Sonucunda veritabanındaki bütün sql nesneleri önüne listelenecektir. Yapman gereken Server Explorer aracındaki listeden 18/25 dizayn ekranına ihtiyaç duyduğun tabloları sürükleyip bırakmak. Bu konudaki örneklerde, daha önce SQL konusunda kullandığın Adventureworks veritabanını kullanabilirsin. Entity olarak dizayn ekranı tarafından üretilen sınıfları incelemek istersen Solution Explorer penceresinde *.designer.cs dosyasına bakmalısın. 19/25 EĞİTİM : LINQ to SQL Bölüm : Veri Tabanı İşlemlerinde LINQ: LINQ to SQL Konu : Nesneleri Ekleme 20/25 LINQ to SQL, projene veri erişim katmanı uygulamak için çok mükemmel bir adaydır. LINQ to SQL ile kullanacağın merkezi nesne DataContext sınıfıdır. Bu sınıf, veritabanları ile uygulama arasındaki bağlantıyı yönetir. Aynı zamanda ürettiğin entity sınıflarına ait veritabanındaki kayıtları içeren Table<TEntity> tipinde koleksiyonları saklar. Bu koleksiyonlar sayesinde kod tarafında, bir tablodaki bütün verilere kolayca erişebilir ve ASP.NET gibi bir arayüzde gösterebilirsin. Örneğin Musteris koleksiyonunu ele alalım. Bu, içinde Musteri tipinde nesneler barındıran Table<Musteri> tipinde bir koleksiyondur. Veritabanına doğru çalıştırılacak bir LINQ sorgusu hazırlamak için Table<TEntity> tipindeki koleksiyon ile çalışmalısın. Bu nesne üzerinden gerçekleştirdiğin manipülasyonlar, C# derleyicisi tarafından önce dinamik TSQL sorgularına dönüştürülür; ardından veritabanına doğru bağlantı açılarak çalıştırılır. DataContext, SqlClient sağlayıcısı üzerinden veritabanına bağlantı açılması ve kapatılması süreçlerini otomatik olarak yönetir. Senin ekstra kod yazmana gerek yoktur. Yeni Kayıt Eklemek LINQ to SQL kullanarak veritabanındaki bir tabloya yeni kayıt eklemek için Table<TEntity> koleksiyonuna yeni bir kayıt eklemen yeterlidir. Bu kayıt, veri eklemek istediğin tablo için dizayn ekranından ürettiğin entity sınıfı tipinde olmalıdır. DataContext.TabloAdı.Add(YeniNesne) Nesneyi hazırlayıp koleksiyona ekledikten sonra DataContext.SubmitChanges() metodu çağrılır. Bu metot, yeni nesnenin veritabanında saklanması için gerekli T-SQL insert sorgusunun hazırlanması ve çalıştırılmasını sağlar. Ayrıca bütün veritabanı işlemlerinde mutlaka System.Data.Linq.DataContext tipinden türeyen projene özel DataContext nesnesine ihtiyacın vardır. NesneModeliDataContext ctx = new NesneModeliDataContext(); Department yeniDep = new Department(); yeniDep.Name = "Yazılım"; yeniDep.GroupName = "Bilgi Teknolojileri"; yeniDep.ModifiedDate = DateTime.Now; ctx.Departments.InsertOnSubmit(yeniDep); ctx.SubmitChanges(); Dilenirse InsertOnSubmit metodu yerine InsertAllOnSubmit metodu kullanılarak bir kayıt değil önceden hazırlanmış bir koleksiyon içindeki bütün kayıtların eklenmesi sağlanabilir. 21/25 EĞİTİM : LINQ to SQL Bölüm : Veri Tabanı İşlemlerinde LINQ: LINQ to SQL Konu : Nesne Güncelleme 22/25 Kayıt Güncellemek Kayıt güncellemek için DataContext üzerindeki koleksiyondan güncellenmesi istenen bir yada birden fazla nesnenin elde edilmesi gerekir. Bunun için where ifadesi ile filtrelenmiş bir sorgu yazılması gerekir. Sorgu sonucunda elde edilen nesnelerin istenen özelliklerinde (property) gerekli değişiklikler yapıldıktan sonra DataContext.SubmitChanges() metodu çağrılır. Bu metot kayıtların veritabanında güncellenmesi için gerekli TSQL update sorgusunun hazırlanması ve çalıştırılmasını sağlar. NesneModeliDataContext ctx = new NesneModeliDataContext(); Department depGuncellenecek = (from d in ctx.Departments where d.DepartmentID == 1 selectd).SingleOrDefault(); if (depGuncellenecek != null) { depGuncellenecek.GroupName = "Finansal Yönetim"; ctx.SubmitChanges(); } Bu örnekte DepartmentId değeri 1 olan tek bir kayıt olacağı için sorgu sonucunda SingleOrDefault metodu çağrılmıştır. Böylece eşitliğin sol tarafında tek bir Department nesnesi elde edilmiş ve o nesnenin GroupName kolonu güncellenmiştir. Eğer birden fazla nesne üzerinde aynı anda güncelleme yapmak durumunda kalırsan aşağıdaki kod parçası sana yol gösterici olacaktır. NesneModeliDataContext ctx = new NesneModeliDataContext(); var depGuncellenecek = from d in ctx.Departments where d.DepartmentID < 10 select d; foreach (var d in depGuncellenecek) { d.GroupName = "Finansal Yönetim"; } ctx.SubmitChanges(); Bu kod parçasında LINQ sorgusu sonucunda 9 kayıt döner. Bu 9 kayıt üzerinde güncelleme yapmak için foreach döngüsünden faydalanılır. Döngünün sonunda SubmitChanges metodu çağrılarak bütün güncellemeler tek bir seferde veritabanına yansıtılmış olur. 23/25 EĞİTİM : LINQ to SQL Bölüm : Veri Tabanı İşlemlerinde LINQ: LINQ to SQL Konu : Nesne Silme 24/25 Kayıt Silmek Veri tabanından tek bir kayıt yada birden fazla kayıt silmek için DataContext üzerindeki koleksiyondan nesnelerin silinmesi gerekir. DataContext.TabloAdı.Remove(SilinecekNesne) Bunun için where ifadesi ile filtrelenmiş bir sorgu yazılması gerekir. Sorgu sonucunda elde edilen nesneler koleksiyondan silindikten sonra DataContext.SubmitChanges() metodu çağrılır. Bu metot kayıtların veritabanından silinmesi için gerekli T-SQL delete sorgusunun hazırlanması ve çalıştırılmasını sağlar. NesneModeliDataContext ctx = new NesneModeliDataContext(); var depSilinecek = (from d in ctx.Departments where d.DepartmentID == 3 select d).SingleOrDefault(); if (depSilinecek != null) { ctx.Departments.DeleteOnSubmit(depSilinecek); ctx.SubmitChanges(); } Dilenirse DeleteOnSubmit metodu yerine DeleteAllOnSubmit metodu kullanılarak bir kayıt değil bir koleksiyon içindeki bütün kayıtların silinmesi sağlanabilir. 25/25