Aracılığıyla paylaş


Entity Framework 4.0 ve ObjectDataSource Denetimini Kullanma, Bölüm 1: Başlarken

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.

Contoso University örnek web uygulaması, Entity Framework 4.0 ve Visual Studio 2010 kullanarak ASP.NET Web Forms uygulamaları oluşturmayı gösterir. Örnek uygulama, kurgusal bir Contoso Üniversitesi'nin web sitesidir. Öğrenci kabulü, kurs oluşturma ve eğitmen ödevleri gibi işlevleri içerir.

Öğreticide C# dilinde örnekler gösterilir. İndirilebilir örnek hem C# hem de Visual Basic'te kod içerir.

Önce Veritabanı

Entity Framework'teki verilerle çalışmanın üç yolu vardır: Önce Veritabanı, Önce Model ve Kod önce. Bu öğretici, Önce Veritabanı'nın öğreticisi içindir. Bu iş akışları arasındaki farklar hakkında bilgi edinmek ve senaryonuz için en iyi iş akışını seçme yönergeleri için bkz . Entity Framework Geliştirme İş Akışları.

Web Forms

Başlarken serisinde olduğu gibi bu öğretici serisi de ASP.NET Web Forms modelini kullanır ve Visual Studio'da ASP.NET Web Forms ile nasıl çalışabileceğinizi bildiğinizi varsayar. Kullanmıyorsanız bkz. ASP.NET 4.5 Web Forms Kullanmaya Başlama. ASP.NET MVC çerçevesiyle çalışmayı tercih ediyorsanız bkz. ASP.NET MVC kullanarak Entity Framework ile Çalışmaya Başlama.

Yazılım sürümleri

Öğreticide gösterilmiştir Ayrıca ile de çalışır
Windows 7 Windows 8
Visual Studio 2010 Web için Visual Studio 2010 Express. Öğretici, Visual Studio'nun sonraki sürümleriyle test edilmedi. Menü seçimlerinde, iletişim kutularında ve şablonlarda birçok farklılık vardır.
.NET 4 .NET 4.5, .NET 4 ile geriye dönük olarak uyumludur, ancak öğretici .NET 4.5 ile test edilmemiştir.
Entity Framework 4 Öğretici, Entity Framework'ün sonraki sürümleriyle test edilmedi. Entity Framework 5'den başlayarak EF, EF 4.1 ile sunulanı varsayılan olarak DbContext API kullanır. EntityDataSource denetimi API'yi ObjectContext kullanacak şekilde tasarlanmıştır. EntityDataSource denetimini API ile DbContext kullanma hakkında bilgi için bu blog gönderisine bakın.

Sorular

Öğreticiyle doğrudan ilgili olmayan sorularınız varsa bunları ASP.NET Entity Framework forumu, Entity Frameworkve LINQ to Entities forumu veya StackOverflow.com gönderebilirsiniz.

Denetim EntityDataSource , çok hızlı bir şekilde uygulama oluşturmanıza olanak tanır, ancak genellikle .aspx sayfalarınızda önemli miktarda iş mantığı ve veri erişim mantığı tutmanızı gerektirir. Uygulamanızın karmaşıklığını artırmasını ve sürekli bakım gerektirmesini bekliyorsanız, daha sürdürülebilir bir n katmanlı veya katmanlı uygulama yapısı oluşturmak için önceden daha fazla geliştirme süresine yatırım yapabilirsiniz. Bu mimariyi uygulamak için sunu katmanını iş mantığı katmanından (BLL) ve veri erişim katmanından (DAL) ayırırsınız. Bu yapıyı uygulamanın bir yolu, denetim yerine denetimi kullanmaktır ObjectDataSourceEntityDataSource . Denetimi kullandığınızda ObjectDataSource , kendi veri erişim kodunuzu uygular ve ardından diğer veri kaynağı denetimleriyle aynı özelliklerin birçoğuna sahip bir denetim kullanarak .aspx sayfalarında çağırırsınız. Bu, n katmanlı yaklaşımın avantajlarını veri erişimi için Web Forms denetimi kullanmanın avantajlarıyla birleştirmenizi sağlar.

Denetim ObjectDataSource , diğer şekillerde de daha fazla esneklik sağlar. Kendi veri erişim kodunuzu yazdığınızdan, denetimin gerçekleştirmek üzere tasarlandığı görevler EntityDataSource olan belirli bir varlık türünü okumak, eklemek, güncelleştirmek veya silmekten daha fazlasını yapmak daha kolaydır. Örneğin, bir varlık her güncelleştirildiğinde günlüğe kaydetme gerçekleştirebilir, bir varlık silindiğinde verileri arşivleyebilir veya yabancı anahtar değerine sahip bir satır eklerken ilgili verileri gerektiği gibi otomatik olarak denetleyip güncelleştirebilirsiniz.

İş Mantığı ve Depo Sınıfları

