Veritabanı Değişikliklerini Bir İşlemin İçinde Sarmalama (VB)
tarafından Scott Mitchell
Bu öğretici, veri toplu işlemlerini güncelleştirme, silme ve ekleme konularına bakan dört öğreticiden ilkidir. Bu öğreticide, veritabanı işlemlerinin toplu değişikliklerin atomik bir işlem olarak gerçekleştirilmesini nasıl sağladığını ve bu sayede tüm adımların başarılı veya tüm adımların başarısız olmasını sağladığını öğreniriz.
Giriş
Veri Ekleme, Güncelleştirme ve Silmeye Genel Bakış öğreticisiyle başladığımızı gördüğümüz gibi GridView satır düzeyi düzenleme ve silme için yerleşik destek sağlar. Farenin birkaç tıklamasıyla, satır başına düzenleme ve silme işlemiyle memnun olduğunuz sürece, bir kod satırı yazmadan zengin veri değiştirme arabirimi oluşturmak mümkündür. Ancak, bazı senaryolarda bu yetersizdir ve kullanıcılara bir grup kaydı düzenleme veya silme olanağı sağlamamız gerekir.
Örneğin, web tabanlı e-posta istemcilerinin çoğu, her satırın e-posta bilgileri (konu, gönderen vb.) ile birlikte bir onay kutusu içerdiği her iletiyi listelemek için bir kılavuz kullanır. Bu arabirim, kullanıcının birden çok iletiyi denetleyerek ve ardından Seçili İletileri Sil düğmesine tıklayarak silmesine izin verir. Toplu düzenleme arabirimi, kullanıcıların yaygın olarak birçok farklı kaydı düzenlediği durumlarda idealdir. Kullanıcıyı Düzenle'ye tıklamaya zorlamak, değişikliklerini yapmak ve ardından değiştirilmesi gereken her kayıt için Güncelleştir'e tıklamak yerine, toplu düzenleme arabirimi her satırı düzenleme arabirimiyle işler. Kullanıcı değiştirilmesi gereken satır kümesini hızla değiştirebilir ve ardından Tümünü Güncelleştir düğmesine tıklayarak bu değişiklikleri kaydedebilir. Bu öğretici kümesinde, veri toplu işlemlerini eklemek, düzenlemek ve silmek için arabirimlerin nasıl oluşturulacağını inceleyeceğiz.
Toplu işlem gerçekleştirirken, toplu işteki bazı işlemlerin başarılı olması ve diğerleri başarısız olması gerekip gerekmediğini saptamak önemlidir. Toplu silme arabirimini göz önünde bulundurun- seçilen ilk kayıt başarıyla silinirse, ancak ikinci kayıt örneğin yabancı anahtar kısıtlaması ihlali nedeniyle başarısız olursa ne olur? İlk kaydın silinmesi geri alınsın mı yoksa ilk kaydın silinmeye devam etmesi kabul edilebilir mi?
Toplu işlemin, tüm adımların başarılı veya tüm adımların başarısız olduğu atomik bir işlem olarak değerlendirilmesini istiyorsanız, veritabanı işlemlerine yönelik desteği içerecek şekilde Veri Erişim Katmanının genişletilmesi gerekir. Veritabanı işlemleri, işlemin çatısı altında yürütülen , UPDATE
ve DELETE
deyimleri kümesi INSERT
için bölünmezliği garanti eder ve tüm modern veritabanı sistemlerinin çoğu tarafından desteklenen bir özelliktir.
Bu öğreticide, DAL'yi veritabanı işlemlerini kullanacak şekilde genişletmeyi inceleyeceğiz. Sonraki öğreticilerde, arabirimleri toplu ekleme, güncelleştirme ve silme için web sayfalarının uygulanması incelenir. Haydi başlayalım!
Not
Bir toplu işlemdeki verileri değiştirirken, bölünmezlik her zaman gerekli değildir. Bazı senaryolarda, web tabanlı bir e-posta istemcisinden bir dizi e-postayı silerken bazı veri değişikliklerinin başarılı olması ve aynı toplu işlemdeki diğerlerinin başarısız olması kabul edilebilir. Silme işleminin ortasında bir veritabanı hatası varsa, hata olmadan işlenen bu kayıtların silinmeye devam ettiği kabul edilebilir. Böyle durumlarda DAL'nin veritabanı işlemlerini desteklemek için değiştirilmesi gerekmez. Ancak bölünmezliğin hayati önem taşıdığı başka toplu işlem senaryoları da vardır. Bir müşteri fonlarını bir banka hesabından diğerine taşırken iki işlem yapılmalıdır: fonlar ilk hesaptan düşülmeli ve sonra ikincisine eklenmelidir. Banka ilk adımın başarılı olmasına rağmen ikinci adımın başarısız olmasına rağmen müşterileri açıkça üzülecek. Bu öğreticide çalışmanızı ve aşağıdaki üç öğreticide oluşturacağımız arabirimleri toplu ekleme, güncelleştirme ve silme işlemlerinde kullanmayı planlamıyor olsanız bile veritabanı işlemlerini desteklemeye yönelik DAL geliştirmelerini uygulamanızı öneririz.
İşlemlere Genel Bakış
Çoğu veritabanı, birden çok veritabanı komutlarının tek bir mantıksal iş birimi halinde gruplandırılabilmesini sağlayan işlemlere yönelik destek içerir. Bir işlemi oluşturan veritabanı komutlarının atomik olduğu garanti edilir; bu da tüm komutların başarısız olacağı veya tümünün başarılı olacağı anlamına gelir.
Genel olarak, işlemler aşağıdaki desen kullanılarak SQL deyimleri aracılığıyla uygulanır:
- İşlemin başlangıcını belirtin.
- İşlemi oluşturan SQL deyimlerini yürütür.
- 2. Adımdaki deyimlerden birinde hata varsa işlemi geri alın.
- 2. Adımdaki tüm deyimler hatasız tamamlanırsa işlemi işleyin.
İşlemi oluşturmak, işlemek ve geri almak için kullanılan SQL deyimleri, SQL betikleri yazarken veya saklı yordam oluştururken ya da ad alanında ADO.NET veya sınıfları System.Transactions
kullanarak programlama yoluyla el ile girilebilir. Bu öğreticide yalnızca ADO.NET kullanarak işlemleri yönetmeyi inceleyeceğiz. Gelecekteki bir öğreticide Veri Erişim Katmanı'nda saklı yordamların nasıl kullanılacağına bakacağız. Bu aşamada işlemleri oluşturmak, geri almak ve işlemek için SQL deyimlerini inceleyeceğiz. Bu arada, daha fazla bilgi için SQL Server Saklı Yordamlarda İşlemleri Yönetme bölümüne bakın.
Not
TransactionScope
Ad alanında sınıfıSystem.Transactions
, geliştiricilerin bir işlem kapsamında bir dizi deyimi program aracılığıyla sarmalamalarına olanak tanır ve microsoft SQL Server veritabanı, Oracle veritabanı ve Web hizmeti gibi iki farklı veritabanı ve heterojen veri deposu türleri gibi birden çok kaynak içeren karmaşık işlemler için destek içerir. ADO.NET veritabanı işlemleri için daha özel olduğundan ve çoğu durumda kaynak açısından çok daha az yoğun olduğundan, bu öğretici için sınıf yerine TransactionScope
ADO.NET işlemleri kullanmaya karar verdim. Ayrıca, bazı senaryolarda TransactionScope
sınıfı Microsoft Dağıtılmış İşlem Düzenleyicisi'ni (MSDTC) kullanır. MSDTC'yi çevreleyen yapılandırma, uygulama ve performans sorunları, onu oldukça özelleştirilmiş ve gelişmiş bir konu haline getirir ve bu öğreticilerin kapsamının dışındadır.
ADO.NET'da SqlClient sağlayıcısıyla çalışırken, işlemler bir nesnesi döndüren SqlTransaction
sınıf BeginTransaction
yöntemineSqlConnection
yapılan bir çağrı aracılığıyla başlatılır. İşlemin yapısını oluşturan veri değiştirme deyimleri bir try...catch
blok içine yerleştirilir. Bloktaki bir deyimde try
hata oluşursa, yürütme işlemi nesnesinin catch
Rollback
yöntemi aracılığıyla SqlTransaction
geri alınabileceği bloğa aktarır. Deyimlerin tümü başarıyla tamamlanırsa, bloğunun SqlTransaction
sonundaki nesnenin Commit
yöntemine yapılan try
bir çağrı işlemi işler. Aşağıdaki kod parçacığında bu desen gösterilmektedir.
' Create the SqlTransaction object
Dim myTransaction As SqlTransaction = SqlConnectionObject.BeginTransaction();
Try
'
' ... Perform the database transaction�s data modification statements...
'
' If we reach here, no errors, so commit the transaction
myTransaction.Commit()
Catch
' If we reach here, there was an error, so rollback the transaction
myTransaction.Rollback()
Throw
End Try
Varsayılan olarak, Yazılan Veri Kümesindeki TableAdapters işlemleri kullanmaz. İşlemler için destek sağlamak için TableAdapter sınıflarını, bir işlem kapsamında bir dizi veri değiştirme deyimi gerçekleştirmek üzere yukarıdaki deseni kullanan ek yöntemleri içerecek şekilde artırmamız gerekir. 2. Adımda, bu yöntemleri eklemek için kısmi sınıfların nasıl kullanılacağını göreceğiz.
1. Adım: Toplu VeriLerle Çalışma Web Sayfaları Oluşturma
DAL'yi veritabanı işlemlerini destekleyecek şekilde nasıl genişletebileceğimizi keşfetmeye başlamadan önce, önce bu öğretici için ihtiyacımız olacak ASP.NET web sayfalarını ve ardından gelen üç sayfayı oluşturalım. adlı BatchData
yeni bir klasör ekleyerek başlayın ve ardından aşağıdaki ASP.NET sayfaları ekleyerek her sayfayı ana sayfayla ilişkilendirin Site.master
.
Default.aspx
Transactions.aspx
BatchUpdate.aspx
BatchDelete.aspx
BatchInsert.aspx
Şekil 1: SqlDataSource-Related Öğreticileri için ASP.NET Sayfaları Ekleme
Diğer klasörlerde olduğu gibi, Default.aspx
bölümündeki öğreticileri listelemek için Kullanıcı Denetimi'ni kullanır SectionLevelTutorialListing.ascx
. Bu nedenle, bu Kullanıcı Denetimini Default.aspx
Çözüm Gezgini sayfanın Tasarım görünümüne sürükleyerek öğesine ekleyin.
Şekil 2: Kullanıcı Denetimini ekleme SectionLevelTutorialListing.ascx
Default.aspx
(Tam boyutlu görüntüyü görüntülemek için tıklayın)
Son olarak, bu dört sayfayı dosyaya Web.sitemap
girdi olarak ekleyin. Özellikle, Site Haritasını <siteMapNode>
Özelleştirme'nin ardından aşağıdaki işaretlemeyi ekleyin:
<siteMapNode title="Working with Batched Data"
url="~/BatchData/Default.aspx"
description="Learn how to perform batch operations as opposed to
per-row operations.">
<siteMapNode title="Adding Support for Transactions"
url="~/BatchData/Transactions.aspx"
description="See how to extend the Data Access Layer to support
database transactions." />
<siteMapNode title="Batch Updating"
url="~/BatchData/BatchUpdate.aspx"
description="Build a batch updating interface, where each row in a
GridView is editable." />
<siteMapNode title="Batch Deleting"
url="~/BatchData/BatchDelete.aspx"
description="Explore how to create an interface for batch deleting
by adding a CheckBox to each GridView row." />
<siteMapNode title="Batch Inserting"
url="~/BatchData/BatchInsert.aspx"
description="Examine the steps needed to create a batch inserting
interface, where multiple records can be created at the
click of a button." />
</siteMapNode>
güncelleştirdikten Web.sitemap
sonra, öğreticiler web sitesini bir tarayıcı üzerinden görüntülemek için biraz zaman ayırın. Sol taraftaki menüde artık toplu verilerle çalışma öğreticileri için öğeler yer alır.
Şekil 3: Site Haritası Artık Toplu Verilerle Çalışma Öğreticileri için Girdiler Içeriyor
2. Adım: Veri Erişim Katmanını Veritabanı İşlemlerini Destekleyecek Şekilde Güncelleştirme
İlk öğreticide( Veri Erişim Katmanı Oluşturma) değindiğimiz gibi DAL'mizdeki Typed DataSet, DataTables ve TableAdapters'lardan oluşur. TableAdapters verileri tutarken, TableAdapters veritabanından DataTable'lara veri okuma, veritabanını DataTable'larda yapılan değişikliklerle güncelleştirme gibi işlevler sağlar. TableAdapters'ın verileri güncelleştirmek için batch update ve DB-Direct olarak adlandırılan iki desen sağladığını hatırlayın. Batch Update düzeniyle TableAdapter'a DataSet, DataTable veya DataRows koleksiyonu geçirilir. Bu veriler numaralandırılır ve eklenen, değiştirilen veya silinen her satır InsertCommand
için , UpdateCommand
veya DeleteCommand
yürütülür. DB-Direct deseni ile TableAdapter bunun yerine tek bir kaydı eklemek, güncelleştirmek veya silmek için gereken sütunların değerlerine geçirilir. Db Doğrudan desen yöntemi daha sonra uygun InsertCommand
, UpdateCommand
veya DeleteCommand
deyimini yürütmek için bu geçirilen değerleri kullanır.
Kullanılan güncelleştirme deseni ne olursa olsun, TableAdapters otomatik olarak oluşturulan yöntemler işlemleri kullanmaz. Varsayılan olarak TableAdapter tarafından gerçekleştirilen her ekleme, güncelleştirme veya silme işlemi tek bir ayrık işlem olarak kabul edilir. Örneğin, DB-Direct deseninin veritabanına on kayıt eklemek için BLL'deki bir kod tarafından kullanıldığını düşünün. Bu kod TableAdapter Insert
yöntemini on kez çağırır. İlk beş ekleme başarılı olursa, ancak altıncısı özel durumla sonuçlanırsa, eklenen ilk beş kayıt veritabanında kalır. Benzer şekilde, Batch Update düzeni DataTable'da eklenen, değiştirilen ve silinen satırlara ekleme, güncelleştirme ve silme işlemleri gerçekleştirmek için kullanılırsa, ilk birkaç değişiklik başarılı olduysa ancak daha sonra bir hatayla karşılaşırsa, tamamlanan önceki değişiklikler veritabanında kalır.
Bazı senaryolarda, bir dizi değişiklikte bölünmezlik sağlamak istiyoruz. Bunu başarmak için, UpdateCommand
, ve DeleteCommand
'lerini bir işlemin şemsiyesi altında yürüten InsertCommand
yeni yöntemler ekleyerek TableAdapter'ı el ile genişletmemiz gerekir. Veri Erişim Katmanı Oluşturma bölümünde, Yazılan DataSet içindeki DataTable'ların işlevselliğini genişletmek için kısmi sınıflar kullanmayı inceledik. Bu teknik TableAdapters ile de kullanılabilir.
Yazılan Veri Kümesi Northwind.xsd
klasörün DAL
alt klasöründe App_Code
bulunur. adlı klasörde bir alt klasör DAL
oluşturun ve adlı TransactionSupport
ProductsTableAdapter.TransactionSupport.vb
yeni bir sınıf dosyası ekleyin (bkz. Şekil 4). Bu dosya, bir işlem kullanarak veri değişiklikleri gerçekleştirme yöntemlerini içeren kısmi uygulamasını ProductsTableAdapter
tutar.
Şekil 4: Adlı Bir Klasör ve Adlandırılmış TransactionSupport
Sınıf Dosyası Ekleme ProductsTableAdapter.TransactionSupport.vb
Dosyaya ProductsTableAdapter.TransactionSupport.vb
aşağıdaki kodu girin:
Imports System.Data
Imports System.Data.SqlClient
Namespace NorthwindTableAdapters
Partial Public Class ProductsTableAdapter
Private _transaction As SqlTransaction
Private Property Transaction() As SqlTransaction
Get
Return Me._transaction
End Get
Set(ByVal Value As SqlTransaction)
Me._transaction = Value
End Set
End Property
Public Sub BeginTransaction()
' Open the connection, if needed
If Me.Connection.State <> ConnectionState.Open Then
Me.Connection.Open()
End If
' Create the transaction and assign it to the Transaction property
Me.Transaction = Me.Connection.BeginTransaction()
' Attach the transaction to the Adapters
For Each command As SqlCommand In Me.CommandCollection
command.Transaction = Me.Transaction
Next
Me.Adapter.InsertCommand.Transaction = Me.Transaction
Me.Adapter.UpdateCommand.Transaction = Me.Transaction
Me.Adapter.DeleteCommand.Transaction = Me.Transaction
End Sub
Public Sub CommitTransaction()
' Commit the transaction
Me.Transaction.Commit()
' Close the connection
Me.Connection.Close()
End Sub
Public Sub RollbackTransaction()
' Rollback the transaction
Me.Transaction.Rollback()
' Close the connection
Me.Connection.Close()
End Sub
End Class
End Namespace
Partial
Buradaki sınıf bildirimindeki anahtar sözcük derleyiciye, içinde eklenen üyelerin ad alanında sınıfa ProductsTableAdapter
NorthwindTableAdapters
ekleneceğini belirtir. Imports System.Data.SqlClient
Dosyanın en üstündeki deyimine dikkat edin. TableAdapter SqlClient sağlayıcısını kullanacak şekilde yapılandırıldığından, veritabanına komutlarını vermek için dahili olarak bir SqlDataAdapter
nesnesi kullanır. Sonuç olarak, işlemi başlatmak ve ardından işlemek veya geri almak için sınıfını kullanmamız SqlTransaction
gerekir. Microsoft SQL Server dışında bir veri deposu kullanıyorsanız uygun sağlayıcıyı kullanmanız gerekir.
Bu yöntemler bir işlemi başlatmak, geri almak ve işlemek için gereken yapı taşları sağlar. İşaretlenir, Public
dal içindeki başka bir sınıftan ProductsTableAdapter
veya mimarideki BLL gibi başka bir katmandan kullanılmasını sağlar. BeginTransaction
TableAdapter'ın iç SqlConnection
öğesini açar (gerekirse), işlemi başlatır ve özelliğine Transaction
atar ve işlemi iç SqlDataAdapter
s SqlCommand
nesnelerine ekler. CommitTransaction
ve RollbackTransaction
iç Connection
nesneyi kapatmadan önce sırasıyla s Commit
nesnesini ve Rollback
yöntemlerini çağırınTransaction
.
3. Adım: İşlem Kapsamında Verileri Güncelleştirme ve Silme Yöntemleri Ekleme
Bu yöntemler tamamlandıktan sonra, bir işlem şemsiyesi altında bir dizi komut gerçekleştiren veya BLL'ye ProductsDataTable
yöntem eklemeye hazırız. Aşağıdaki yöntem, bir işlemi kullanarak bir ProductsDataTable
örneği güncelleştirmek için Batch Update desenini kullanır. yöntemini çağırarak BeginTransaction
bir işlem başlatır ve ardından veri değişikliği deyimlerini vermek için bir Try...Catch
blok kullanır. Nesnesinin Adapter
Update
yöntemine yapılan çağrı bir özel durumla sonuçlanırsa yürütme, işlemin geri alınacağı ve özel durumun yeniden oluşturulacağı bloğa aktarılır catch
. Yönteminin Update
, sağlanan ProductsDataTable
satırları numaralandırarak ve gerekli InsertCommand
, UpdateCommand
ve DeleteCommand
s değerlerini gerçekleştirerek Batch Update düzenini uyguladığını hatırlayın. Bu komutlardan herhangi biri hatayla sonuçlanırsa işlem geri alınır ve işlem ömrü boyunca yapılan önceki değişiklikler geri alınır. Update
Deyim hatasız tamamlanırsa, işlem tamamen işlenir.
Public Function UpdateWithTransaction _
(ByVal dataTable As Northwind.ProductsDataTable) As Integer
Me.BeginTransaction()
Try
' Perform the update on the DataTable
Dim returnValue As Integer = Me.Adapter.Update(dataTable)
' If we reach here, no errors, so commit the transaction
Me.CommitTransaction()
Return returnValue
Catch
' If we reach here, there was an error, so rollback the transaction
Me.RollbackTransaction()
Throw
End Try
End Function
UpdateWithTransaction
yöntemini ProductsTableAdapter
içindeki kısmi sınıfı aracılığıyla sınıfına ProductsTableAdapter.TransactionSupport.vb
ekleyin. Alternatif olarak, bu yöntem birkaç küçük söz dizimsel değişiklikle İş Mantığı Katmanı sınıfına ProductsBLL
eklenebilir. Yani , ve içindeki Me.CommitTransaction()
anahtar sözcüğü Me
ile değiştirilmesi Adapter
gerekir (türünde bir özelliğin ProductsTableAdapter
ProductsBLL
adı olduğunu Adapter
hatırlayın).Me.BeginTransaction()
Me.RollbackTransaction()
UpdateWithTransaction
yöntemi Batch Update desenini kullanır, ancak aşağıdaki yöntemin gösterdiği gibi işlem kapsamında bir dizi DB-Direct çağrısı da kullanılabilir. DeleteProductsWithTransaction
yöntemi, silinecek s türünde bir List(Of T)
Integer
giriş olarak kabul ederProductID
. yöntemi işlemi bir çağrısıyla BeginTransaction
başlatır ve blokta Try
her ProductID
değer için DB-Direct desen Delete
yöntemini çağıran sağlanan listede yinelenir. çağrısından Delete
herhangi biri başarısız olursa denetim, işlemin geri alındığı ve özel durumun yeniden oluştuğu bloğa aktarılır Catch
. Başarılı olmak için Delete
tüm çağrılar yapılırsa işlem tamamlanır. Bu yöntemi sınıfına ProductsBLL
ekleyin.
Public Sub DeleteProductsWithTransaction _
(ByVal productIDs As System.Collections.Generic.List(Of Integer))
' Start the transaction
Adapter.BeginTransaction()
Try
' Delete each product specified in the list
For Each productID As Integer In productIDs
Adapter.Delete(productID)
Next
' Commit the transaction
Adapter.CommitTransaction()
Catch
' There was an error - rollback the transaction
Adapter.RollbackTransaction()
Throw
End Try
End Sub
Birden Çok TableAdapter Arasında İşlem Uygulama
Bu öğreticide incelenen işlemle ilgili kod, öğesine karşı birden çok deyimin ProductsTableAdapter
atomik işlem olarak değerlendirilmesini sağlar. Peki farklı veritabanı tablolarında birden çok değişikliğin atomik olarak gerçekleştirilmesi gerekiyorsa ne olur? Örneğin, bir kategoriyi silerken önce geçerli ürünlerini başka bir kategoriye yeniden atamak isteyebiliriz. Ürünleri yeniden atamak ve kategoriyi silmek için bu iki adım atomik bir işlem olarak yürütülmelidir. Ancak, ProductsTableAdapter
yalnızca tabloyu değiştirme Products
yöntemlerini ve CategoriesTableAdapter
yalnızca tabloyu değiştirme Categories
yöntemlerini içerir. Peki bir işlem her iki TableAdapter'ı da nasıl kapsayabiliyor?
Bir seçenek, adlandırılmış DeleteCategoryAndReassignProducts(categoryIDtoDelete, reassignToCategoryID)
öğesine CategoriesTableAdapter
bir yöntem eklemek ve bu yöntemin hem ürünleri yeniden atadan hem de saklı yordam içinde tanımlanan bir işlem kapsamında kategoriyi silen saklı yordamı çağırmasını sağlamaktır. Sonraki bir öğreticide saklı yordamlarda işlemleri başlatma, işleme ve geri alma işlemlerini gözden geçireceksiniz.
Bir diğer seçenek de DAL'de yöntemini içeren bir yardımcı sınıf oluşturmaktır DeleteCategoryAndReassignProducts(categoryIDtoDelete, reassignToCategoryID)
. Bu yöntem ve öğesinin CategoriesTableAdapter
bir örneğini oluşturur ve ardından bu iki TableAdapters Connection
özelliğini aynı SqlConnection
örneğe ProductsTableAdapter
ayarlar. Bu noktada iki TableAdapter'den biri çağrısıyla BeginTransaction
işlemi başlatacak. Ürünleri yeniden atamak ve kategoriyi silmek için TableAdapters yöntemleri, işlem gerektiği gibi yürütülen veya geri alınan bir Try...Catch
blok halinde çağrılır.
4. Adım: İş Mantığı Katmanına Yöntemi EklemeUpdateWithTransaction
3. Adımda DAL'de öğesine ProductsTableAdapter
bir UpdateWithTransaction
yöntem ekledik. BLL'ye karşılık gelen bir yöntem eklemeliyiz. Sunu Katmanı, yöntemini çağırmak UpdateWithTransaction
için doğrudan DAL'yi çağırabilse de, bu öğreticiler DAL'yi Sunu Katmanı'ndan yalıtan katmanlı bir mimari tanımlamaya çalışır. Bu nedenle, bu yaklaşımı sürdürmek bizi teşvik eder.
ProductsBLL
Sınıf dosyasını açın ve yalnızca ilgili DAL yöntemine çağıran adlı UpdateWithTransaction
bir yöntem ekleyin. Artık içinde iki yeni yöntem ProductsBLL
olmalıdır: UpdateWithTransaction
yeni eklediğiniz ve DeleteProductsWithTransaction
3. Adımda eklenen .
Public Function UpdateWithTransaction _
(ByVal products As Northwind.ProductsDataTable) As Integer
Return Adapter.UpdateWithTransaction(products)
End Function
Public Sub DeleteProductsWithTransaction _
(ByVal productIDs As System.Collections.Generic.List(Of Integer))
' Start the transaction
Adapter.BeginTransaction()
Try
' Delete each product specified in the list
For Each productID As Integer In productIDs
Adapter.Delete(productID)
Next
' Commit the transaction
Adapter.CommitTransaction()
Catch
' There was an error - rollback the transaction
Adapter.RollbackTransaction()
Throw
End Try
End Sub
Not
Bu yöntemleri doğrudan ASP.NET sayfaları arka planda ProductsBLL
kod sınıflarından çağıracağımızdan, bu yöntemler sınıftaki diğer yöntemlerin çoğuna atanan özniteliği içermezDataObjectMethodAttribute
. DataObjectMethodAttribute
ObjectDataSource'un Veri Kaynağını Yapılandırma sihirbazında ve hangi sekmenin (SELECT, UPDATE, INSERT veya DELETE) altında hangi yöntemlerin görüneceğini işaretlemek için kullanıldığını hatırlayın. GridView'da toplu düzenleme veya silme için yerleşik destek olmadığından, kodsuz bildirim temelli yaklaşımı kullanmak yerine bu yöntemleri program aracılığıyla çağırmamız gerekir.
5. Adım: Sunu Katmanından Veritabanı Verilerini Atomik Olarak Güncelleştirme
Bir kayıt toplu işlemini güncelleştirirken işlemin etkisini göstermek için GridView'daki tüm ürünleri listeleyen ve tıklandığında ürün CategoryID
değerlerini yeniden atayabilen bir Button Web denetimi içeren bir kullanıcı arabirimi oluşturalım. Özellikle, kategori yeniden ataması ilerlerken, ilk birkaç ürüne geçerli CategoryID
bir değer atanırken diğer ürünlere bilerek var CategoryID
olmayan bir değer atanır. Veritabanını mevcut bir kategoriyle CategoryID
eşleşmeyen CategoryID
bir ürünle güncelleştirmeye çalışırsak yabancı anahtar kısıtlaması ihlali oluşur ve bir özel durum oluşur. Bu örnekte göreceğimiz şey, bir işlem kullanılırken yabancı anahtar kısıtlama ihlalinden kaynaklanan özel durumun önceki geçerli CategoryID
değişikliklerin geri alınmasına neden olacağıdır. Ancak, bir işlem kullanmadığınızda, ilk kategorilerde yapılan değişiklikler kalır.
İlk olarak klasördeki BatchData
sayfayı Transactions.aspx
açın ve Toolbox'tan bir GridView'ı Tasarım Aracı sürükleyin. ID
Products
akıllı etiketinden ve olarak ayarlayın, bunu adlı ProductsDataSource
yeni bir ObjectDataSource'a bağlayın. ObjectDataSource'u sınıfın ProductsBLL
GetProducts
yönteminden verilerini çekecek şekilde yapılandırın. Bu salt okunur bir GridView olacaktır, bu nedenle UPDATE, INSERT ve DELETE sekmelerindeki açılan listeleri (Yok) olarak ayarlayın ve Son'a tıklayın.
Şekil 5: ObjectDataSource'ı Sınıf GetProducts
Yöntemini Kullanacak ProductsBLL
Şekilde Yapılandırma (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Şekil 6: UPDATE, INSERT ve DELETE Sekmelerindeki Drop-Down Listeler (Yok) olarak ayarlayın (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Veri Kaynağını Yapılandırma sihirbazını tamamladıktan sonra Visual Studio, ürün veri alanları için BoundFields ve CheckBoxField oluşturur. , , CategoryID
ProductName
ve dışındaki ProductID
tüm bu alanları kaldırın ve CategoryName
ve CategoryName
BoundFields HeaderText
özelliklerini sırasıyla Product ve Category olarak yeniden adlandırınProductName
. Akıllı etiketten Disk Belleğini Etkinleştir seçeneğini işaretleyin. Bu değişiklikleri yaptıktan sonra GridView ve ObjectDataSource bildirim temelli işaretleme aşağıdaki gibi görünmelidir:
<asp:GridView ID="Products" runat="server" AllowPaging="True"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsDataSource">
<Columns>
<asp:BoundField DataField="ProductID" HeaderText="ProductID"
InsertVisible="False" ReadOnly="True"
SortExpression="ProductID" />
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="CategoryID" HeaderText="CategoryID"
SortExpression="CategoryID" />
<asp:BoundField DataField="CategoryName" HeaderText="Category"
SortExpression="CategoryName" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProducts" TypeName="ProductsBLL">
</asp:ObjectDataSource>
Ardından, GridView'un üzerine üç Düğme Web denetimi ekleyin. İlk Düğmenin Metin özelliğini Refresh Grid, ikincilerini Kategorileri Değiştir (İLE İŞLEM) ve üçüncüsü de Kategorileri Değiştir (İŞLEM OLMADAN) olarak ayarlayın.
<p>
<asp:Button ID="RefreshGrid" runat="server" Text="Refresh Grid" />
</p>
<p>
<asp:Button ID="ModifyCategoriesWithTransaction" runat="server"
Text="Modify Categories (WITH TRANSACTION)" />
</p>
<p>
<asp:Button ID="ModifyCategoriesWithoutTransaction" runat="server"
Text="Modify Categories (WITHOUT TRANSACTION)" />
</p>
Bu noktada Visual Studio'daki Tasarım görünümü, Şekil 7'de gösterilen ekran görüntüsüne benzer olmalıdır.
Şekil 7: Sayfa GridView ve Üç Düğmeli Web Denetimleri İçerir (Tam boyutlu resmi görüntülemek için tıklayın)
Üç Button Click
olayının her biri için olay işleyicileri oluşturun ve aşağıdaki kodu kullanın:
Protected Sub RefreshGrid_Click _
(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles RefreshGrid.Click
Products.DataBind()
End Sub
Protected Sub ModifyCategoriesWithTransaction_Click _
(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles ModifyCategoriesWithTransaction.Click
' Get the set of products
Dim productsAPI As New ProductsBLL()
Dim productsData As Northwind.ProductsDataTable = productsAPI.GetProducts()
' Update each product's CategoryID
For Each product As Northwind.ProductsRow In productsData
product.CategoryID = product.ProductID
Next
' Update the data using a transaction
productsAPI.UpdateWithTransaction(productsData)
' Refresh the Grid
Products.DataBind()
End Sub
Protected Sub ModifyCategoriesWithoutTransaction_Click _
(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles ModifyCategoriesWithoutTransaction.Click
' Get the set of products
Dim productsAPI As New ProductsBLL()
Dim productsData As Northwind.ProductsDataTable = productsAPI.GetProducts()
' Update each product's CategoryID
For Each product As Northwind.ProductsRow In productsData
product.CategoryID = product.ProductID
Next
' Update the data WITHOUT using a transaction
Dim productsAdapter As New NorthwindTableAdapters.ProductsTableAdapter()
productsAdapter.Update(productsData)
' Refresh the Grid
Products.DataBind()
End Sub
Refresh Button olay Click
işleyicisi, GridView s yöntemini çağırarak Products
verileri GridView'a DataBind
yeniden bağlamanız yeterlidir.
İkinci olay işleyicisi ürünleri CategoryID
yeniden atar ve veritabanı güncelleştirmelerini bir işlem şemsiyesi altında gerçekleştirmek için BLL'den yeni işlem yöntemini kullanır. Her ürünün CategoryID
rastgele olarak ile ProductID
aynı değere ayarlandığını unutmayın. Bu ürünler geçerli CategoryID
s değerleriyle eşlenecek değerlere sahip ProductID
olduğundan, bu ilk birkaç ürün için düzgün çalışır. Ancak s sayısı ProductID
fazla artmaya başladığında, s ve CategoryID
s'nin bu tesadüfi çakışması ProductID
artık geçerli olmaz.
Üçüncü Click
olay işleyicisi, ürünleri CategoryID
aynı şekilde güncelleştirir, ancak s varsayılan Update
yöntemini kullanarak ProductsTableAdapter
güncelleştirmeyi veritabanına gönderir. Bu Update
yöntem bir işlem içindeki komut serisini sarmalamaz, bu nedenle bu değişiklikler ilk karşılaşılan yabancı anahtar kısıtlama ihlali hatasından önce yapılır.
Bu davranışı göstermek için bu sayfayı bir tarayıcı üzerinden ziyaret edin. Başlangıçta Şekil 8'de gösterildiği gibi verilerin ilk sayfasını görmeniz gerekir. Ardından Kategorileri Değiştir (İle İşlem) düğmesine tıklayın. Bu bir geri göndermeye neden olur ve tüm ürün CategoryID
değerlerini güncelleştirmeye çalışır, ancak yabancı anahtar kısıtlama ihlaline neden olur (bkz. Şekil 9).
Şekil 8: Ürünler, Sayfalanabilir GridView'da Görüntülenir (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Şekil 9: Kategorileri Yeniden Atama Yabancı Anahtar Kısıtlama İhlaliyle Sonuçlanır (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Şimdi tarayıcınızın Geri düğmesine basın ve ardından Kılavuzu Yenile düğmesine tıklayın. Verileri yeniledikten sonra, Şekil 8'de gösterildiği gibi tam olarak aynı çıkışı görmeniz gerekir. Diğer bir ifadeyle, bazı ürünler CategoryID
yasal değerlere değiştirilip veritabanında güncelleştirilmiş olsa da, yabancı anahtar kısıtlaması ihlali oluştuğunda geri alınmıştır.
Şimdi Kategorileri Değiştir (İşlem OLMADAN) düğmesine tıklamayı deneyin. Bu, aynı yabancı anahtar kısıtlama ihlali hatasına neden olur (bkz. Şekil 9), ancak bu kez değerleri yasal bir değerle değiştirilen ürünler CategoryID
geri alınmaz. Tarayıcınızın Geri düğmesine ve ardından Kılavuzu Yenile düğmesine basın. Şekil 10'da gösterildiği gibi, CategoryID
ilk sekiz ürünün s'leri yeniden atanmıştır. Örneğin, Şekil 8'de Chang'in 1 sayısı vardı CategoryID
, ancak Şekil 10'da 2'ye yeniden atandı.
Şekil 10: Bazı Ürün CategoryID
Değerleri Güncelleştirilirken Diğerleri Güncelleştirildi (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Özet
Varsayılan olarak, TableAdapter yöntemleri yürütülen veritabanı deyimlerini bir işlem kapsamında sarmalamaz, ancak küçük bir çalışmayla bir işlem oluşturacak, işleyecek ve geri alacak yöntemler ekleyebiliriz. Bu öğreticide ProductsTableAdapter
, sınıfında bu tür üç yöntem oluşturduk: BeginTransaction
, CommitTransaction
ve RollbackTransaction
. Bir dizi veri değişikliği deyimini atomik yapmak için blokla Try...Catch
birlikte bu yöntemlerin nasıl kullanılacağını gördük. Özellikle, sağlanan ProductsDataTable
bir öğesinin UpdateWithTransaction
ProductsTableAdapter
satırlarında gerekli değişiklikleri gerçekleştirmek için Batch Update düzenini kullanan içinde yöntemini oluşturduk. Ayrıca BLL'de sınıfına ProductsBLL
yöntemini ekledikDeleteProductsWithTransaction
. Bu yöntem giriş olarak değerlerden ProductID
birini List
kabul eder ve her ProductID
için DB-Direct desen yöntemini Delete
çağırır. Her iki yöntem de bir işlem oluşturarak ve ardından blok Try...Catch
içinde veri değiştirme deyimlerini yürüterek başlar. Bir özel durum oluşursa işlem geri alınır, aksi takdirde işlenir.
5. adım, işlem toplu güncelleştirmelerinin ve bir işlemi kullanmayı ihmal eden toplu güncelleştirmelerin etkisini gösterir. Sonraki üç öğreticide bu öğreticide temeli oluşturacak ve toplu güncelleştirmeleri, silmeleri ve eklemeleri gerçekleştirmek için kullanıcı arabirimleri oluşturacağız.
Mutlu Programlama!
Daha Fazla Bilgi
Bu öğreticide ele alınan konular hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın:
- İşlemler Kolay Hale Getirildi:
System.Transactions
- TransactionScope ve DataAdapters
- .NET'te Oracle Veritabanı İşlemlerini Kullanma
Yazar hakkında
Yedi ASP/ASP.NET kitabının yazarı ve 4GuysFromRolla.com kurucusu Scott Mitchell, 1998'den beri Microsoft Web teknolojileriyle çalışmaktadır. Scott bağımsız bir danışman, eğitmen ve yazar olarak çalışmaktadır. Son kitabı Sams Teach Yourself ASP.NET 24 Saat içinde 2.0. Adresine adresinden veya adresinden ulaşabileceğiniz http://ScottOnWriting.NETblogu aracılığıyla ulaşabilirsinizmitchell@4GuysFromRolla.com.
Özel Teşekkürler
Bu öğretici serisi birçok yararlı gözden geçiren tarafından gözden geçirildi. Bu öğreticinin baş gözden geçirenleri Dave Gardner, Hilton Giesenow ve Teresa Murphy'ydi. Yaklaşan MSDN makalelerimi gözden geçirmek istiyor musunuz? Öyleyse, bana bir satır mitchell@4GuysFromRolla.combırakın.