Aracılığıyla paylaş


ASP.NET 4 Web Uygulamasında Entity Framework 4.0 ile Eşzamanlılığı İşleme

tarafından Tom Dykstra

Bu öğretici serisi , Entity Framework 4.0 ile Çalışmaya Başlama öğretici serisi tarafından oluşturulan Contoso Üniversitesi web uygulamasını oluşturur. Önceki öğreticileri tamamlamadıysanız, bu öğreticinin başlangıç noktası olarak oluşturduğunuz uygulamayı indirebilirsiniz . Öğretici serisinin tamamı tarafından oluşturulan uygulamayı da indirebilirsiniz. Öğreticiler hakkında sorularınız varsa bunları ASP.NET Entity Framework forumu'na gönderebilirsiniz.

Önceki öğreticide, denetimi ve Entity Framework'i kullanarak verileri sıralamayı ObjectDataSource ve filtrelemeyi öğrendinsiniz. Bu öğretici, Entity Framework kullanan bir ASP.NET web uygulamasında eşzamanlılığı işleme seçeneklerini gösterir. Eğitmen ofis ödevlerini güncelleştirmeye ayrılmış yeni bir web sayfası oluşturacaksınız. Bu sayfada ve daha önce oluşturduğunuz Departmanlar sayfasında eşzamanlılık sorunlarını ele alacağız.

Resim06

Resim01

Eşzamanlılık Çakışmaları

Bir kullanıcı kaydı düzenlediğinde ve başka bir kullanıcı ilk kullanıcının değişikliği veritabanına yazılmadan önce aynı kaydı düzenlediğinde eşzamanlılık çakışması oluşur. Bu tür çakışmaları algılamak için Entity Framework'u ayarlamazsanız, veritabanını son güncelleştiren kişi diğer kullanıcının değişikliklerinin üzerine yazar. Birçok uygulamada bu risk kabul edilebilir ve uygulamayı olası eşzamanlılık çakışmalarını işleyecek şekilde yapılandırmanız gerekmez. (Çok az kullanıcı veya birkaç güncelleştirme varsa ya da bazı değişikliklerin üzerine yazılırsa gerçekten kritik değilse eşzamanlılık programlama maliyeti avantajdan daha ağır basabilir.) Eşzamanlılık çakışmaları konusunda endişelenmeniz gerekmiyorsa bu öğreticiyi atlayabilirsiniz; serinin kalan iki öğreticisi, bu öğreticide oluşturduğunuz hiçbir şeye bağlı değildir.

Kötümser Eşzamanlılık (Kilitleme)

Uygulamanızın eşzamanlılık senaryolarında yanlışlıkla veri kaybını önlemesi gerekiyorsa, bunu gerçekleştirmenin bir yolu veritabanı kilitlerini kullanmaktır. Buna kötümser eşzamanlılık denir. Örneğin, veritabanından bir satırı okumadan önce salt okunur veya güncelleştirme erişimi için bir kilit isteyebilirsiniz. Bir satırı güncelleştirme erişimi için kilitlerseniz, başka hiçbir kullanıcının salt okunur veya güncelleştirme erişimi için satırı kilitlemesine izin verilmez, çünkü değiştirme sürecindeki verilerin bir kopyasını alabilirler. Bir satırı salt okunur erişim için kilitlerseniz, diğerleri de satırı salt okunur erişim için kilitleyebilir ancak güncelleştirme için kilitleyebilir.

Kilitleri yönetmenin bazı dezavantajları vardır. Programlamak karmaşık olabilir. Önemli veritabanı yönetim kaynakları gerektirir ve bir uygulamanın kullanıcı sayısı arttıkça performans sorunlarına neden olabilir (yani iyi ölçeklendirilemez). Bu nedenlerden dolayı, tüm veritabanı yönetim sistemleri kötümser eşzamanlılığı desteklemez. Entity Framework bunun için yerleşik destek sağlamaz ve bu öğreticide bunu nasıl uygulayabileceğiniz gösterilmez.

İyimser Eşzamanlılık

Kötümser eşzamanlılığın alternatifi iyimser eşzamanlılıktır. İyimser eşzamanlılık, eşzamanlılık çakışmalarının gerçekleşmesine izin vermek ve varsa uygun şekilde tepki vermek anlamına gelir. Örneğin, John Department.aspx sayfasını çalıştırır, Geçmiş bölümünün Düzenle bağlantısına tıklar ve Bütçe tutarını 1.000.000,00 TL'den 125.000,00 TL'ye düşürür. (John rakip bir departmanı yönetiyor ve kendi departmanı için para boşaltmak istiyor.)

Resim07