Denetim ObjectDataSource , oluşturduğunuz bir sınıfı çağırarak çalışır. sınıfı, verileri alan ve güncelleştiren yöntemler içerir ve bu yöntemlerin adlarını işaretleme denetimine ObjectDataSource sağlarsınız. İşleme veya geri gönderme işlemi sırasında belirttiğiniz ObjectDataSource yöntemleri çağırır.

Temel CRUD işlemlerinin yanı sıra, denetimle birlikte kullanmak için oluşturduğunuz sınıfın ObjectDataSource verileri okurken veya güncelleştirirken iş mantığını yürütmesi ObjectDataSource gerekebilir. Örneğin, bir departmanı güncelleştirdiğinizde, başka hiçbir departmanın aynı yöneticiye sahip olmadığını doğrulamanız gerekebilir çünkü bir kişi birden fazla departmanın yöneticisi olamaz.

ObjectDataSource Sınıfına genel bakış gibi bazı ObjectDataSource belgelerde denetim, hem iş mantığını hem de veri erişim mantığını içeren bir iş nesnesi olarak adlandırılan bir sınıfı çağırır. Bu öğreticide, iş mantığı ve veri erişim mantığı için ayrı sınıflar oluşturacaksınız. Veri erişim mantığını kapsülleyen sınıfa depo adı verilir. İş mantığı sınıfı hem iş mantığı yöntemlerini hem de veri erişim yöntemlerini içerir, ancak veri erişim yöntemleri veri erişim görevlerini gerçekleştirmek için depoyu çağırır.

Ayrıca BLL'niz ile DAL arasında BLL'nin otomatik birim testini kolaylaştıran bir soyutlama katmanı da oluşturacaksınız. Bu soyutlama katmanı, bir arabirim oluşturarak ve iş mantığı sınıfında depo örneği oluştururken arabirimini kullanarak uygulanır. Bu, iş mantığı sınıfına depo arabirimini uygulayan herhangi bir nesneye başvuru sağlamanızı mümkün kılar. Normal işlem için Entity Framework ile çalışan bir depo nesnesi sağlarsınız. Test için, koleksiyon olarak tanımlanan sınıf değişkenleri gibi kolayca işleyebileceğiniz bir şekilde depolanan verilerle çalışan bir depo nesnesi sağlarsınız.

Aşağıdaki çizimde, depo içermeyen veri erişim mantığı içeren bir iş mantığı sınıfı ile depo kullanan bir iş mantığı arasındaki fark gösterilmektedir.

Görüntü05

İlk olarak, denetimin ObjectDataSource yalnızca temel veri erişim görevlerini yerine getirmesi nedeniyle doğrudan bir depoya bağlı olduğu web sayfaları oluşturacaksınız. Sonraki öğreticide doğrulama mantığına sahip bir iş mantığı sınıfı oluşturacak ve denetimi depo sınıfı yerine bu sınıfa bağlayacaksınız ObjectDataSource . Doğrulama mantığı için birim testleri de oluşturacaksınız. Bu serinin üçüncü öğreticisinde uygulamaya sıralama ve filtreleme işlevi ekleyeceksiniz.

Bu öğreticide oluşturduğunuz sayfalar, Başlarken öğretici serisinde oluşturduğunuz veri modelinin varlık kümesiyle Departments çalışır.

Departmanlar sayfanızın nasıl görünmesi gerektiğini gösteren ekran görüntüsü.

Görüntü02

Veritabanını ve Veri Modelini Güncelleştirme

Bu öğreticiye veritabanında iki değişiklik yaparak başlayacaksınız. Her ikisi de Entity Framework ile Çalışmaya Başlama ve Web Forms öğreticilerinde oluşturduğunuz veri modelinde ilgili değişiklikleri gerektirir. Bu öğreticilerden birinde, veritabanı değişikliğinden sonra veri modelini veritabanıyla eşitlemek için tasarımcıda el ile değişiklikler yaptınız. Bu öğreticide, veri modelini otomatik olarak güncelleştirmek için tasarımcının Veritabanından Modeli Güncelleştir aracını kullanacaksınız.

Veritabanına İlişki Ekleme

Visual Studio'da, Entity Framework ile Çalışmaya Başlama ve Web Forms öğretici serisinde oluşturduğunuz Contoso University web uygulamasını açın ve ardından veritabanı diyagramını SchoolDiagram açın.

Veritabanı diyagramındaki tabloya Department bakarsanız, bir sütunu olduğunu Administrator görürsünüz. Bu sütun tablonun yabancı anahtarıdır Person , ancak veritabanında yabancı anahtar ilişkisi tanımlanmaz. Entity Framework'ün bu ilişkiyi otomatik olarak işleyebilmesi için ilişkiyi oluşturmanız ve veri modelini güncelleştirmeniz gerekir.

Veritabanı diyagramında tabloya sağ tıklayın ve İlişkiler'iDepartment seçin.

Görüntü80

