19 Aralık 2009 Cumartesi

Hala Linq Kullanmıyor musunuz?

.Net için ufak bir uygulama geliştirirken, bu uygulamada veritabanı bağlantısını Sql Data Client ile sağlıyordum, dolayısıyla oluşturduğum her yeni dosyada kodlamaya başlamadan önce "using System.Data.SqlClient;" satırını eklemek zorundaydım. Oysa "using System.Linq;" satırı hazır olarak geliyordu. Bende Microsoft'ta çalışanların elbet bir bildiği vardır diye düşündüm ve kodlamayı yarım bırakarak google'a "linq tutorial" yazıp arattım.

Yeni şeyler öğrenmek her zaman insana zor gelir, ancak linq öğrendikten sonra, neden daha önce bakmadım diye kendime sordum. Çünkü her seferinde bağlantı açıp kapamak, sql sorguları yollayıp sonuçları okumak gibi işlemler linq ile çok kolay.

Bu yazıda çok basit bir uygulamayı linq kullanarak nasıl daha basit hale getirilebileceğini göreceksiniz.Bu uygulamada bir tane öğrenci tablomuz, bir tane de ders tablomuz olacak ve her öğrencinin istediği kadar ders seçebilmesi için de bunları bağlayan bir join tablomuz olacak.

İlk olarak tabloları oluşturmak için, "SQL Serve Management Studio Express"i başlatıyoruz. "Deneme" adında bir veritabanı yaratıp,  aşağıdaki tabloları oluşturuyoruz. Tablo isimlerini ingilizce olarak yazıyorum, eğer türkçe oluşturursak kod içerisinde ingilizce-türkçe karışık bir notasyon oluşacaktır.



{code type=php}
Tablo Adı: student
std_id    int     NOT NULL    PrimaryKey
name    varchar(50)    NOT NULL
lastname    varchar(50)    NOT NULL
std_number    varchar(50)    NOT NULL

{/code}

{code type=php}

Tablo Adı: course
crs_id    int    NOT NULL    PrimaryKey
crs_title    varchar(50)    NOT NULL

{/code}

{code type=php}

Tablo Adı: student_course_join
std_id    int    NOT NULL    PrimaryKey
crs_id    int    NOT NULL    PrimaryKey
{/code}

Tabloları oluşturduktan sonra ForeignKey eklemeyi unutmayın.

Aşağıdaki SQL sorgusunuda çalıştırarak bu tabloları elde edebilirsiniz.

diyagram