John Güncelleştir'e tıklamadan önce, Jane aynı sayfayı çalıştırır, Geçmiş bölümünün Düzenle bağlantısına tıklar ve başlangıç tarihi alanını 10.01.2011'den 1/1/1999'a değiştirir. (Jane, Geçmiş bölümünü yönetiyor ve daha fazla kıdem vermek istiyor.)

Resim08

John önce Güncelleştir'e tıklar, sonra Jane Güncelleştir'e tıklar. Jane'in tarayıcısı şimdi Bütçe tutarını 1.000.000.00 TL olarak listeler, ancak bu yanlıştır çünkü miktar John tarafından 125.000,00 TL olarak değiştirilmiştir.

Bu senaryoda gerçekleştirebileceğiniz eylemlerden bazıları şunlardır:

  • Kullanıcının hangi özelliği değiştirdiğini izleyebilir ve veritabanında yalnızca ilgili sütunları güncelleştirebilirsiniz. Örnek senaryoda, iki kullanıcı tarafından farklı özellikler güncelleştirildiğinden hiçbir veri kaybolmaz. Geçmiş bölümüne bir daha göz atarken 1/1/1999 ve 125.000,00 ABD doları görecektir.

    Bu, Entity Framework'teki varsayılan davranıştır ve veri kaybına neden olabilecek çakışma sayısını önemli ölçüde azaltabilir. Ancak, bir varlığın aynı özelliğinde rakip değişiklikler yapıldığında bu davranış veri kaybını önlemez. Buna ek olarak, bu davranış her zaman mümkün değildir; saklı yordamları bir varlık türüyle eşlediğinizde, veritabanında varlıkta herhangi bir değişiklik yapıldığında varlığın tüm özellikleri güncelleştirilir.

  • Jane'in değişikliğinin John'un değişikliğinin üzerine yazmasına izin vekleyebilirsiniz. Jane Güncelleştir'e tıkladıktan sonra Bütçe tutarı 1.000.000,00 TL'ye geri döner. Bu, İstemci Kazanır veya Wins senaryosunda Son olarak adlandırılır. (İstemcinin değerleri, veri deposundakilerden önceliklidir.)

  • Jane'in değişikliğinin veritabanında güncelleştirilmesini engelleyebilirsiniz. Genellikle bir hata iletisi görüntüler, verilerin geçerli durumunu gösterir ve yine de yapmak isterse değişikliklerini yeniden girmesine izin verirsiniz. Girdisini kaydederek ve yeniden girmenize gerek kalmadan yeniden uygulama fırsatı vererek süreci daha da otomatikleştirebilirsiniz. Buna Store Wins senaryosu adı verilir. (Veri deposu değerleri, istemci tarafından gönderilen değerlerden önceliklidir.)

Eşzamanlılık Çakışmalarını Algılama

Entity Framework'te, Entity Framework'ün oluşturduğu özel durumları işleyerek OptimisticConcurrencyException çakışmaları çözebilirsiniz. Bu özel durumların ne zaman oluşturulacağı hakkında bilgi edinmek için Entity Framework'ün çakışmaları algılayabilmesi gerekir. Bu nedenle, veritabanını ve veri modelini uygun şekilde yapılandırmanız gerekir. Çakışma algılamayı etkinleştirmeye yönelik bazı seçenekler şunlardır:

  • Veritabanına, bir satırın ne zaman değiştirildiğini belirlemek için kullanılabilecek bir tablo sütunu ekleyin. Daha sonra Entity Framework'i bu sütunu SQL Update veya Delete komutların yan tümcesine Where dahil etmek üzere yapılandırabilirsiniz.

    Bu, tablodaki sütunun Timestamp amacıdır OfficeAssignment .

    Resim09

    Sütunun Timestamp veri türü olarak da adlandırılır Timestamp. Ancak sütun aslında bir tarih veya saat değeri içermez. Bunun yerine değer, satır her güncelleştirildiğinde artırılan sıralı bir sayıdır. Bir Update veya komutunda Where yan tümcesi özgün Timestamp değeri Delete içerir. Güncelleştirilmekte olan satır başka bir kullanıcı tarafından değiştirildiyse içindeki değer özgün değerden Timestamp farklıdır, bu nedenle Where yan tümcesi güncelleştirilecek satır döndürmez. Entity Framework, geçerli Update veya Delete komut tarafından güncelleştirilmiş satır olmadığını bulduğunda (yani, etkilenen satırların sayısı sıfır olduğunda), bunu eşzamanlılık çakışması olarak yorumlar.

  • Entity Framework'leri tablodaki Where her sütunun özgün değerlerini ve Delete komutlarının yan tümcesine Update dahil etmek için yapılandırın.

    İlk seçenekte olduğu gibi, satırdaki herhangi bir şey satır ilk okunduktan sonra değiştiyse, Where yan tümcesi güncelleştirilecek bir satır döndürmez ve Entity Framework bu satırı eşzamanlılık çakışması olarak yorumlar. Bu yöntem bir Timestamp alan kullanmak kadar etkilidir, ancak verimli olmayabilir. Çok sayıda sütunu olan veritabanı tablolarında çok büyük Where yan tümcelere neden olabilir ve bir web uygulamasında büyük miktarlarda durum korumanız gerekebilir. Sunucu kaynakları (örneğin, oturum durumu) gerektirdiğinden veya web sayfasının kendisine (örneğin, görüntüleme durumu) dahil edilmesi gerektiğinden, büyük miktarlarda durumun korunması uygulama performansını etkileyebilir.