Yabancı Anahtar İlişkileri kutusunda Ekle'ye tıklayın ve ardından Tablolar ve Sütunlar Belirtimi için üç noktaya tıklayın.

Resim81

Tablolar ve Sütunlar iletişim kutusunda, birincil anahtar tablosunu ve alanını Person ve PersonIDolarak, yabancı anahtar tablosu ve alanını ve Administratorolarak Department ayarlayın. (Bunu yaptığınızda, ilişki adı olarak değişir FK_Department_DepartmentFK_Department_Person.)

Resim82

Tablolar ve Sütunlar kutusunda Tamam'a tıklayın, Yabancı Anahtar İlişkileri kutusunda Kapat'a tıklayın ve değişiklikleri kaydedin. ve Department tablolarını kaydetmek Person isteyip istemediğiniz sorulursa Evet'e tıklayın.

Not

Zaten sütunda Administrator yer alan verilere karşılık gelen satırları sildiysenizPerson, bu değişikliği kaydedemezsiniz. Bu durumda, her Department satırdaki değerin tabloda gerçekten var olan bir kaydın kimliğini içerdiğinden emin olmak Administrator için Sunucu Gezgini'ndeki tablo düzenleyicisini Person kullanın.

Değişikliği kaydettikten sonra, söz konusu kişi departman yöneticisiyse tablodan Person satır silemezsiniz. Üretim uygulamasında, veritabanı kısıtlaması silmeyi engellediğinde belirli bir hata iletisi sağlayabilir veya basamaklı silme belirtebilirsiniz. Basamaklı silmenin nasıl belirtileceğini gösteren bir örnek için bkz . Entity Framework ve ASP.NET – Başlarken Bölüm 2.

Veritabanına Görünüm Ekleme

Oluşturacağınız yeni Departments.aspx sayfasında, kullanıcıların departman yöneticilerini seçebilmesi için adları "son, ilk" biçiminde olacak şekilde eğitmenlerin yer aldığı bir açılan liste sağlamak istiyorsunuz. Bunu daha kolay hale getirmek için veritabanında bir görünüm oluşturacaksınız. Görünüm yalnızca açılan listenin gerektirdiği verilerden oluşur: tam ad (düzgün biçimlendirilmiş) ve kayıt anahtarı.

Sunucu Gezgini'ndeSchool.mdf dosyasını genişletin, Görünümler klasörüne sağ tıklayın ve Yeni Görünüm Ekle'yi seçin.

Resim06

Tablo Ekle iletişim kutusu görüntülendiğinde Kapat'a tıklayın ve aşağıdaki SQL deyimini SQL bölmesine yapıştırın:

SELECT        LastName + ',' + FirstName AS FullName, PersonID
FROM          dbo.Person
WHERE        (HireDate IS NOT NULL)

Görünümü olarak vInstructorNamekaydedin.

Veri Modelini Güncelleştirme

DAL klasöründe SchoolModel.edmx dosyasını açın, tasarım yüzeyine sağ tıklayın ve Veritabanından Modeli Güncelleştir'i seçin.

Resim07

Veritabanı Nesnelerinizi Seçin iletişim kutusunda Ekle sekmesini seçin ve yeni oluşturduğunuz görünümü seçin.

Resim08

Finish (Son) düğmesine tıklayın.

Tasarımcıda, aracın ve varlıkları arasında DepartmentPerson bir vInstructorName varlık ve yeni bir ilişkilendirme oluşturduğunu görürsünüz.

Resim13

Not

Çıkış ve Hata Listesi pencerelerinde, aracın yeni vInstructorName görünüm için otomatik olarak bir birincil anahtar oluşturduğunu bildiren bir uyarı iletisi görebilirsiniz. Bu beklenen bir davranıştır.

Koddaki yeni vInstructorName varlığa başvurduğunda, küçük harfli bir "v" ön ekini eklemeye ilişkin veritabanı kuralını kullanmak istemezsiniz. Bu nedenle, modelde varlık ve varlık kümesini yeniden adlandıracaksınız.

Model Tarayıcısı'nı açın. Varlık türü ve görünüm olarak listelendiğini görürsünüz vInstructorName .

Resim14

SchoolModel (SchoolModel.Store değil) altında vInstructorName öğesine sağ tıklayın ve Özellikler'i seçin. Özellikler penceresinde Name özelliğini "InstructorName" olarak değiştirin ve Varlık Kümesi Adı özelliğini "InstructorNames" olarak değiştirin.

Resim15

Veri modelini kaydedip kapatın ve projeyi yeniden derleyin.

Depo Sınıfı ve ObjectDataSource Denetimi Kullanma

DAL klasöründe yeni bir sınıf dosyası oluşturun, SchoolRepository.cs olarak adlandırın ve mevcut kodu aşağıdaki kodla değiştirin:

using System;
using System.Collections.Generic;
using System.Linq;
using ContosoUniversity.DAL;

namespace ContosoUniversity.DAL
{
    public class SchoolRepository : IDisposable
    {
        private SchoolEntities context = new SchoolEntities();

