Form’a DataSet Eklemek Her ne kadar DataReader oldukça kullanışlı olsa da çoğu uygulama forward-only ve read-only bir yapıdan fazlasına ihtiyaç duyar. .NET uygulamalarında bu gereksinimi DataSet ile karşılıyoruz. DataSet nesnesi bir veya daha çok sayıda tablo içerebilir (ve bu tablolar arasında ilişkiler kurulabilir), değişiklikleri local olarak kullanıma sunabilir veya veri kaynağını güncelleyebilir.
DataSet local bir veri kaynağı olarak görülebilir ancak kullanılacak verilerin DataSet’e aktarılması gerekmektedir. Bu işlem için, SQL Server üzerindeki verileri, DataSet’e aktarmak için köprü görevi gören DataAdapter nesnesini kullanırız. Sunucu üzerindeki veri kaynağını bir SQL ifadesi, tablo adı, view veya stored procedure adı ile belirtebiliriz. DataAdapter nesnesinin iki ana görevi vardır. Birincisi, veri kaynağındaki verileri DataSet’e aktarır. Bu bölümde ilk olarak bu rolün üzerinde duracağız. İkinci olarakta local DataSet’teki güncellemeleri veri kaynağı ile senkronize etmek. Bu rolün üzerinde ise bu bölümün ikinci yarısında duracağız.
Veri kaynağından seçilecek verileri belirlemek için DataAdapter nesnesinin SelectCommand özelliğine ilgili SQL ifadesini yazarız. Veri kaynağındaki verileri DataSet’e DataAdapter nesnesinin Fill metodunu kullanarak aktarırız. Bu metod iki arguman kullanır. Birincisi verilerin aktarılacak DataSet’in adı, ikinci olarak kullanılacak DataSet’te verilerin kopyalanacağı tablo adı. DataSet içindeki tablolara, belirttiğiniz isimler ile erişebileceğiniz gibi index değerleriyle de (ilk eklenen tablo çin 0, sonraki her tablo için 1 artar) erişebilirsiniz.
Aşağıdaki örnek prosedür, DataAdapter nesnesi ve Command nesnesi kullanarak bir DataSet’in nasıl kullanılabileceğini göstermektedir.
DataSet nesnesini modül seviyesinde tanımlıyoruz
Böylece modül içindeki her yerden erişilebilecek
Dim ds As New DataSet
Sub Populate()
DataAdapter tarafından kullanılacak
Northwind veritabanı bağlantısı
Dim c As New SqlConnection _
("Data Source=(local);" & _
"Integrated Security=SSPI;" & _
"Initial Catalog=northwind")
DataSet için veri kaynağı görevi görecek olan
Command ve DataAdapter nesnelerini tanımlıyoruz
Dim cmd As SqlCommand = _
New SqlCommand _
("SELECT CategoryID, CategoryName, Description " & _
"FROM Categories", _
c)
DataAdapter nesnesini tanımlıyoruz
Dim da As New SqlDataAdapter
DataAdapter nesnesinin SelectCommand özelliğine
Oluşturduğumuz SqlCommand nesnesini atıyoruz
da.SelectCommand = cmd
Bağlantıyı açıyoruz
c.Open()
DataAdapterı kullanarak DataSetin (ds) içinde
Categories adlı bir tablo oluşturuyoruz ve Select
ifadesinin çalıştırılması sonucu dönen sonuç kümesini
Bu tabloya aktarıyoruz
da.Fill(ds, "Categories")
DataSet ile çalışmak için aktif bir
bağlantıya ihtiyaç duymadığımız için
Veritabanı bağlantısını kapatıyoruz
c.Close()
End Sub
Bu noktadan sonra ds adlı DataSet form üzerindeki her noktadan erişilebilir hale gelecektir. DataSet içindeki Categories adlı tablo kullanılarak veri üzerinde işlemler yapılabilir. Şimdi oluşturulan bir DataSet içindeki verilerin form üzerindeki kontrollere bağlanmasını görelim..
Verinin Form Kontrollerine Bağlanması Verileri DataSet’e aktardıktan sonra Form üzerideki kontrollerde bu verileri görüntülemek istediğimizi söyledik. Bu işi gerçekleştirmek için iki temel yöntem vardır. Simple Data Binding yönteminde yerel veri kaynağındaki (örneğin DataSet içinde yer alan bir DataTable) bir sütunu bir kontrolün istenilen özelliğine örneğin TextBox kontrolünün Text özelliğine bağlar. Yerel veri kaynağındaki sütunlardan birini kontrolün istenilen özelliğine bağlamak için kontrolün DataBindings kolleksiyonunu kullanırız. Complex Data Binding ise kullanabileceğimiz diğer bir yöntemdir. Bu yöntemde kontrol (örneğin combobox, datagrid veya listbox) bir sütun kolleksiyonuna (örneğin DataSet içindeki DataTable) bağlanır. Bu bölümde her iki veri bağlama yönteminide örnekliyor olacağız ve bu örneklerde bir önceki bölümde oluşturduğumuz Populate adlı prosedürü kullanıyor olacağız. Aşağıdaki grafikte formumuzun tasarım ve çalışma aşamalarındaki görünümü yer almaktadır.
Şekil 4:1 – Formun tasarım ve çalışma zamanındaki görüntüleri
İlk olarak Form yüklenirken Populate adlı prosedürü çağırarak DataSet’in oluşturulmasını ve Form üzerindeki kontrollerin DataSet içindeki DataTable nesnesinin sütunlarına bağlanmasını sağlayacak kodları yazıyoruz...
Private Sub Form4_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Populate prosedürünü çağırarak DataSetin
oluşturulmasını ve verilerin DataSete
aktarılmasını sağlıyoruz
Populate()
TextBox kontrollerini DataSet içindeki
Categories tablosunun farklı sütunlarına
bağlıyoruz
TextBox1.DataBindings.Add _
(New Binding("Text", ds, "Categories.CategoryID"))
TextBox2.DataBindings.Add _
(New Binding("Text", ds, "Categories.Description"))
Combobox kontrolünüde Categories
tablosuna bağlıyoruz. DataSet sadece 1
tablo içerdiği için tablo indexi 0 oluyor
ComboBox1.DataSource = ds.Tables("Categories")
ComboBox1.DisplayMember = "CategoryName"
Birinci kayıda gidiliyor
Me.BindingContext(ds.Tables(0)).Position = 0
Daha sonra Combobox’ta yapılan seçim değiştiğinde Form üzerindeki kontrollerin, seçilen Kategorinin indexine göre görüntüledikleri verilerin güncellenmesini sağlayacak kodları yazıyoruz..
Private Sub ComboBox1_SelectedIndexChanged _
(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles ComboBox1.SelectedIndexChanged
Comboboxta seçilen Combobox elemanının
index değerine göre Form üzerindeki kontrollerin
görüntüledikleri kayıtlar değiştiriliyor
Me.BindingContext(ds, "Categories").Position _
= Me.ComboBox1.SelectedIndex
Karışık formlarla çalışırken simple data binding kullandığımız durumlarda (özellikle bizim hazırlamadığımız formlar üzerinde çalışmamız gerektiğinde) DataBinding raporu almak formu analiz etmemizi son derece kolaylaştıracaktır. Örneğimizdeki button bizim form’un databinding kolleksiyonunun raporunu almamızı sağlayacak kodları içerecek.
Aşağıdaki prosedür (PrintBindingMemberInfo) parametre olarak bir formun referansını alır ve iki adet döngü çalıştırır. Birinci döngüde form üzerindeki kontrolleri, ikinci döngüde ise birincei döngüden dönen kontrollerin DataBinding özelliğini sırayla kontrol eder ve rapor için hazırlar.
Sub PrintBindingMemberInfo(ByRef f As Form)
Dim c As Control
Dim s As String
For Each c In f.Controls
Dim t As Binding
For Each t In c.DataBindings
Görüntülenecek rapor hazırlanıyor
s = s & ControlChars.Cr + c.ToString()
Dim bInfo As BindingMemberInfo = t.BindingMemberInfo
s = s & "Binding Path " + ControlChars.Tab + bInfo.BindingPath
s = s & "Binding Field " + ControlChars.Tab + bInfo.BindingField
s = s & "Binding Member " + ControlChars.Tab + bInfo.BindingMember
s = s & ControlChars.CrLf
Next t
Next c
MsgBox(s)
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
raporu oluşturacak prosedürü çağırıyor ve
parametre olarak aktif formu temsilen Me
değerini gönderiyoruz
PrintBindingMemberInfo(Me)
Bu kodları ekledikten sonra Button1 tıklandığında karşımız gelecek rapor aşağıdaki gibi olacaktır.
Şekil 4:2 – DataBinding Raporu
Bu prosedür aynı zamanda aktif olmayan formlar içind de kullanılabilir. Aşağıdaki prosedür Form1 üzerinden Form2’ye ait DataBinding raporu alabilmemizi sağlamaktadır.
Sub Form2DataBindingRaporu()
Dim f As New Form2
PrintBindingMemberInfo(f)
DataSet’in Parent-Child İlişkili Tablolar ile Birlikte Kullanımı
Tek bir tablo ile çalışabileceğimiz gibi DataSet içinde birden çok sayıda DataTable’da oluşturabiliriz. ADO.NET, ado gibi tüm kayıtları tek bir sonuç kümesinde birleştirmek yerinde birden çok DataTable arasındaki ilişkiyi hiyerarşik olarak tanımlamanıza olanak sağlıyor. Bu bölümde iki DataTable nesnesi içeren bir DataSet ile çalışma konusunu ele alacağız. Ek olarak DataGrid’de görüntülenen kayıtların kontrol edilmesi için bir ComboBox kontrolünün kullanımını görüyor olacağız. DataGrid’de görüntülenecek kayıtların ComboBox’a göre filtrelenmesi işlemini gerçekleştirebilmek için DataView kullanacağız. DataView nesnesi, Datagrid için DataSource olacaktır.
Aşağıdaki grafiklerde örneğimizin form tasarımını ve çalışma zamanı görüntülerini görebilirsiniz.
Şekil 4:3 – Tasarım Görünümü
Şekil 4:4 – Çalışma Zamanı Görünümü
Bu örnekte kullandığımız DataSet nesnesi Products ve Categories DataTable nesneleri arasında bir ilişki tanımlar. Aşağıda, örneğin adım adım kodlarını açıklamalarıyla birlikte görebilirsiniz:
Modül seviyesinde tanımlamalar
DataSet, DataView ve DataRelation
nesnelerimizi tanımlıyoruz
Dim das1 As DataSet
Dim dav1 As DataView
Dim rel1 As DataRelation
Dim cnn1 As SqlConnection = _
New SqlConnection _
DataAdaptera DataSete aktaracağı verileri
aktaracak bir command nesnesi oluşturuyor
ve sorgu ifademizi yazıyoruz
Dim cmd1 As SqlCommand = _
cnn1)
Dim dap1 As SqlDataAdapter = New SqlDataAdapter
DataAdapter nesnesinin SelectCommand
özelliğine cmd1 Command nesnesini atıyoruz
dap1.SelectCommand = cmd1
cnn1.Open()
DataAdapter nesnesinin Fill metodunu kullanarak
Northwind veritabanından gelen verileri
DataSette oluşturduğumuz Categories
adlı DataTablea aktarıyoruz
das1 = New DataSet
dap1.Fill(das1, "Categories")
Products tablosundan yapacağımız sorgulama için
SQL ifadesini yeniden belirtiyoruz
cmd1.CommandText = "SELECT CategoryID, ProductID, " & _
"ProductName, UnitsInStock, Discontinued " & _
"FROM Products"
DataSet içinde Products adlı yeni bir
DataTable oluşturuyor ve DataAdapterın Fill
metodu ile ikinci sonuç kümesini bu tabloya
aktarıyoruz
dap1.Fill(das1, "Products")
Bağlantıyı kapatıyoruz
cnn1.Close()
Sub RelateProductsToCategories()
DataSet içindeki Products ve Categories adlı
datatablelar için ilişki kuracağımız
Parent ve child sütunları tanımlıyoruz
Dim parentcol As DataColumn
Dim childcol As DataColumn
parentcol = das1.Tables("Categories").Columns("CategoryID")
childcol = das1.Tables("Products").Columns("CategoryID")
DataRelation oluşturuyoruz
rel1 = New DataRelation _
("CategoriesProducts", parentcol, childcol)
das1.Relations.Add(rel1)
Seçilen ComboBox elemanına göre DataView
üzerinde filtreleme yapıyoruz
Dim strFilter = "CategoryID = " & _
(ComboBox1.SelectedIndex + 1).ToString
dav1.RowFilter = strFilter
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Form yüklenirken ilk olarak Populate prosedürünü çalıştırıyoruz
Daha sonra ilişkilerin kurulduğu
RelateProductsToCategories prosedürünü çağırıyoruz
RelateProductsToCategories()
ComboBox kontrolünü 0 indexli tabloya yani
Categories tablosuna bağlıyoruz
ComboBox1.DataSource = das1.Tables(0)
Me.BindingContext(das1.Tables(0)).Position = 0
Products tablosuna dayanan yeni bir DataView oluşturuyor
ve ComboBoxın SelectedIndex değerine bağlı olarak
bir filtre oluşturuyoruz
dav1 = New DataView(das1.Tables("Products"))
DataViewı DataGrid için DataSource olarak belirtiyoruz
DataGrid1.DataSource = dav1
Buraya kadar tek bir form üzerinde veri işlemleri gerçekleştirdik. Bölümün sonunda birden çok form içeren uygulamalarda veritabanı işlemlerini nasıl gerçekleştirebileceğimizi gösteren bir uygulama geliştireceğiz.
Çoklu Formlarda Veritabanı İşlemleri Bölümün sonunda iki form içeren ve yine verinin kontrollere bağlanmasına dair örnekler içeren bir uygulama geliştireceğiz.
Bu bölümdeki uygulama ayrı ayrı gerçekleştirdiğimiz bazı işlemlerin bir arada kullanımına örnek teşkil etmesi açısındanda önemlidir. Uygulamamızın birinci formunda bir il seçimi gerçekleştiriliyor. Birinci formda comboboxtan yapılan bu seçim button’un tıklanması ile ikinci forma gönderiliyor. İkinci form gelen parametreye bağlı olarak iki DataTable nesnesi oluşturuyor. Birinci DataTable’da gönderilen değer bir stored procedure’un çalıştırılması için parametre olarak kullanılıyor. İkinci DataTable ise yine gönderilen parametreye göre oluşturulan bir SQL ifadesine bağlı olarak çalıştırılıyor. Bu tablo ikinci formda bulunan textboxları doğrudan güncellemez, bunun yerine metin kutularını ikinci DataTable nesnesine dayanan DataView nesnesine bağlıyoruz ancak comboboxta yapılan seçime bağlı olarak filtreliyoruz.
Örneği geliştirmeye başlamadan önce kullanacağımız stored procedure’u hazırlamamız gerekiyor. Kodlar aşağıdaki gibi..
--Northwind veritabanı ile çalışıyoruz.
USE Northwind
GO
--udpCitiesInCustomersCountry
-- adında bir SP varsa siliyoruz
IF EXISTS (SELECT ROUTINE_NAME
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_TYPE = PROCEDURE AND
ROUTINE_NAME = udpCitiesInCustomersCountry)
DROP PROCEDURE udpCitiesInCustomersCountry
--udpCitiesInCustomersCountry adlı SP’yi oluşturuyoruz
CREATE PROC udpCitiesInCustomersCountry
@country nvarchar (15) = USA
AS
SELECT DISTINCT City
FROM Customers
WHERE Country = @country
Formlarımızın tasarım aşamasındaki görünümleri ise aşağıdaki gibidir.
Şekil 4:5 – Tasarım Görünümü
Birinci formun kodları ve açıklamaları aşağıdaki gibidir.
Private Sub Form3_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Close düğmesinin görüntülenmemesini
sağlamak için border stilini değiştiriyoruz
Me.FormBorderStyle = FormBorderStyle.None
Dim f As New Form4
İkinci formdaki Country değişkenine
Metin kutusundaki değeri atıyoruz
f.Country = TextBox1.Text
İkinci formu aç ve bu formu gizle
f.Show()
Me.Hide()
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
Uygulamayı kapat.
Application.Exit()
İkinci formun (örnek projemde Form4 adlı form) kodları ve açıklamalar aşağıdaki gibidir:
DataSet ve DataView nesnelerimizi
Modül seviyesinde tanımlıyoruz
Dim das1 As New DataSet
Dim dav1 As New DataView
Form Load eventinde Combobox1i değişikliklere
karşı denetleyecek boolean değişken
Dim bolViewSetInFormLoad As Boolean
Country değişkenini Public olarak tanımlıyoruz
Böylece birinci formdan değer atayabileceğiz
Public Country As String
Northwind bağlantısı
New SqlConnection("Data Source=(local);" & _
udpCitiesInCustomersCountry adlı SPyi çalıştıracak
Command nesnesini oluşturuyoruz
New SqlCommand("udpCitiesInCustomersCountry", cnn1)
cmd1.CommandType = CommandType.StoredProcedure
SqlDbType ile Command için parametre tanımlıyor ve
Country adlı public değişkene birinci formdan gelen
değere bağlı olarak değer atıyoruz
Dim prm1 As SqlParameter = _
cmd1.Parameters.Add("@country", SqlDbType.NVarChar, 15)
prm1.Value = Country
Oluşturduğumuz command nesnesini DataAdapter nesnesi için
SelectCommand özelliğine atıyoruz
Fill the data set das1 with the data adapter dap1;
the Fill method populates the data set with the
udpCitiesInCustomersCountry result set and names
the resulting datatable CitiesInCountry.
DataAdapterı kullanarak Oluşturduğumuz DataSetin
içinde CitiesnCountry adlı bir DataTable oluşturuyor
ve sonuç kümesini bu DataTablea aktarıyoruz
dap1.Fill(das1, "CitiesInCountry")
Command nesnesinin Commandtext özelliğine bir
SQL ifadesi atıyor, CommandType özelliğinin değerini
Text olarak değiştiriyor ve yeni sorgu için hazır
hale getiriyoruz
cmd1.CommandText = "SELECT CustomerID, " & _
"ContactName, Phone, City " & _
"FROM Customers " & _
"WHERE Country = " & Country & ""
Eklediğimiz parametreyi kaldırıyoruz
cmd1.Parameters.Remove(prm1)
cmd1.CommandType = CommandType.Text
Yeni SQL ifadesinin sonucunda dönen sonuç kümesini
CustomersInCountry adlı ikinci DataTable nesnesine
dap1.Fill(das1, "CustomersInCountry")
Private Sub Form4_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Form yüklenirken Populate adlı prosedürü
çalıştırıyoruz
Comboboxı DataSet içindeki birinci
DataTablea bağlıyoruz. ComboBoxın displaymember
ve valuemember değerlerini DataTabledaki birinci
sütuna eşitliyoruz
MsgBox(das1.Tables.Count)
ComboBox1.DisplayMember = _
das1.Tables(0).Columns(0).ColumnName
ComboBox1.ValueMember = _
CustomersInCountry DataTable nesnesine bağlı olarak
bir DataView nesnesi oluşturuyoruz ve form açıldığında
ComboBoxtaki seçili değer bağlı olarak filtreleme yapıyoruz
dav1 = New DataView(das1.Tables("CustomersInCountry"))
Dim strFilter = "City = " & ComboBox1.SelectedValue & ""
Form Load eventi DataViewin filtresini belirledikten sonra
bolViewSetInFormLoad değişkeninin değerini varsayılan
False değerinden True olarak değiştiriyoruz
bolViewSetInFormLoad = True
Metin kutularını DataViewdeki ilgili
alanlara bağlıyoruz
(New Binding("Text", dav1, "CustomerID"))
(New Binding("Text", dav1, "ContactName"))
TextBox3.DataBindings.Add _
(New Binding("Text", dav1, "Phone"))
Navigasyon butonlarını görüntüleyip görüntülemeyeceğimizi
DataViewde yer alan satır sayısı belirleyecek
ShowNavButtons(dav1.Count)
Formun kapat butonu dışında bir yöntemle kapatılmasını
önlemek için ControlBox,MinimizeBox ve Maximizebox
özelliklerini false olarak belirliyoruz
Me.MinimizeBox = False
Me.MaximizeBox = False
Me.ControlBox = False
Sub ShowNavButtons(ByVal NavNum As Integer)
Eğer seçilen şehirde birden çok müşteri varsa
Navigasyon butonlarını aktif hale getiriyoruz
If NavNum > 1 Then
Button1.Visible = True
Button2.Visible = True
Button3.Visible = True
Button4.Visible = True
Else
Button1.Visible = False
Button2.Visible = False
Button3.Visible = False
Button4.Visible = False
End If
ComboBoxta yapılacak seçime bağlı olarak
DataViewin Filtresini güncelliyoruz
If bolViewSetInFormLoad = True Then
Dim strFilter = "City = " & _
ComboBox1.SelectedValue & ""
### Navigasyon Butonları ###
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Birinci kayıt görüntülenir
Me.BindingContext(dav1).Position _
= Me.BindingContext(dav1).Position.MinValue
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Bir önceki kayıt
Me.BindingContext(dav1).Position -= 1
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Bir sonraki kayıt
Me.BindingContext(dav1).Position += 1
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
Son kayıt görüntülenir
= Me.BindingContext(dav1).Position.MaxValue
### kapat ###
Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
Uygulamayı Kapat
Uygulamanın çalışma zamanındaki görünümü ise şu şekilde;
Şekil 4:6 – Uygulamanın Çalışma Zamanı Görüntüleri
Bir sonraki bölümde, ADO.NET ile verileri silme, düzenleme ve yeni veri ekleme konularını ele alıyor olacağız.. Kadir SÜMERKENT kadirs@yazgelistir.com