Bu öğreticide, izleme özelliği olmayan bir varlık (varlık) ve izleme özelliğine ( Department varlık) sahip OfficeAssignment bir varlık için iyimser eşzamanlılık çakışmaları için hata işleme ekleyebilirsiniz.

İzleme Özelliği Olmadan İyimser Eşzamanlılığı İşleme

Varlığın Department izleme (Timestamp) özelliği olmayan iyimser eşzamanlılığını uygulamak için aşağıdaki görevleri tamamlayacaksınız:

  • Varlıklar için eşzamanlılık izlemeyi etkinleştirmek için Department veri modelini değiştirin.
  • SchoolRepository sınıfında, yöntemindeki eşzamanlılık özel durumlarını işleyebilirSaveChanges.
  • Departments.aspx sayfasında, kullanıcıya yapılan değişikliklerin başarısız olduğuna ilişkin bir ileti görüntüleyerek eşzamanlılık özel durumlarını işleyebilirsiniz. Kullanıcı daha sonra geçerli değerleri görebilir ve hala gerekliyse değişiklikleri yeniden deneyebilir.

Veri Modelinde Eşzamanlılık İzlemeyi Etkinleştirme

Visual Studio'da, bu serinin önceki öğreticisinde üzerinde çalıştığınız Contoso University web uygulamasını açın.

SchoolModel.edmx dosyasını açın ve veri modeli tasarımcısında varlıktaki özelliğe sağ tıklayın Name ve özellikler'e Departmenttıklayın. Özellikler penceresinde özelliğini olarak FixeddeğiştirinConcurrencyMode.

Resim16

Aynı işlemi diğer birincil anahtar olmayan skaler özellikler (Budget, StartDateve Administrator.) için de yapın. (Gezinti özellikleri için bunu yapamazsınız.) Bu, Entity Framework veritabanındaki varlığı güncelleştirmek Department için bir Update veya Delete SQL komutu oluşturduğunda, bu sütunların (özgün değerlerle) yan tümcesine Where eklenmesi gerektiğini belirtir. veya Delete komutu yürütürken Update satır bulunamazsa, Entity Framework iyimser-eşzamanlılık özel durumu oluşturur.

Veri modelini kaydedin ve kapatın.

DAL'de Eşzamanlılık Özel Durumlarını İşleme

SchoolRepository.cs dosyasını açın ve ad alanı için System.Data aşağıdaki using deyimi ekleyin:

using System.Data;

İyimser eşzamanlılık özel durumlarını işleyen aşağıdaki yeni SaveChanges yöntemi ekleyin:

public void SaveChanges()
{
    try
    {
        context.SaveChanges();
    }
    catch (OptimisticConcurrencyException ocex)
    {
        context.Refresh(RefreshMode.StoreWins, ocex.StateEntries[0].Entity);
        throw ocex;
    }
}

Bu yöntem çağrıldığında eşzamanlılık hatası oluşursa, bellekteki varlığın özellik değerleri veritabanındaki değerlerle değiştirilir. Web sayfasının işleyebilmesi için eşzamanlılık özel durumu yeniden oluşturulur.

ve yöntemlerindeDeleteDepartment, yeni yöntemi çağırmak için context.SaveChanges() var olan çağrısı yerine bir çağrısı SaveChanges()UpdateDepartment ekleyin.

Sunu Katmanında Eşzamanlılık Özel Durumlarını İşleme

Departments.aspx dosyasını açın ve denetime DepartmentsObjectDataSource bir OnDeleted="DepartmentsObjectDataSource_Deleted" öznitelik ekleyin. Denetimin açma etiketi artık aşağıdaki örneğe benzeyecektir.

<asp:ObjectDataSource ID="DepartmentsObjectDataSource" runat="server" 
        TypeName="ContosoUniversity.BLL.SchoolBL" DataObjectTypeName="ContosoUniversity.DAL.Department" 
        SelectMethod="GetDepartmentsByName" DeleteMethod="DeleteDepartment" UpdateMethod="UpdateDepartment"
        ConflictDetection="CompareAllValues" OldValuesParameterFormatString="orig{0}" 
        OnUpdated="DepartmentsObjectDataSource_Updated" SortParameterName="sortExpression" 
        OnDeleted="DepartmentsObjectDataSource_Deleted" >