        public IEnumerable<Department> GetDepartments()
        {
            return context.Departments.Include("Person").ToList();
        }

        private bool disposedValue = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposedValue)
            {
                if (disposing)
                {
                    context.Dispose();
                }
            }
            this.disposedValue = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

    }
}

Bu kod, varlık kümesindeki Departments tüm varlıkları döndüren tek GetDepartments bir yöntem sağlar. Döndürülen her satır için gezinti özelliğine Person erişeceğinizden, yöntemini kullanarak Include bu özellik için istekli yükleme belirtirsiniz. sınıfı, nesnesi atıldığında veritabanı bağlantısının serbest bırakıldığından emin olmak için arabirimini de uygular IDisposable .

Not

Yaygın bir uygulama, her varlık türü için bir depo sınıfı oluşturmaktır. Bu öğreticide, birden çok varlık türü için bir depo sınıfı kullanılır. Depo düzeni hakkında daha fazla bilgi için Entity Framework ekibinin blogunda ve Julie Lerman'ın blogunda yer alangönderilere bakın.

yöntemi, GetDepartments depo nesnesinin kendisi atıldıktan sonra bile döndürülen koleksiyonun kullanılabilir olmasını sağlamak için nesne yerine bir IQueryable nesnesi döndürürIEnumerable. Bir IQueryable nesne her erişildiğinde veritabanı erişimine neden olabilir, ancak veri bağlantısı denetimi verileri işlemeye çalıştığında depo nesnesi atılabilir. Nesne yerine IEnumerable nesne gibi başka bir IList koleksiyon türü döndürebilirsiniz. Ancak, bir IEnumerable nesnenin döndürülmesi döngüler ve LINQ sorguları gibi foreach tipik salt okunur liste işleme görevlerini gerçekleştirebilmenizi sağlar, ancak koleksiyondaki öğeleri ekleyemez veya kaldıramazsınız, bu da bu değişikliklerin veritabanında kalıcı olacağı anlamına gelebilir.

Site.Master ana sayfasını kullanan bir Departments.aspx sayfası oluşturun ve adlı Content2denetime aşağıdaki işaretlemeyi Content ekleyin:

<h2>Departments</h2>
    <asp:ObjectDataSource ID="DepartmentsObjectDataSource" runat="server" 
        TypeName="ContosoUniversity.DAL.SchoolRepository" 
        DataObjectTypeName="ContosoUniversity.DAL.Department" 
        SelectMethod="GetDepartments" >
    </asp:ObjectDataSource>
    <asp:GridView ID="DepartmentsGridView" runat="server" AutoGenerateColumns="False"
        DataSourceID="DepartmentsObjectDataSource"  >
        <Columns>
            <asp:CommandField ShowEditButton="True" ShowDeleteButton="True"
                ItemStyle-VerticalAlign="Top">
            </asp:CommandField>
            <asp:DynamicField DataField="Name" HeaderText="Name" SortExpression="Name" ItemStyle-VerticalAlign="Top" />
            <asp:DynamicField DataField="Budget" HeaderText="Budget" SortExpression="Budget" ItemStyle-VerticalAlign="Top" />
            <asp:DynamicField DataField="StartDate" HeaderText="Start Date" ItemStyle-VerticalAlign="Top" />
            <asp:TemplateField HeaderText="Administrator" SortExpression="Person.LastName" ItemStyle-VerticalAlign="Top" >
                <ItemTemplate>
                    <asp:Label ID="AdministratorLastNameLabel" runat="server" Text='<%# Eval("Person.LastName") %>'></asp:Label>,
                    <asp:Label ID="AdministratorFirstNameLabel" runat="server" Text='<%# Eval("Person.FirstMidName") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

Bu işaretleme, yeni oluşturduğunuz depo sınıfını kullanan bir ObjectDataSource denetim ve verileri görüntülemek için bir GridView denetim oluşturur. Denetim GridViewDüzenle ve Sil komutlarını belirtir, ancak henüz bunları desteklemek için kod eklememişsinizdir.

Otomatik veri biçimlendirme ve doğrulama işlevinden yararlanabilmeniz için çeşitli sütunlarda denetimler kullanılır DynamicField . Bunların çalışması için olay işleyicisinde Page_Init yöntemini çağırmanız EnableDynamicData gerekir. (DynamicControl denetimler gezinti özellikleriyle çalışmadığından alanda kullanılmaz Administrator .)

Daha sonra kılavuza Vertical-Align="Top" iç içe GridView denetime sahip bir sütun eklediğinizde öznitelikler önemli hale gelir.

Departments.aspx.cs dosyasını açın ve aşağıdaki using deyimi ekleyin:

using ContosoUniversity.DAL;

Ardından sayfanın Init olayı için aşağıdaki işleyiciyi ekleyin:

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

DAL klasöründe Department.cs adlı yeni bir sınıf dosyası oluşturun ve mevcut kodu aşağıdaki kodla değiştirin:

using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.DAL
{
    [MetadataType(typeof(DepartmentMetaData))]
    public partial class Department
    {
    }

    public class DepartmentMetaData
    {
        [DataType(DataType.Currency)]
        [Range(0, 1000000, ErrorMessage = "Budget must be less than $1,000,000.00")]
        public Decimal Budget { get; set; }

        [DisplayFormat(DataFormatString="{0:d}",ApplyFormatInEditMode=true)]
        public DateTime StartDate { get; set; }

    }
}

Bu kod veri modeline meta veri ekler. Veri türü Decimalolsa da varlığın özelliğinin Department para birimini temsil ettiğini Budget belirtir ve değerin 0 ile 1.000.000.00 TL arasında olması gerektiğini belirtir. Ayrıca özelliğin StartDate aa/gg/y biçiminde bir tarih olarak biçimlendirilmesi gerektiğini belirtir.

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

Çalıştırıldığında Departmanlar sayfasını gösteren ekran görüntüsü.

Departments.aspx sayfa işaretlemesinde Bütçe veya Başlangıç Tarihi sütunları için bir biçim dizesi belirtmemiş olmanıza rağmen, Department.cs dosyasında sağladığınız meta veriler kullanılarak denetimler tarafından DynamicField bu sütunlara varsayılan para birimi ve tarih biçimlendirmesi uygulandığına dikkat edin.

Ekleme ve Silme İşlevi Ekleme

SchoolRepository.cs dosyasını açın, bir Insert yöntem ve Delete yöntem oluşturmak için aşağıdaki kodu ekleyin. Kod, yöntemi tarafından Insert kullanılmak üzere bir sonraki kullanılabilir kayıt anahtarı değerini hesaplayan adlı GenerateDepartmentID bir yöntem de içerir. Veritabanı tablo için Department bunu otomatik olarak hesaplayacak şekilde yapılandırılmadığından bu gereklidir.

public void InsertDepartment(Department department)
{
    try
    {
        department.DepartmentID = GenerateDepartmentID();
        context.Departments.AddObject(department);
        context.SaveChanges();
    }
    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 DeleteDepartment(Department department)
{
    try
    {
        context.Departments.Attach(department);
        context.Departments.DeleteObject(department);
        context.SaveChanges();
    }
    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;
    }
}

private Int32 GenerateDepartmentID()
{
    Int32 maxDepartmentID = 0;
    var department = (from d in GetDepartments()
                      orderby d.DepartmentID descending
                      select d).FirstOrDefault();
    if (department != null)
    {
        maxDepartmentID = department.DepartmentID + 1;
    }
    return maxDepartmentID;
}

Attach Yöntemi

yöntemi, DeleteDepartment bellekteki Attach varlık ile temsil edilen veritabanı satırı arasında nesne bağlamı nesne durum yöneticisinde tutulan bağlantıyı yeniden oluşturmak için yöntemini çağırır. Yöntemin yöntemini çağırmadan SaveChanges önce bu durum ortaya çıkmalıdır.

Nesne bağlamı terimi, varlık kümelerinize ve varlıklarınıza erişmek için kullandığınız sınıftan ObjectContext türetilen Entity Framework sınıfına başvurur. Bu projenin kodunda, sınıfı olarak adlandırılır SchoolEntitiesve bir örneği her zaman olarak adlandırılır context. Nesne bağlamın nesne durum yöneticisi , sınıfından ObjectStateManager türetilen bir sınıftır. Nesne kişisi, varlık nesnelerini depolamak ve her birinin veritabanındaki ilgili tablo satırı veya satırlarıyla eşitlenmiş olup olmadığını izlemek için nesne durum yöneticisini kullanır.

Bir varlığı okuduğunuzda, nesne bağlamı bunu nesne durum yöneticisinde depolar ve nesnenin bu gösteriminin veritabanıyla eşitlenmiş olup olmadığını izler. Örneğin, bir özellik değerini değiştirirseniz, değiştirdiğiniz özelliğin artık veritabanıyla eşitlenmediğini belirtmek için bir bayrak ayarlanır. Ardından yöntemini çağırdığınızda SaveChanges nesne bağlamı veritabanında ne yapacağını bilir çünkü nesne durumu yöneticisi varlığın geçerli durumu ile veritabanının durumu arasında tam olarak nelerin farklı olduğunu bilir.

Ancak, bir sayfa işlendikten sonra nesne durum yöneticisindeki her şeyle birlikte bir varlığı okuyan nesne bağlam örneği atıldığından, bu işlem genellikle bir web uygulamasında çalışmaz. Değişiklikleri uygulaması gereken nesne bağlam örneği, geri gönderme işlemi için örneklenmiş yeni bir örnektir. yöntemi söz konusu olduğunda DeleteDepartment denetim, ObjectDataSource görüntüleme durumundaki değerlerden varlığın özgün sürümünü sizin için yeniden oluşturur, ancak bu yeniden oluşturulan Department varlık nesne durum yöneticisinde mevcut değildir. Bu yeniden oluşturulan varlıkta yöntemini çağırdıysanız DeleteObject , nesne bağlamı varlığın veritabanıyla eşitlenmiş olup olmadığını bilmediğinden çağrı başarısız olur. Ancak yöntemini çağırmak Attach , yeniden oluşturulan varlık ile varlık nesne bağlamının önceki bir örneğinde okunduğunda başlangıçta otomatik olarak yapılan veritabanındaki değerler arasında aynı izlemeyi yeniden oluşturur.

