Veritabanı Değişikliklerini Bir İşlemin İçinde Sarmalama (VB)

tarafından Scott Mitchell

PDF’yi İndir

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 , UPDATEve DELETE deyimleri kümesi INSERTiç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:

  1. İşlemin başlangıcını belirtin.
  2. İşlemi oluşturan SQL deyimlerini yürütür.
  3. 2. Adımdaki deyimlerden birinde hata varsa işlemi geri alın.
  4. 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.Transactionskullanarak 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 SqlTransactionsı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 catchRollback 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

SqlDataSource-Related Öğreticileri için ASP.NET Sayfaları Ekleme

Ş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.

SectionLevelTutorialListing.ascx Kullanıcı Denetimini Default.aspx ekleme

Şekil 2: Kullanıcı Denetimini ekleme SectionLevelTutorialListing.ascxDefault.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.sitemapsonra, öğ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.

Site Haritası Artık Toplu Verilerle Çalışma Öğreticileri için Girdiler Içeriyor

Ş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 InsertCommandiçin , UpdateCommandveya 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, UpdateCommandveya 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 InsertCommandyeni 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ı TransactionSupportProductsTableAdapter.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.

TransactionSupport Adlı Bir Klasör ve ProductsTableAdapter.TransactionSupport.vb Adlı Bir Sınıf Dosyası Ekleme

Ş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 ProductsTableAdapterNorthwindTableAdapters 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, Publicdal içindeki başka bir sınıftan ProductsTableAdapterveya 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. CommitTransactionve RollbackTransactionConnection 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 AdapterUpdate 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, UpdateCommandve 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.vbekleyin. 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 ProductsTableAdapterProductsBLL 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)Integergiriş 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 BeginTransactioniş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 ProductsBLLolmalıdır: UpdateWithTransactionyeni eklediğiniz ve DeleteProductsWithTransaction3. 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 CategoryIDeş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. IDProducts akıllı etiketinden ve olarak ayarlayın, bunu adlı ProductsDataSourceyeni bir ObjectDataSource'a bağlayın. ObjectDataSource'u sınıfın ProductsBLLGetProducts 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.

ObjectDataSource'ı ProductsBLL Sınıfının GetProducts Yöntemini Kullanacak Şekilde Yapılandırma

Ş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)

UPDATE, INSERT ve DELETE Sekmelerindeki Drop-Down Listeler (Yok) olarak ayarlayı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. , , CategoryIDProductNameve dışındaki ProductIDtü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.

Sayfada GridView ve Üç Düğmeli Web Denetimleri Var

Ş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 ProductIDaynı 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).

Ürünler Sayfalanabilir GridView'da Görüntülenir

Ş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)

Kategorilerin Yeniden Atanarak Yabancı Anahtar Kısıtlama İhlaliNe Neden Olur

Ş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ı.

Bazı Ürünler CategoryID Değerleri Güncelleştirilirken Diğerleri Güncelleştirilmedi

Ş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, CommitTransactionve 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 ProductsDataTablebir öğesinin UpdateWithTransactionProductsTableAdaptersatı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 ProductIDiç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:

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.