Denetimde DepartmentsGridView , aşağıdaki örnekte gösterildiği gibi özniteliğindeki DataKeyNames tüm tablo sütunlarını belirtin. Bunun çok büyük görünüm durumu alanları oluşturacağını unutmayın. Bu, izleme alanı kullanmanın genellikle eşzamanlılık çakışmalarını izlemenin tercih edilen yolu olmasının bir nedenidir.

<asp:GridView ID="DepartmentsGridView" runat="server" AutoGenerateColumns="False"
        DataSourceID="DepartmentsObjectDataSource" 
        DataKeyNames="DepartmentID,Name,Budget,StartDate,Administrator" 
        OnRowUpdating="DepartmentsGridView_RowUpdating"
        OnRowDataBound="DepartmentsGridView_RowDataBound"
        AllowSorting="True" >

Departments.aspx.cs dosyasını açın ve ad alanı için System.Data aşağıdaki using deyimi ekleyin:

using System.Data;

Eşzamanlılık özel durumlarını işlemek için veri kaynağı denetiminin Updated ve Deleted olay işleyicilerinden çağıracağınız aşağıdaki yeni yöntemi ekleyin:

private void CheckForOptimisticConcurrencyException(ObjectDataSourceStatusEventArgs e, string function)
{
    if (e.Exception.InnerException is OptimisticConcurrencyException)
    {
        var concurrencyExceptionValidator = new CustomValidator();
        concurrencyExceptionValidator.IsValid = false;
        concurrencyExceptionValidator.ErrorMessage = 
            "The record you attempted to edit or delete was modified by another " +
            "user after you got the original value. The edit or delete operation was canceled " +
            "and the other user's values have been displayed so you can " +
            "determine whether you still want to edit or delete this record.";
        Page.Validators.Add(concurrencyExceptionValidator);
        e.ExceptionHandled = true;
    }
}

Bu kod özel durum türünü denetler ve eşzamanlılık özel durumuysa kod dinamik olarak denetimde ValidationSummary bir CustomValidator ileti görüntüleyen bir denetim oluşturur.

Daha önce eklediğiniz olay işleyicisinden Updated yeni yöntemi çağırın. Ayrıca, aynı yöntemi çağıran (ancak başka bir şey yapmayan) yeni Deleted bir olay işleyicisi oluşturun:

protected void DepartmentsObjectDataSource_Updated(object sender, ObjectDataSourceStatusEventArgs e)
{
    if (e.Exception != null)
    {
        CheckForOptimisticConcurrencyException(e, "update");
        // ...
    }
}

protected void DepartmentsObjectDataSource_Deleted(object sender, ObjectDataSourceStatusEventArgs e)
{
    if (e.Exception != null)
    {
        CheckForOptimisticConcurrencyException(e, "delete");
    }
}

Departmanlar Sayfasında İyimser Eşzamanlılığı Test Etme

Departments.aspx sayfasını çalıştırın.

Departmanlar sayfasını gösteren ekran görüntüsü.

Satırda Düzenle'ye tıklayın ve Bütçe sütunundaki değeri değiştirin. (Mevcut School veritabanı kayıtları bazı geçersiz veriler içerdiğinden, yalnızca bu öğretici için oluşturduğunuz kayıtları düzenleyebildiğinizi unutmayın. İktisat departmanının kaydı, deney yapmak için güvenli bir kayıttır.)

Resim18