Nesne bağlamını nesne durum yöneticisindeki varlıkları izlemek istemediğiniz zamanlar olabilir ve bunu yapmasını önlemek için bayraklar ayarlayabilirsiniz. Bunun örnekleri, bu serinin sonraki öğreticilerinde gösterilmiştir.

SaveChanges Yöntemi

Bu basit depo sınıfı, CRUD işlemlerinin nasıl gerçekleştirileceklerine ilişkin temel ilkeleri gösterir. Bu örnekte, yöntemi her güncelleştirmeden SaveChanges hemen sonra çağrılır. Bir üretim uygulamasında veritabanının SaveChanges ne zaman güncelleştirilebileceği üzerinde daha fazla denetim sağlamak için yöntemini ayrı bir yöntemden çağırmak isteyebilirsiniz. (Sonraki öğreticinin sonunda, ilgili güncelleştirmeleri koordine etmeye yönelik yaklaşımlardan biri olan çalışma düzeni birimini ele alan bir teknik incelemenin bağlantısını bulacaksınız.) Ayrıca örnekte yönteminin DeleteDepartment eşzamanlılık çakışmalarını işlemeye yönelik kod içermediğini, bunu yapacak kodun bu serinin sonraki öğreticilerinde ekleneceğini de göreceksiniz.

Eklerken Seçecek Eğitmen Adlarını Alma

Kullanıcıların yeni departmanlar oluştururken açılan listedeki eğitmen listesinden yönetici seçebilmeleri gerekir. Bu nedenle, daha önce oluşturduğunuz görünümü kullanarak eğitmen listesini almak için bir yöntem oluşturmak üzere SchoolRepository.cs dosyasına aşağıdaki kodu ekleyin:

public IEnumerable<InstructorName> GetInstructorNames()
{
    return context.InstructorNames.OrderBy("it.FullName").ToList();
}

Departman Eklemek için Sayfa Oluşturma

Site.Master sayfasını kullanan bir DepartmentsAdd.aspx sayfası oluşturun ve adlı Content2denetime aşağıdaki işaretlemeyi Content ekleyin:

<h2>Departments</h2>
    <asp:ObjectDataSource ID="DepartmentsObjectDataSource" runat="server" 
        TypeName="ContosoUniversity.DAL.SchoolRepository" DataObjectTypeName="ContosoUniversity.DAL.Department"
        InsertMethod="InsertDepartment" >
    </asp:ObjectDataSource>
    <asp:DetailsView ID="DepartmentsDetailsView" runat="server" 
        DataSourceID="DepartmentsObjectDataSource" AutoGenerateRows="False"
        DefaultMode="Insert" OnItemInserting="DepartmentsDetailsView_ItemInserting">
        <Fields>
            <asp:DynamicField DataField="Name" HeaderText="Name" />
            <asp:DynamicField DataField="Budget" HeaderText="Budget" />
            <asp:DynamicField DataField="StartDate" HeaderText="Start Date" />
            <asp:TemplateField HeaderText="Administrator">
                <InsertItemTemplate>
                    <asp:ObjectDataSource ID="InstructorsObjectDataSource" runat="server" 
                        TypeName="ContosoUniversity.DAL.SchoolRepository" 
                        DataObjectTypeName="ContosoUniversity.DAL.InstructorName"
                        SelectMethod="GetInstructorNames" >
                    </asp:ObjectDataSource>
                    <asp:DropDownList ID="InstructorsDropDownList" runat="server" 
                        DataSourceID="InstructorsObjectDataSource"
                        DataTextField="FullName" DataValueField="PersonID" OnInit="DepartmentsDropDownList_Init">
                    </asp:DropDownList>
                </InsertItemTemplate>
            </asp:TemplateField>
            <asp:CommandField ShowInsertButton="True" />
        </Fields>
    </asp:DetailsView>
   <asp:ValidationSummary ID="DepartmentsValidationSummary" runat="server" 
        ShowSummary="true" DisplayMode="BulletList"  />

Bu işaretleme, biri yeni Department varlıklar eklemek ve diğeri departman yöneticilerini seçmek için kullanılan denetim için eğitmen adlarını almak için DropDownList iki ObjectDataSource denetim oluşturur. İşaretleme, yeni departmanlar girmek için bir DetailsView denetim oluşturur ve yabancı anahtar değerini ayarlayabilmeniz Administrator için denetimin ItemInserting olayı için bir işleyici belirtir. Sonunda, hata iletilerini görüntülemek için bir ValidationSummary denetim bulunur.