{code type=php}
USE [deneme]
GO
/****** Object:  Table [dbo].[student]    Script Date: 12/15/2009 13:04:24 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[student](
[std_id] [int] IDENTITY(1,1) NOT NULL,
[name] [varchar](50) COLLATE Turkish_CI_AS NOT NULL,
[last_name] [varchar](50) COLLATE Turkish_CI_AS NOT NULL,
[std_number] [varchar](50) COLLATE Turkish_CI_AS NOT NULL,
CONSTRAINT [PK_student] PRIMARY KEY CLUSTERED
(
[std_id] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

USE [deneme]
GO
/****** Object:  Table [dbo].[course]    Script Date: 12/15/2009 13:04:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[course](
[crs_id] [int] IDENTITY(1,1) NOT NULL,
[crs_title] [varchar](50) COLLATE Turkish_CI_AS NOT NULL,
CONSTRAINT [PK_course] PRIMARY KEY CLUSTERED
(
[crs_id] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

USE [deneme]
GO
/****** Object:  Table [dbo].[student_course_join]    Script Date: 12/15/2009 13:04:42 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[student_course_join](
[std_id] [int] NOT NULL,
[crs_id] [int] NOT NULL,
CONSTRAINT [PK_student_course_join] PRIMARY KEY CLUSTERED
(
[std_id] ASC,
[crs_id] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

GO
ALTER TABLE [dbo].[student_course_join]  WITH CHECK ADD  CONSTRAINT [FK_student_course_join_course] FOREIGN KEY([crs_id])
REFERENCES [dbo].[course] ([crs_id])
GO
ALTER TABLE [dbo].[student_course_join] CHECK CONSTRAINT [FK_student_course_join_course]
GO
ALTER TABLE [dbo].[student_course_join]  WITH CHECK ADD  CONSTRAINT [FK_student_course_join_student] FOREIGN KEY([std_id])
REFERENCES [dbo].[student] ([std_id])
GO
ALTER TABLE [dbo].[student_course_join] CHECK CONSTRAINT [FK_student_course_join_student]
{/code}

Artık üç adet birbiri ile ilişkisi olan tablomuz bulunmakta, şimdi bunları linq ile nasıl kullanacağımızı göreceğiz.

Bu yazıda iki adet sayfa oluşturacağız, dosyaların hazır halini yazının sonunda bulabilirsiniz. İlk sayfa hem öğrenci kaydı yapıyor hemde listelemesini, ikinci sayfada ise öğrenci seçip, ona bir ders atıyoruz.

ASP.NET ile web sayfası hazırlamak için Visual Web Developer'a veya Visual Studio'ya ihtiyacımız olacak. Visual Studio'nun Express versiyonları ücretsiz olduğundan http://www.microsoft.com/express/default.aspx adresinden indirebilirsiniz. ASP.NET sürekli olarak geliştirildiğinden son versiyonunu kullanmanızı öneriyorum. Örnek vermek gerekise, daha önceki versiyonlarda ajax özelliklerini kullanabilmek için eklentiler kurmanız gerkiyordu, ancak visual studio 2008 de bu araçlar içinde gelmektedir.

Şimdi Visual Studio'yu başlatın ve yeni proje seçeneğini seçin.

1

Önünüze gelen diyalogdan, c# -> Web içindeki "ASP.NET Web Application" seçeneğini seçin. İsim olarak 'Student'ı uygun gördüm, ama herhangi bir sınırlama yok tabii ki :).

2

Bu işlemden sonra önümüze önceden oluşturulmuş 'Default.aspx' adında bir sayfa gelmeli. Aşağıdaki düğmeler sayesinde tasarım, html kaynağı veya her ikisine de geçiş yapabilirsiniz.

3

Sayfamıza fonksiyonellik katmadan önce linq ile sql sunucumuzu ilişkilendirmemiz lazım. Bunun için "Solution Explorer"dan proje ismine sağ tıklayıp (bu örnekte Student) add->new item'a tıklayıp buradaki 'Data' sekmesinde 'LINQ to SQL Classes'ı seçelim. Visual Studio bu dosya ile SQL veritabanımıza dayanarak otomatik olarak kod üretiyor. Böylelikle yanlış sorgular derlerken hata veriyor ve çalışma sırasında daha az hata ile karşılaşmış oluyoruz.

4

Bu dosyayı yarattığımızda iki pencere gelmeli. Birincisinde (sol tarafta) veri ilişkilerini, ikincisinde ise stored procedure gibi veri tabanında tanımladığımız fonksiyonları belirtiyoruz. Biz uygulamamızda ilk pencereyi kullanacağız. "Server Explorer" sekmesine gelin ve buradaki "Data Connections"a sağ tıklayıp "Add Connection"ı seçin. Burada veri tabanımızı seçip işimizi bitiriyoruz.

5

Sunucumuzu ekledikten sonra tablolarımızı ilk pencereye sürüklüyoruz. Sonuç aşağıdaki resme benzemeli.

6

Dosyamızı kaydediyoruz.

İşe ilk sayfadan başlıyoruz. Bu sayfada 3 adet textbox, 2 adet button ve 1 adet gridview bulunmakta.

7

Aşağıda bu sayfaya ait kodlar bulunmaktadır. Kodların açıklamaları yorum olarak kod üzerinde yapılmıştır. Kodları direk sayfadan kopyalamanız halinde hatalar oluşacaktır. Eğer kodları kullanacak olursanız lütfen sayfanın en altındaki linkten indiriniz.

{code type=php}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Student
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// sayfaya her döndüğünde aynı işlemi tekrarlamasını istemiyoruz.
if (!Page.IsPostBack)
{
// veritabanımızda işlem yapmak için oluşturduğumuz sınıftan bir tane yaratıyoruz.
studentClassesDataContext db = new studentClassesDataContext();

// başlangıç için biraz uzun bir sorgu aslında anlatmak gerekirse,
// from s in db.students -> verileri nereden seçiceğimizi söylüyoruz
//                          ve buna s ismini veriyoruz.
// join s_c_j in db.student_course_joins on s.std_id equals s_c_j.std_id
// into empty_set from n in empty_set.DefaultIfEmpty()
// join kısmında sqlden bildiğimiz inner join işlemini yapıyoruz ancak burada inner
// join olması işimize yaramadığından left join yapmamız gerekiyor. bunu sağlamak için
// bu veriyi ara tabloya aktarıyoruz. Böylelikle tüm öğrenciler listelenmiş oluyor ve
// dersleri yoksa bile sonucumuza yansıyor.
// orderby s.name -> öğrencilerin ismine göre sıralıyoruz.
// select new { s.std_number, s.name, s.last_name, n.course.crs_title};
// bu satırda ise sonucumuzun nasıl olacağını belirtiyoruz.
// eğer sadece buradan student nesnesini çekmemiz gerekseydi yapmamız gereken
// select s  olacaktı. Ama burada kendimize özgün bir şekilde çektiğimiz için
// select new { } dememiz gerekiyor.
var _students = from s in db.students
join s_c_j in db.student_course_joins on s.std_id equals s_c_j.std_id
into empty_set from n in empty_set.DefaultIfEmpty()
orderby s.name
select new { s.std_number, s.name, s.last_name, n.course.crs_title};

GridView1.DataSource = _students;
GridView1.DataBind();
}
}

protected void Button1_Click(object sender, EventArgs e)
{
studentClassesDataContext db = new studentClassesDataContext();

// yeni bir öğrenci oluşturuyoruz.
student std = new student();

// değişkenlerimizi eşitliyoruz.
// trim yapmamızın nedeni, istenmeyen boşlukları önlemek
std.name = TextBox1.Text.Trim();
std.last_name = TextBox2.Text.Trim();
std.std_number = TextBox3.Text.Trim();

// submit ya da gönderme halinde veritabanına kaydetmesini söylüyoruz.
// eğer böyle bir veriyi silmesini isteseydik
// db.students.DeleteOnSubmit(_std)
// satırını çağırmamız gerekirdi.
db.students.InsertOnSubmit(std);

// Değişiklikleri artık veritabanına aktarmasını söylüyoruz.
db.SubmitChanges();

// Listeleme işlemini Page_Load fonksiyonunda yaptığımız için
// kayıtlar listelendikten sonra kayıt işlemi gerçekleşmektedir.
// Yeni yaptığımız kaydın da listelenmesi için sayfayı yeniliyoruz.
Response.Redirect("default.aspx");
}

protected void Button2_Click(object sender, EventArgs e)
{
// Ders kayıt sayfasına git.
Response.Redirect("crs_add.aspx");
}

}
}
{/code}

Bu sayfayı oluşturduktan sonra ders ekleme sayfamızı oluşturuyoruz.

8

Açıklamalar yine kod üzerinde yapılmıştır. HTML kaynağına ise sayfanın sonundan ulaşabilirsiniz.

{code type=php}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Student
{
public partial class crs_add : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
studentClassesDataContext db = new studentClassesDataContext();

// Bütün öğrencileri seç
var student_list = from s in db.students
select s;

// Veri kaynağımızı belirt
DropDownList1.DataSource = student_list;
// DropDownList'te gözükecek kısmın sutün ismi
DropDownList1.DataTextField = "std_number";
// burada ise, value kısmına gelmesini istediğimiz sutün ismi
DropDownList1.DataValueField = "std_id";
DropDownList1.DataBind();
}
}

protected void Button1_Click(object sender, EventArgs e)
{
studentClassesDataContext db = new studentClassesDataContext();

// Böyle bir kayıt var mı kontol et.
var check_crs = from c in db.courses
where c.crs_title == TextBox1.Text.Trim()
select c;

if (check_crs.Count() == 0)
{
// böyle bir kayıt bulunmadığından
// yeni kayıt oluştur.
course crs = new course();
crs.crs_title = TextBox1.Text.Trim();

db.courses.InsertOnSubmit(crs);
db.SubmitChanges();
}

// kesin olarak böyle bir kaydımız olduğundan, onu seç.
course _crs = (from c in db.courses
where c.crs_title == TextBox1.Text.Trim()
select c).First();

if (check_crs.Count() != 0)
{
// bu öğrencide bu ders daha önce kayıt edildi mi kontrol et.
// eğer bu öğrenciye bu ders kayıtlıysa ve biz tekrar kayıt etmek istersek
// belirlediğimiz primary key'lerden ötürü sistem çalışmayacaktır.
// Çünkü eşsizlik ortadan kalkacaktır. Primary Key'lerin eşsiz olması gerekmektedir.
// Buna aykırı hareket edersek "Violation of PRIMARY KEY constrain" uyarısını alırız.
var check_std = from scj in db.student_course_joins
where scj.std_id == Convert.ToInt32(DropDownList1.SelectedValue) &&
scj.crs_id == _crs.crs_id
select scj;

if (check_std.Count() != 0)
{
// böyle bir kayıt varsa bu fonksiyonu bitir.
return;
}
}

// artık join tablomuza kayıt yapabiliriz.
student_course_join newscj = new student_course_join();
newscj.course = _crs;
newscj.std_id = Convert.ToInt32(DropDownList1.SelectedValue);

db.student_course_joins.InsertOnSubmit(newscj);

db.SubmitChanges();
}

protected void Button2_Click(object sender, EventArgs e)
{
// geri dön
Response.Redirect("default.aspx");
}
}
}
{/code}

Bu örnekte aslında basit bir uygulama yapmayı amaçlıyordum ancak listeleme kısmında linq sorgusu istemediğim bir şekilde uzadı. Linq sorgularını yazmak için çok güzel bir örnek olmasa da biraz bilenler için işe yarayacağını düşünüyorum. Çeşitli linq sorguları oluşturmanız için burada anlatılanlardan daha fazlasına ihtiyacınız olacak. Bunun için microsoft'un sitesini ( http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx ) yer imlerinize kaydetmenizi öneririm.

Umarım işinize yaramıştır. Hepinize iyi çalışmalar.

Dosyaları indirmek için tıklayın.

Hiç yorum yok:

Yorum Gönder