Yeni bir tarayıcı penceresi açın ve sayfayı yeniden çalıştırın (url'yi ilk tarayıcı penceresinin adres kutusundan ikinci tarayıcı penceresine kopyalayın).

Giriş için hazır yeni bir tarayıcı penceresi gösteren ekran görüntüsü.

Daha önce düzenlediğiniz satırda Düzenle'ye tıklayın ve Bütçe değerini farklı bir değerle değiştirin.

Resim19

İkinci tarayıcı penceresinde Güncelleştir'e tıklayın. Bütçe tutarı başarıyla bu yeni değere değiştirildi.

Resim20

İlk tarayıcı penceresinde Güncelleştir'e tıklayın. Güncelleştirme başarısız oluyor. Bütçe tutarı, ikinci tarayıcı penceresinde ayarladığınız değer kullanılarak yeniden görüntülenir ve bir hata iletisi görürsünüz.

Resim21

İzleme Özelliği Kullanarak İyimser Eşzamanlılığı İşleme

İzleme özelliğine sahip bir varlığın iyimser eşzamanlılığını işlemek için aşağıdaki görevleri tamamlayacağız:

  • Varlıkları yönetmek OfficeAssignment için veri modeline saklı yordamlar ekleyin. (İzleme özelliklerinin ve saklı yordamların birlikte kullanılması gerekmez; bunlar çizim için burada birlikte gruplandırılır.)
  • DAL'de iyimser eşzamanlılık özel durumlarını işlemek için kod da dahil olmak üzere DAL ve varlıklar için OfficeAssignment BLL'ye CRUD yöntemleri ekleyin.
  • Office atamaları web sayfası oluşturun.
  • Yeni web sayfasında iyimser eşzamanlılığı test edin.

Veri Modeline OfficeAssignment Saklı Yordamları Ekleme

Model tasarımcısında SchoolModel.edmx dosyasını açın, tasarım yüzeyine sağ tıklayın ve Veritabanından Modeli Güncelleştir'e tıklayın. Veritabanı Nesnelerinizi Seçin iletişim kutusunun Ekle sekmesinde Saklı Yordamlar'ı genişletin ve üç OfficeAssignment saklı yordamı seçin (aşağıdaki ekran görüntüsüne bakın) ve ardından Son'a tıklayın. (Bu saklı yordamlar, bir betik kullanarak indirdiğinizde veya oluşturduğunuzda veritabanında zaten vardı.)

Görüntü02

Varlığa OfficeAssignment sağ tıklayın ve Saklı Yordam Eşlemesi'ni seçin.

Görüntü03

Ekle, Güncelleştir ve Sil işlevlerini ilgili saklı yordamlarını kullanacak şekilde ayarlayın. İşlevin OrigTimestamp parametresi Update için Özelliği olarak Timestamp ayarlayın ve Özgün Değer Kullan seçeneğini belirleyin.

Görüntü04

Entity Framework saklı yordamı çağırdığında UpdateOfficeAssignment parametresindeki OrigTimestamp sütunun Timestamp özgün değerini geçirir. Saklı yordam bu parametreyi yan tümcesinde Where kullanır:

ALTER PROCEDURE [dbo].[UpdateOfficeAssignment]
    @InstructorID int,
    @Location nvarchar(50),
    @OrigTimestamp timestamp
    AS
    UPDATE OfficeAssignment SET Location=@Location 
    WHERE InstructorID=@InstructorID AND [Timestamp]=@OrigTimestamp;
    IF @@ROWCOUNT > 0
    BEGIN
        SELECT [Timestamp] FROM OfficeAssignment 
            WHERE InstructorID=@InstructorID;
    END

Saklı yordam ayrıca güncelleştirmeden sonra sütunun Timestamp yeni değerini seçerek Entity Framework'ün bellekteki varlığı ilgili veritabanı satırıyla eşitlenmiş durumda tutabilmesini OfficeAssignment sağlar.

(Office atamasını silmeye yönelik saklı yordamın parametresi OrigTimestamp olmadığını unutmayın. Bu nedenle, Entity Framework bir varlığı silmeden önce değişmediğini doğrulayamaz.)

Veri modelini kaydedin ve kapatın.

DAL'ye OfficeAssignment Yöntemleri Ekleme

ISchoolRepository.cs dosyasını açın ve varlık kümesi için OfficeAssignment aşağıdaki CRUD yöntemlerini ekleyin:

IEnumerable<OfficeAssignment> GetOfficeAssignments(string sortExpression);
void InsertOfficeAssignment(OfficeAssignment OfficeAssignment);
void DeleteOfficeAssignment(OfficeAssignment OfficeAssignment);
void UpdateOfficeAssignment(OfficeAssignment OfficeAssignment, OfficeAssignment origOfficeAssignment);

SchoolRepository.cs dosyasına aşağıdaki yeni yöntemleri ekleyin. yönteminde UpdateOfficeAssignment yerine yerel SaveChanges yöntemini context.SaveChangesçağırırsınız.

public IEnumerable<OfficeAssignment> GetOfficeAssignments(string sortExpression)
{
    return new ObjectQuery<OfficeAssignment>("SELECT VALUE o FROM OfficeAssignments AS o", context).Include("Person").OrderBy("it." + sortExpression).ToList();
}

public void InsertOfficeAssignment(OfficeAssignment officeAssignment)
{
    context.OfficeAssignments.AddObject(officeAssignment);
    context.SaveChanges();
}

public void DeleteOfficeAssignment(OfficeAssignment officeAssignment)
{
    context.OfficeAssignments.Attach(officeAssignment);
    context.OfficeAssignments.DeleteObject(officeAssignment);
    context.SaveChanges();
}

public void UpdateOfficeAssignment(OfficeAssignment officeAssignment, OfficeAssignment origOfficeAssignment)
{
    context.OfficeAssignments.Attach(origOfficeAssignment);
    context.ApplyCurrentValues("OfficeAssignments", officeAssignment);
    SaveChanges();
}

Test projesinde MockSchoolRepository.cs dosyasını açın ve aşağıdaki OfficeAssignment koleksiyonu ve CRUD yöntemlerini ekleyin. (Sahte depo, depo arabirimini uygulamalıdır, aksi zaman çözüm derlenmez.)

List<OfficeAssignment> officeAssignments = new List<OfficeAssignment>();
        
public IEnumerable<OfficeAssignment> GetOfficeAssignments(string sortExpression)
{
    return officeAssignments;
}

public void InsertOfficeAssignment(OfficeAssignment officeAssignment)
{
    officeAssignments.Add(officeAssignment);
}

public void DeleteOfficeAssignment(OfficeAssignment officeAssignment)
{
    officeAssignments.Remove(officeAssignment);
}

public void UpdateOfficeAssignment(OfficeAssignment officeAssignment, OfficeAssignment origOfficeAssignment)
{
    officeAssignments.Remove(origOfficeAssignment);
    officeAssignments.Add(officeAssignment);
}

BLL'ye OfficeAssignment Yöntemleri Ekleme

Ana projede SchoolBL.cs dosyasını açın ve buna ayarlanan varlık için OfficeAssignment aşağıdaki CRUD yöntemlerini ekleyin:

public IEnumerable<OfficeAssignment> GetOfficeAssignments(string sortExpression)
{
    if (string.IsNullOrEmpty(sortExpression)) sortExpression = "Person.LastName";
    return schoolRepository.GetOfficeAssignments(sortExpression);
}

public void InsertOfficeAssignment(OfficeAssignment officeAssignment)
{
    try
    {
        schoolRepository.InsertOfficeAssignment(officeAssignment);
    }
    catch (Exception ex)
    {
        //Include catch blocks for specific exceptions first,
        //and handle or log the error as appropriate in each.
        //Include a generic catch block like this one last.
        throw ex;
    }
}

public void DeleteOfficeAssignment(OfficeAssignment officeAssignment)
{
    try
    {
        schoolRepository.DeleteOfficeAssignment(officeAssignment);
    }
    catch (Exception ex)
    {
        //Include catch blocks for specific exceptions first,
        //and handle or log the error as appropriate in each.
        //Include a generic catch block like this one last.
        throw ex;
    }
}

public void UpdateOfficeAssignment(OfficeAssignment officeAssignment, OfficeAssignment origOfficeAssignment)
{
    try
    {
        schoolRepository.UpdateOfficeAssignment(officeAssignment, origOfficeAssignment);
    }
    catch (Exception ex)
    {
        //Include catch blocks for specific exceptions first,
        //and handle or log the error as appropriate in each.
        //Include a generic catch block like this one last.
        throw ex;
    }
}

OfficeAssignments Web Sayfası Oluşturma

Site.Master ana sayfasını kullanan yeni bir web sayfası oluşturun ve bunu OfficeAssignments.aspx olarak adlandırın. adlı Content2denetime aşağıdaki işaretlemeyi Content ekleyin:

<h2>Office Assignments</h2>
    <asp:ObjectDataSource ID="OfficeAssignmentsObjectDataSource" runat="server" TypeName="ContosoUniversity.BLL.SchoolBL"
        DataObjectTypeName="ContosoUniversity.DAL.OfficeAssignment" SelectMethod="GetOfficeAssignments"
        DeleteMethod="DeleteOfficeAssignment" UpdateMethod="UpdateOfficeAssignment" ConflictDetection="CompareAllValues"
        OldValuesParameterFormatString="orig{0}"
        SortParameterName="sortExpression"  OnUpdated="OfficeAssignmentsObjectDataSource_Updated">
    </asp:ObjectDataSource>
    <asp:ValidationSummary ID="OfficeAssignmentsValidationSummary" runat="server" ShowSummary="true"
        DisplayMode="BulletList" Style="color: Red; width: 40em;" />
    <asp:GridView ID="OfficeAssignmentsGridView" runat="server" AutoGenerateColumns="False"
        DataSourceID="OfficeAssignmentsObjectDataSource" DataKeyNames="InstructorID,Timestamp"
        AllowSorting="True">
        <Columns>
            <asp:CommandField ShowEditButton="True" ShowDeleteButton="True" ItemStyle-VerticalAlign="Top">
                <ItemStyle VerticalAlign="Top"></ItemStyle>
            </asp:CommandField>
            <asp:TemplateField HeaderText="Instructor" SortExpression="Person.LastName">
                <ItemTemplate>
                    <asp:Label ID="InstructorLastNameLabel" runat="server" Text='<%# Eval("Person.LastName") %>'></asp:Label>,
                    <asp:Label ID="InstructorFirstNameLabel" runat="server" Text='<%# Eval("Person.FirstMidName") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:DynamicField DataField="Location" HeaderText="Location" SortExpression="Location"/>
        </Columns>
        <SelectedRowStyle BackColor="LightGray"></SelectedRowStyle>
    </asp:GridView>

özniteliğinde DataKeyNames işaretleme özelliğinin yanı sıra kayıt anahtarını (InstructorID ) da belirttiğine Timestamp dikkat edin. Öznitelikte özelliklerin DataKeyNames belirtilmesi, özgün değerlerin geri gönderme işlemi sırasında kullanılabilir olması için denetimin bunları denetim durumuna (görüntüleme durumuna benzer) kaydetmesine neden olur.

Değeri kaydetmediysenizTimestamp, Entity Framework'ün SQL Update komutunun Where yan tümcesi için bu değere sahip olmaması gerekir. Sonuç olarak, güncelleştirilecek hiçbir şey bulunamadı. Sonuç olarak Entity Framework, bir varlık her güncelleştirildiğinde iyimser bir OfficeAssignment eşzamanlılık özel durumu oluşturur.

OfficeAssignments.aspx.cs dosyasını açın ve veri erişim katmanı için aşağıdaki using deyimi ekleyin:

using ContosoUniversity.DAL;

Dinamik Veri işlevselliğini etkinleştiren aşağıdaki Page_Init yöntemi ekleyin. Eşzamanlılık hatalarını denetlemek için denetimin ObjectDataSourceUpdated olayı için aşağıdaki işleyiciyi de ekleyin:

protected void Page_Init(object sender, EventArgs e)
{
    OfficeAssignmentsGridView.EnableDynamicData(typeof(OfficeAssignment));
}

protected void OfficeAssignmentsObjectDataSource_Updated(object sender, ObjectDataSourceStatusEventArgs e)
{
    if (e.Exception != null)
    {
        var concurrencyExceptionValidator = new CustomValidator();
        concurrencyExceptionValidator.IsValid = false;
        concurrencyExceptionValidator.ErrorMessage = "The record you attempted to " +
            "update has been modified by another user since you last visited this page. " +
            "Your update was canceled to allow you to review the other user's " +
            "changes and determine if you still want to update this record.";
        Page.Validators.Add(concurrencyExceptionValidator);
        e.ExceptionHandled = true;
    }
}

OfficeAssignments Sayfasında İyimser Eşzamanlılığı Test Etme

OfficeAssignments.aspx sayfasını çalıştırın.

Office Atamaları sayfasını gösteren ekran görüntüsü.

Satırda Düzenle'ye tıklayın ve Konum sütunundaki değeri değiştirin.

Resim11

Yeni bir tarayıcı penceresi açın ve sayfayı yeniden çalıştırın (url'yi ilk tarayıcı penceresinden ikinci tarayıcı penceresine kopyalayın).

Yeni bir tarayıcı penceresi gösteren ekran görüntüsü.

Daha önce düzenlediğiniz satırda Düzenle'ye tıklayın ve Konum değerini farklı bir değerle değiştirin.

Resim12

İkinci tarayıcı penceresinde Güncelleştir'e tıklayın.

Resim13

İlk tarayıcı penceresine geçin ve Güncelleştir'e tıklayın.

Resim15

Bir hata iletisi görürsünüz ve Konum değeri, ikinci tarayıcı penceresinde değiştirdiğiniz değeri gösterecek şekilde güncelleştirildi.

EntityDataSource Denetimi ile Eşzamanlılığı İşleme

Denetim, EntityDataSource veri modelindeki eşzamanlılık ayarlarını tanıyan ve güncelleştirme ve silme işlemlerini uygun şekilde işleyen yerleşik mantık içerir. Ancak, tüm özel durumlarda olduğu gibi, kullanıcı dostu bir hata iletisi sağlamak için özel durumları kendiniz işlemeniz OptimisticConcurrencyException gerekir.

Ardından, güncelleştirme ve silme işlemlerine izin vermek ve eşzamanlılık çakışması oluşursa hata iletisi görüntülemek için Courses.aspx sayfasını (denetim kullanan EntityDataSource ) yapılandıracaksınız. Varlığın Course eşzamanlılık izleme sütunu yoktur, bu nedenle varlıkla Department yaptığınız yöntemi kullanırsınız: anahtar olmayan tüm özelliklerin değerlerini izleme.

SchoolModel.edmx dosyasını açın. Varlığın (Title, Creditsve DepartmentID) anahtar olmayan özellikleri Course için Eşzamanlılık Modu özelliğini olarak Fixedayarlayın. Ardından veri modelini kaydedip kapatın.

Courses.aspx sayfasını açın ve aşağıdaki değişiklikleri yapın:

  • Denetimde CoursesEntityDataSource ve EnableDelete="true" öznitelikleri ekleyinEnableUpdate="true". Bu denetimin açma etiketi artık aşağıdaki örneğe benzer:

    <asp:EntityDataSource ID="CoursesEntityDataSource" runat="server" 
            ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="false" 
            AutoGenerateWhereClause="True" EntitySetName="Courses"
            EnableUpdate="true" EnableDelete="true">
    
  • Denetimde CoursesGridView öznitelik değerini olarak "CourseID,Title,Credits,DepartmentID"değiştirinDataKeyNames. Ardından öğeye ColumnsDüzenle ve Sil düğmelerini ()<asp:CommandField ShowEditButton="True" ShowDeleteButton="True" /> gösteren bir CommandField öğe ekleyin. Denetim GridView artık aşağıdaki örneğe benzer:

    <asp:GridView ID="CoursesGridView" runat="server" AutoGenerateColumns="False" 
            DataKeyNames="CourseID,Title,Credits,DepartmentID"
            DataSourceID="CoursesEntityDataSource" >
            <Columns>
                <asp:CommandField ShowEditButton="True" ShowDeleteButton="True" />
                <asp:BoundField DataField="CourseID" HeaderText="CourseID" ReadOnly="True" SortExpression="CourseID" />
                <asp:BoundField DataField="Title" HeaderText="Title" SortExpression="Title" />
                <asp:BoundField DataField="Credits" HeaderText="Credits" SortExpression="Credits" />
            </Columns>
        </asp:GridView>
    

Sayfayı çalıştırın ve Departmanlar sayfasında daha önce yaptığınız gibi bir çakışma durumu oluşturun. Sayfayı iki tarayıcı penceresinde çalıştırın, her pencerede aynı satırda Düzenle'ye tıklayın ve her birinde farklı bir değişiklik yapın. Bir pencerede Güncelleştir'e tıklayın ve ardından diğer pencerede Güncelleştir'e tıklayın. İkinci kez Güncelleştir'e tıkladığınızda, işlenmeyen bir eşzamanlılık özel durumunun neden olduğu hata sayfasını görürsünüz.

Resim22

Bu hatayı, denetim için ObjectDataSource nasıl işlediğinize çok benzer bir şekilde işlersiniz. Courses.aspx sayfasını açın ve denetimde CoursesEntityDataSource ve Updated olayları için Deleted işleyicileri belirtin. Denetimin açma etiketi artık aşağıdaki örneğe benzer:

<asp:EntityDataSource ID="CoursesEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="false"
        AutoGenerateWhereClause="true" EntitySetName="Courses" 
        EnableUpdate="true" EnableDelete="true" 
        OnDeleted="CoursesEntityDataSource_Deleted" 
        OnUpdated="CoursesEntityDataSource_Updated">

Denetimden CoursesGridView önce aşağıdaki ValidationSummary denetimi ekleyin:

<asp:ValidationSummary ID="CoursesValidationSummary" runat="server" 
        ShowSummary="true" DisplayMode="BulletList"  />

Courses.aspx.cs dosyasında ad alanı için System.Data bir using deyim ekleyin, eşzamanlılık özel durumlarını denetleyan bir yöntem ekleyin ve denetimin EntityDataSourceUpdated ve Deleted işleyicilerinin işleyicilerini ekleyin. Kod aşağıdaki gibi görünür:

using System.Data;
protected void CoursesEntityDataSource_Updated(object sender, EntityDataSourceChangedEventArgs e)
{
    CheckForOptimisticConcurrencyException(e, "update");
}

protected void CoursesEntityDataSource_Deleted(object sender, EntityDataSourceChangedEventArgs e)
{
    CheckForOptimisticConcurrencyException(e, "delete");
}

private void CheckForOptimisticConcurrencyException(EntityDataSourceChangedEventArgs e, string function)
{
    if (e.Exception != null && e.Exception is OptimisticConcurrencyException)
    {
        var concurrencyExceptionValidator = new CustomValidator();
        concurrencyExceptionValidator.IsValid = false;
        concurrencyExceptionValidator.ErrorMessage = 
            "The record you attempted to edit or delete was modified by another " +
            "user after you got the original value. The edit or delete operation was canceled " +
            "and the other user's values have been displayed so you can " +
            "determine whether you still want to edit or delete this record.";
        Page.Validators.Add(concurrencyExceptionValidator);
        e.ExceptionHandled = true;
    }
}

Bu kodla denetim için ObjectDataSource yaptıklarınız arasındaki tek fark, bu durumda eşzamanlılık özel durumunun bu özel InnerException durumun özelliği yerine olay bağımsız değişkenleri nesnesinin özelliğinde olmasıdırException.

Sayfayı çalıştırın ve yeniden eşzamanlılık çakışması oluşturun. Bu kez bir hata iletisi görürsünüz:

Resim23

Bu, eşzamanlılık çakışmalarını işlemeye giriş işlemini tamamlar. Sonraki öğretici, Entity Framework kullanan bir web uygulamasında performansın nasıl geliştirileceğine ilişkin rehberlik sağlayacaktır.