DepartmentsAdd.aspx.cs dosyasını açın ve aşağıdaki using deyimi ekleyin:

using ContosoUniversity.DAL;

Aşağıdaki sınıf değişkenini ve yöntemlerini ekleyin:

private DropDownList administratorsDropDownList;

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

protected void DepartmentsDropDownList_Init(object sender, EventArgs e)
{
    administratorsDropDownList = sender as DropDownList;
}

protected void DepartmentsDetailsView_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
    e.Values["Administrator"] = administratorsDropDownList.SelectedValue;
}

yöntemi Dinamik Page_Init Veri işlevselliğini etkinleştirir. Denetimin Init olayının DropDownList işleyicisi denetime bir başvuru kaydeder ve denetimin Inserting olayının DetailsView işleyicisi seçilen eğitmenin değerini almak PersonID ve varlığın yabancı anahtar özelliğini güncelleştirmek Administrator için bu başvuruyu Department kullanır.

Sayfayı çalıştırın, yeni bir departman için bilgi ekleyin ve ekle bağlantısına tıklayın.

Resim04

Başka bir yeni departmanın değerlerini girin. Bütçe alanına 1.000.000.00'dan büyük bir sayı girin ve sekme tuşuyla sonraki alana geçin. Alanda bir yıldız işareti görünür ve fare işaretçisini bu alanın üzerinde tutarsanız, bu alanın meta verilerine girdiğiniz hata iletisini görebilirsiniz.

Resim03

Ekle'ye tıkladığınızda, sayfanın en altındaki denetim tarafından ValidationSummary görüntülenen hata iletisini görürsünüz.

Resim12

Ardından tarayıcıyı kapatın ve Departments.aspx sayfasını açın. Denetime bir öznitelik ve DataKeyNamesGridView denetime bir DeleteMethod öznitelik ObjectDataSource ekleyerek Departments.aspx sayfasına silme özelliği ekleyin. Bu denetimlerin açılış etiketleri artık aşağıdaki örneğe benzer olacaktır:

<asp:ObjectDataSource ID="DepartmentsObjectDataSource" runat="server" 
        TypeName="ContosoUniversity.DAL.SchoolRepository" 
        DataObjectTypeName="ContosoUniversity.DAL.Department"
        SelectMethod="GetDepartments" 
        DeleteMethod="DeleteDepartment" >

    <asp:GridView ID="DepartmentsGridView" runat="server" AutoGenerateColumns="False"
        DataSourceID="DepartmentsObjectDataSource" DataKeyNames="DepartmentID" >

Sayfayı çalıştırın.

Çalıştırıldıktan sonra Departmanlar sayfasını gösteren ekran görüntüsü.

DepartmentsAdd.aspx sayfasını çalıştırdığınızda eklediğiniz bölümü silin.

Güncelleştirme İşlevselliği Ekleme

SchoolRepository.cs dosyasını açın ve aşağıdaki Update yöntemi ekleyin:

public void UpdateDepartment(Department department, Department origDepartment)
{
    try
    {
        context.Departments.Attach(origDepartment);
        context.ApplyCurrentValues("Departments", department);
        context.SaveChanges();
    }
    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;
    }
}

Departments.aspx sayfasında Güncelleştir'e tıkladığınızda, ObjectDataSource denetim yöntemine UpdateDepartment geçirmek için iki Department varlık oluşturur. Biri görünüm durumunda depolanmış özgün değerleri, diğeri de denetime GridView girilen yeni değerleri içerir. yöntemindeki UpdateDepartment kod, varlık ile veritabanındakiler arasında izleme oluşturmak için özgün değerleri Attach içeren varlığı yöntemine geçirirDepartment. Ardından kod, yeni değerleri içeren varlığı yöntemine ApplyCurrentValues geçirirDepartment. Nesne bağlamı eski ve yeni değerleri karşılaştırır. Yeni bir değer eski bir değerden farklıysa, nesne bağlamı özellik değerini değiştirir. Yöntemi SaveChanges daha sonra veritabanında yalnızca değiştirilen sütunları güncelleştirir. (Ancak, bu varlığın güncelleştirme işlevi bir saklı yordamla eşlenmişse, hangi sütunların değiştirildiğine bakılmaksızın satırın tamamı güncelleştirilir.)

Departments.aspx dosyasını açın ve denetime aşağıdaki öznitelikleri DepartmentsObjectDataSource ekleyin:

  • UpdateMethod="UpdateDepartment"
  • ConflictDetection="CompareAllValues"
    Bu, yöntemindeki yeni değerlerle karşılaştırılabilmesi için eski değerlerin görünüm durumunda depolanmasına Update neden olur.
  • OldValuesParameterFormatString="orig{0}"
    Bu, denetimine özgün değerler parametresinin adının olduğunu origDepartment bildirir.

Denetimin açılış etiketinin ObjectDataSource işaretlemesi artık aşağıdaki örneğe benzer:

<asp:ObjectDataSource ID="DepartmentsObjectDataSource" runat="server" 
        TypeName="ContosoUniversity.DAL.SchoolRepository" 
        DataObjectTypeName="ContosoUniversity.DAL.Department" 
        SelectMethod="GetDepartments" DeleteMethod="DeleteDepartment" 
        UpdateMethod="UpdateDepartment"
        ConflictDetection="CompareAllValues" 
        OldValuesParameterFormatString="orig{0}" >

Denetime GridView bir OnRowUpdating="DepartmentsGridView_RowUpdating" öznitelik ekleyin. Özellik değerini kullanıcının açılan listede seçtiği satıra göre ayarlamak Administrator için bunu kullanacaksınız. Açma GridView etiketi artık aşağıdaki örneğe benzer:

<asp:GridView ID="DepartmentsGridView" runat="server" AutoGenerateColumns="False"
        DataSourceID="DepartmentsObjectDataSource" DataKeyNames="DepartmentID"
        OnRowUpdating="DepartmentsGridView_RowUpdating">

Bu sütunun denetiminden AdministratorGridView hemen sonra, denetime ItemTemplate sütun için bir EditItemTemplate denetim ekleyin:

<EditItemTemplate>
                    <asp:ObjectDataSource ID="InstructorsObjectDataSource" runat="server" DataObjectTypeName="ContosoUniversity.DAL.InstructorName"
                        SelectMethod="GetInstructorNames" TypeName="ContosoUniversity.DAL.SchoolRepository">
                    </asp:ObjectDataSource>
                    <asp:DropDownList ID="InstructorsDropDownList" runat="server" DataSourceID="InstructorsObjectDataSource"
                        SelectedValue='<%# Eval("Administrator")  %>'
                        DataTextField="FullName" DataValueField="PersonID" OnInit="DepartmentsDropDownList_Init" >
                    </asp:DropDownList>
                </EditItemTemplate>

Bu EditItemTemplate denetim, DepartmentsAdd.aspx sayfasındaki denetime InsertItemTemplate benzer. Aradaki fark, denetimin ilk değerinin özniteliği kullanılarak SelectedValue ayarlanmasıdır.

Denetimden GridView önce, DepartmentsAdd.aspx sayfasında yaptığınız gibi bir ValidationSummary denetim ekleyin.

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

Departments.aspx.cs dosyasını açın ve kısmi sınıf bildiriminden hemen sonra, denetime başvurmak DropDownList üzere özel bir alan oluşturmak için aşağıdaki kodu ekleyin:

private DropDownList administratorsDropDownList;

Ardından denetimin olayı ve denetimin DropDownListInitGridViewRowUpdating olayı için işleyiciler ekleyin:

protected void DepartmentsDropDownList_Init(object sender, EventArgs e)
{
    administratorsDropDownList = sender as DropDownList;
}

protected void DepartmentsGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    e.NewValues["Administrator"] = administratorsDropDownList.SelectedValue;
}

olay işleyicisi Init , sınıf alanındaki denetime DropDownList bir başvuru kaydeder. Olay işleyicisi RowUpdating , kullanıcının girdiği değeri almak ve varlığın özelliğine uygulamak için Administrator başvuruyu Department kullanır.

DepartmentsAdd.aspx sayfasını kullanarak yeni bir departman ekleyin, ardından Departments.aspx sayfasını çalıştırın ve eklediğiniz satırda Düzenle'ye tıklayın.

Not

Veritabanındaki geçersiz veriler nedeniyle, eklemediğiniz satırları (başka bir ifadeyle veritabanında bulunan) düzenleyemezsiniz; veritabanıyla oluşturulan satırların yöneticileri öğrencilerdir. Bunlardan birini düzenlemeye çalışırsanız, şunun gibi bir hata bildiren bir hata sayfası alırsınız: 'InstructorsDropDownList' has a SelectedValue which is invalid because it does not exist in the list of items.

Resim10

Geçersiz bir Bütçe tutarı girip Güncelleştir'e tıklarsanız, Departments.aspx sayfasında gördüğünüz yıldız ve hata iletisinin aynısını görürsünüz.

Bir alan değerini değiştirin veya farklı bir yönetici seçin ve Güncelleştir'e tıklayın. Değişiklik görüntülenir.

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

Bu, Entity Framework ile temel CRUD (oluşturma, okuma, güncelleştirme, silme) işlemlerinin denetimini kullanmaya ObjectDataSource giriş işlemini tamamlar. Basit bir n katmanlı uygulama oluşturdunuz, ancak iş mantığı katmanı yine de veri erişim katmanıyla sıkı bir şekilde birleştirilir ve bu da otomatik birim testini karmaşıklaştırır. Aşağıdaki öğreticide, birim testini kolaylaştırmak için depo düzeninin nasıl uygulandığını göreceksiniz.