WinForms ile veri bağlama

Bu adım adım izlenecek yol, POCO türlerinin bir "ana-ayrıntı" formunda pencere formları (WinForms) denetimlerine nasıl bağlanacağını gösterir. Uygulama, nesneleri veritabanındaki verilerle doldurmak, değişiklikleri izlemek ve verileri veritabanına kalıcı hale getirmek için Entity Framework kullanır.

Model bire çok ilişkiye katılan iki tür tanımlar: kategori (principal\master) ve ürün (bağımlılık \ ayrıntı). ardından Visual Studio araçları, modelde tanımlanan türleri WinForms denetimlerine bağlamak için kullanılır. WinForms veri bağlama çerçevesi ilgili nesneler arasında gezinmeyi sağlar: ana görünümdeki satırları seçme, ayrıntı görünümünün karşılık gelen alt verilerle güncelleştirilmesine neden olur.

bu izlenecek yolda ekran görüntüleri ve kod listeleri Visual Studio 2013 alınmıştır, ancak bu kılavuzu Visual Studio 2012 veya Visual Studio 2010 ile tamamlayabilirsiniz.

Önkoşullar

bu izlenecek yolu tamamlamak için Visual Studio 2013, Visual Studio 2012 veya Visual Studio 2010 ' i yüklemiş olmanız gerekir.

Visual Studio 2010 kullanıyorsanız, NuGet de yüklemelisiniz. Daha fazla bilgi için bkz. yükleme NuGet.

Uygulamayı oluşturma

  • Visual Studio’yu açın
  • Dosya- Yeni- > Project....
  • sol bölmedeki Windows seçin ve sağ bölmedeki formsapplication Windows
  • Ad olarak Winformyüzthefsample girin
  • Tamam'ı seçin

Entity Framework NuGet paketini yükler

  • Çözüm Gezgini, Winformyüzthefsample projesine sağ tıklayın
  • NuGet paketlerini yönet ' i seçin...
  • NuGet paketlerini yönet iletişim kutusunda çevrimiçi sekmesini seçin ve entityframework paketini seçin
  • Install 'a tıklayın

    Not

    EntityFramework derlemesine ek olarak, System. ComponentModel. Dataaçıklamalarda bir başvuru de eklenir. Projenin System. Data. Entity başvurusu varsa, EntityFramework paketi yüklendiğinde kaldırılır. System. Data. Entity derlemesi artık Entity Framework 6 uygulamaları için kullanılmıyor.

Koleksiyonlar için ISource uygulama

Windows Forms kullanılırken sıralama ile iki yönlü veri bağlamayı etkinleştirmek için koleksiyon özelliklerinin ısource arabirimini uygulaması gerekir. Bunu yapmak için ObservableCollection ISource işlevselliği eklemek üzere genişletireceğiz.

  • Projeye bir ObservableListSource sınıfı ekleyin:
    • Proje adına sağ tıklayın
    • Ekle- Yeni öğe Seç
    • Sınıf adı için Class ' ı seçin ve ObservableListSource girin
  • Varsayılan olarak oluşturulan kodu aşağıdaki kodla değiştirin:

Bu sınıf iki yönlü veri bağlamayı ve sıralamayı mümkün kılmaktadır. Sınıf, ObservableCollection T öğesinden < türetilir > ve ISource 'un açık bir uygulamasını ekler. ISource 'un GetList () yöntemi, ObservableCollection ile eşitlenmiş bir IBindingList uygulamasını döndürecek şekilde uygulanır. ToBindingList tarafından oluşturulan IBindingList uygulamasının sıralamayı destekler. ToBindingList Extension yöntemi EntityFramework derlemesinde tanımlanmıştır.

    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Diagnostics.CodeAnalysis;
    using System.Data.Entity;

    namespace WinFormswithEFSample
    {
        public class ObservableListSource<T> : ObservableCollection<T>, IListSource
            where T : class
        {
            private IBindingList _bindingList;

            bool IListSource.ContainsListCollection { get { return false; } }

            IList IListSource.GetList()
            {
                return _bindingList ?? (_bindingList = this.ToBindingList());
            }
        }
    }

Model tanımlama

bu izlenecek yolda, Code First veya EF tasarımcısını kullanarak bir model uygulamayı seçebilirsiniz. Aşağıdaki iki bölümden birini doldurun.

Seçenek 1: Code First kullanarak model tanımlama

Bu bölümde, Code First kullanarak bir modelin ve ilişkili veritabanının nasıl oluşturulacağı gösterilmektedir. Bir sonraki bölüme atlayın (seçenek 2: Database First kullanarak bir model tanımlayın) , bir VERITABANıNDAN, EF Designer kullanarak modelinize ters mühendislik uygulamak için Database First kullanmayı tercih ediyorsanız

Code First geliştirme kullanılırken, genellikle kavramsal (etki alanı) modelinizi tanımlayan .NET Framework sınıfları yazarak başlarsınız.

  • Projeye yeni bir ürün sınıfı ekleyin
  • Varsayılan olarak oluşturulan kodu aşağıdaki kodla değiştirin:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace WinFormswithEFSample
    {
        public class Product
        {
            public int ProductId { get; set; }
            public string Name { get; set; }

            public int CategoryId { get; set; }
            public virtual Category Category { get; set; }
        }
    }
  • Projeye bir Kategori sınıfı ekleyin.
  • Varsayılan olarak oluşturulan kodu aşağıdaki kodla değiştirin:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace WinFormswithEFSample
    {
        public class Category
        {
            private readonly ObservableListSource<Product> _products =
                    new ObservableListSource<Product>();

            public int CategoryId { get; set; }
            public string Name { get; set; }
            public virtual ObservableListSource<Product> Products { get { return _products; } }
        }
    }

Varlıkları tanımlamaya ek olarak, DbContext öğesinden türeten bir sınıf tanımlamanız ve dbset TEntity özelliklerini kullanıma sunabilmeniz gerekir. Dbset özellikleri bağlamın modele hangi türleri dahil etmek istediğinizi bilmesini sağlar. DbContext ve Dbset türleri EntityFramework derlemesinde tanımlanmıştır.

DbContext türetilmiş türünün bir örneği, çalışma zamanı sırasında varlık nesnelerini yönetir, bu da nesneleri bir veritabanındaki verilerle doldurmayı, değişiklik izlemeyi ve kalıcı verileri veritabanına getirmeyi içerir.

  • Projeye yeni bir Productcontext sınıfı ekleyin.
  • Varsayılan olarak oluşturulan kodu aşağıdaki kodla değiştirin:
    using System;
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Linq;
    using System.Text;

    namespace WinFormswithEFSample
    {
        public class ProductContext : DbContext
        {
            public DbSet<Category> Categories { get; set; }
            public DbSet<Product> Products { get; set; }
        }
    }

Projeyi derleyin.

Seçenek 2: Database First kullanarak model tanımlama

Bu bölümde, EF Designer kullanarak bir veritabanından modelinize ters mühendislik uygulamak için Database First nasıl kullanılacağı gösterilmektedir. önceki bölümü (1. seçenek: Code First kullanarak model tanımlama)tamamladıysanız, bu bölümü atlayın ve doğrudan geç yükleme bölümüne gidin.

Var olan bir veritabanı oluştur

Genellikle, var olan bir veritabanını hedeflerken zaten oluşturulur, ancak bu izlenecek yol için, erişmek üzere bir veritabanı oluşturulması gerekir.

Visual Studio ile yüklenen veritabanı sunucusu, yüklemiş olduğunuz Visual Studio sürümüne bağlı olarak farklılık gösteren bir sürümdür:

  • Visual Studio 2010 kullanıyorsanız SQL bir Express veritabanı oluşturursunuz.
  • Visual Studio 2012 kullanıyorsanız, localdb veritabanı oluşturursunuz.

Şimdi veritabanını oluşturalım.

  • Görünüm- Sunucu Gezgini

  • Veri bağlantıları ' na sağ tıklayın - bağlantı ekle...

  • Sunucu Gezgini bir veritabanına bağlı değilseniz, veri kaynağı olarak Microsoft SQL Server seçmeniz gerekir

    Veri kaynağını Değiştir

  • Bağlan, ne kullandığınıza bağlı olarak localdb 'ye veya SQL Express 'e ya da veritabanı adı olarak ürünleri girin

    Bağlantı LocalDB Ekle

    Bağlantı Express ekleme

  • Tamam ' ı seçtiğinizde, yeni bir veritabanı oluşturmak isteyip istemediğiniz sorulur, Evet ' i seçin.

    Veritabanı Oluşturma

  • Yeni veritabanı artık Sunucu Gezgini görüntülenir, sağ tıklayıp Yeni sorgu ' yı seçin.

  • aşağıdaki SQL yeni sorguya kopyalayın, ardından sorguya sağ tıklayıp yürüt ' ü seçin.

    CREATE TABLE [dbo].[Categories] (
        [CategoryId] [int] NOT NULL IDENTITY,
        [Name] [nvarchar](max),
        CONSTRAINT [PK_dbo.Categories] PRIMARY KEY ([CategoryId])
    )

    CREATE TABLE [dbo].[Products] (
        [ProductId] [int] NOT NULL IDENTITY,
        [Name] [nvarchar](max),
        [CategoryId] [int] NOT NULL,
        CONSTRAINT [PK_dbo.Products] PRIMARY KEY ([ProductId])
    )

    CREATE INDEX [IX_CategoryId] ON [dbo].[Products]([CategoryId])

    ALTER TABLE [dbo].[Products] ADD CONSTRAINT [FK_dbo.Products_dbo.Categories_CategoryId] FOREIGN KEY ([CategoryId]) REFERENCES [dbo].[Categories] ([CategoryId]) ON DELETE CASCADE

Tersine mühendislik modeli

modelimizi oluşturmak için Visual Studio bir parçası olarak dahil edilen Entity Framework Designer kullanacağız.

  • Project- Yeni öğe Ekle...

  • sol menüden verileri seçin ve ardından ADO.NET Varlık Veri Modeli

  • Ad olarak ProductModel girin ve Tamam 'a tıklayın

  • Bu, varlık veri modeli Sihirbazı 'nı başlatır

  • Veritabanından oluştur ' u seçin ve İleri ' ye tıklayın.

    Model Içeriğini seçin

  • İlk bölümde oluşturduğunuz veritabanına bağlantıyı seçin, bağlantı dizesinin adı olarak Productcontext girin ve İleri ' ye tıklayın.

    Bağlantınızı seçin

  • Tüm tabloları içeri aktarmak için ' tablolar ' seçeneğinin yanındaki onay kutusuna tıklayın ve ' son ' a tıklayın

    Nesnelerinizi seçin

Tersine mühendislik işlemi tamamlandıktan sonra, yeni model projenize eklenir ve Entity Framework Designer görüntülemeniz için açılır. Veritabanına yönelik bağlantı ayrıntılarına sahip bir App.config dosyası da projenize eklenmiştir.

Visual Studio 2010 ' de ek adımlar

Visual Studio 2010 ' de çalışıyorsanız, EF6 kod oluşturmayı kullanmak için EF designer ' ı güncelleştirmeniz gerekir.

  • EF Designer 'daki modelinizin boş bir noktasına sağ tıklayıp kod oluşturma öğesi Ekle... seçeneğini belirleyin.
  • Sol menüden çevrimiçi şablonlar ' ı seçin ve DbContext ' i arayın
  • C# için EF 6. x DbContext Generator ' yı seçin, ad olarak productsmodel girin ve Ekle ' ye tıklayın.

Veri bağlama için kod üretimi güncelleştiriliyor

EF, modelden T4 şablonları kullanarak kod oluşturur. Visual Studio ile gönderilen veya Visual Studio galeriden indirilen şablonlar genel amaçlı kullanım için tasarlanmıştır. Bu, bu şablonlardan oluşturulan varlıkların basit ICollection T özelliklerine sahip < olduğu anlamına > gelir. Ancak, veri bağlaması yaparken IListSource uygulayan koleksiyon özelliklerine sahip olmak tercih edilir. Bu nedenle yukarıda ObservableListSource sınıfını oluşturduk ve şimdi şablonları bu sınıftan kullanmak üzere değiştirerek değiştirerek.

  • Çözüm Gezgini ProductModel.edmx dosyasını bulun

  • ProductModel.edmx dosyasının altında iç içe ProductModel.tt dosyanın adını bulun

    Ürün Modeli Şablonu

  • ProductModel.tt dosyasına çift tıklar ve dosyayı düzenleyicide Visual Studio açın

  • "ICollection" ifadesinin iki oluşumunu bulun ve yerine "ObservableListSource" ifadesini kullanın. Bunlar yaklaşık 296 ve 484. satırlarda bulunur.

  • "HashSet" ifadesinin ilk oluşumunu bulun ve yerine "ObservableListSource "ifadesini kullanın. Bu durum yaklaşık 50. satırda bulunur. Kodda daha sonra bulunan HashSet'in ikinci oluşumunu değiştirme.

  • ProductModel.tt kaydedin. Bu, varlıkların kodunun yeniden oluşturulmasına neden olur. Kod otomatik olarak yeniden üretene kadar yeniden oluştur'a ProductModel.tt ve "Özel Aracı Çalıştır"ı seçin.

Category.cs dosyasını (ProductModel.tt altında iç içe geçmiş) açarsanız Products koleksiyonunun ObservableListSource Product türüne sahip olduğunu görüyor olun. >

Projeyi derle.

Yavaş Yükleme

Category sınıfındakiProducts özelliği ve Product sınıfındaki Categoryözelliği gezinti özellikleridir. Gezinti Entity Framework, iki varlık türü arasında bir ilişkide gezinmek için bir yol sağlar.

EF, gezinti özelliğine ilk kez erişilirken ilgili varlıkları veritabanından otomatik olarak yükleme seçeneği sağlar. Bu yükleme türüyle (yavaş yükleme olarak da adlandırılan), her gezinti özelliğine ilk kez erişen içerikler bağlam içinde yoksa veritabanına karşı ayrı bir sorgunun yürütülecek olduğunu unutmayın.

POCO varlık türlerini kullanırken EF, çalışma zamanı sırasında türetilmiş proxy türlerinin örneklerini oluşturarak ve ardından yükleme kancası eklemek için sınıflarınız sanal özelliklerini geçersiz karak yavaş yükleme yapar. İlgili nesnelerin yavaş yüklenmesini almak için, gezinti özelliği getters'larını genel ve sanal (Visual Basic'de geçersiz kılınabilir) olarak bildirebilirsiniz ve sınıf korumalı değil (NotOverridable in Visual Basic). Gezinti Database First yavaş yüklemeyi etkinleştirmek için otomatik olarak sanal yapılır. Bu Code First gezinti özelliklerini aynı nedenle sanal hale ayarlamayı seçtik

Nesneyi Denetimlere Bağlama

Modelde tanımlanan sınıfları bu WinForms uygulaması için veri kaynağı olarak ekleyin.

  • Ana menüden Project - Yeni Veri Kaynağı Ekle ... seçeneğini belirleyin (Visual Studio 2010'da Veri - Yeni Veri Kaynağı Ekle... seçeneğini seçmeniz gerekir)

  • Veri Kaynağı Türü Seçin penceresinde Nesne'yi seçin ve Ardından'yatıklayın.

  • Veri Nesnelerini Seç iletişim kutusunda WinFormswithEFSample öğesini iki kez açın ve Kategori'yi seçin. Kategori Veri kaynağını seçmenize gerek yoktur çünkü Kategori veri kaynağında Ürün'ün özelliği aracılığıyla bu veri kaynağına varacağız.

    Veri Kaynağı

  • Son'a tıklayın. Veri Kaynakları penceresi görünmüyorsa Görünüm - Diğer Windows- Veri Kaynakları'ı seçin

  • Sabitle simgesine basarak Veri Kaynakları penceresinin otomatik olarak gizlenene kadar devam edin. Pencere zaten görünür durumda ise yenile düğmesine basabilirsiniz.

    Veri Kaynağı 2

  • Bu Çözüm Gezgini Form1.cs dosyasına çift tıklar ve ana formu tasarımcıda açın.

  • Kategori veri kaynağını seçin ve forma sürükleyin. Varsayılan olarak tasarımcıya yeni bir DataGridView (categoryDataGridView) ve Gezinti araç çubuğu denetimleri eklenir. Bu denetimler, oluşturulan BindingSource (categoryBindingSource) ve Bağlama Gezgini (categoryBindingNavigator) bileşenlerine de bağlıdır.

  • categoryDataGridView sütunlarını düzenleyin. CategoryId sütununu salt okunur olarak ayarlamak istiyorum. CategoryId özelliğinin değeri, verileri kaydettikten sonra veritabanı tarafından oluşturulur.

    • DataGridView denetimine sağ tıklayın ve Sütunları Düzenle... öğesini seçin.
    • CategoryId sütununu seçin ve ReadOnly'yi True olarak ayarlayın
    • Tamam'a basın
  • Kategori veri kaynağının altından Ürünler'i seçin ve forma sürükleyin. productDataGridView ve productBindingSource forma eklenir.

  • productDataGridView'da sütunları düzenleyin. CategoryId ve Category sütunlarını gizlemek ve ProductId'i salt okunur olarak ayarlamak istiyorum. ProductId özelliğinin değeri, verileri kaydettikten sonra veritabanı tarafından oluşturulur.

    • DataGridView denetimine sağ tıklayın ve Sütunları Düzenle... öğesini seçin.
    • ProductId sütununu seçin ve ReadOnly seçeneğini True olarak ayarlayın.
    • CategoryId sütununu seçin ve Kaldır düğmesine basın. Aynı şeyi Category sütunuyla da yapma.
    • Tamam'a basın.

    Şu ana kadar DataGridView denetimlerimizi tasarımcıda BindingSource bileşenleriyle ilişkilendirildi. Bir sonraki bölümde categoryBindingSource.DataSource'un dbContext tarafından şu anda iz altında olan varlık koleksiyonuna ayarlayarak arkasındaki koda kod ekleycez. Products'i Kategori'nin altından sürükleyip bıraktığımız zaman WinForms, productsBindingSource.DataSource özelliğini categoryBindingSource ve productsBindingSource.DataMember özelliğini Products olarak ayarlamayı ele aldı. Bu bağlama nedeniyle, productDataGridView içinde yalnızca seçili olan Kategoriye ait olan ürünler görüntülenir.

  • Sağ fare düğmesine tıklar ve Etkin'i seçerek Gezinti araç çubuğunda Kaydet düğmesini etkinleştirin.

    Form 1 Tasarımcısı

  • Düğmeye çift tıklayarak kaydet düğmesinin olay işleyicisini ekleyin. Bu, olay işleyicisini ekler ve sizi form için arkandaki koda getirir. Olay işleyicisi categoryBindingNavigatorSaveItem_Click sonraki bölümde eklenecektir.

Veri Etkileşimini Ele Alan Kodu Ekleme

Şimdi veri erişimini gerçekleştirmek için ProductContext'i kullanmak üzere kodu ekleyebilirsiniz. Ana form penceresinin kodunu aşağıda gösterildiği gibi güncelleştirin.

Kod, uzun süre çalışan bir ProductContext örneği bildirer. ProductContext nesnesi, verileri sorgulamak ve veritabanına kaydetmek için kullanılır. Ardından, ProductContext örneğinde Dispose() yöntemi geçersiz kılınan OnClosing yönteminden çağrılır. Kod yorumları, kodun ne yaptığına ilişkin ayrıntıları sağlar.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Data.Entity;

    namespace WinFormswithEFSample
    {
        public partial class Form1 : Form
        {
            ProductContext _context;
            public Form1()
            {
                InitializeComponent();
            }

            protected override void OnLoad(EventArgs e)
            {
                base.OnLoad(e);
                _context = new ProductContext();

                // Call the Load method to get the data for the given DbSet
                // from the database.
                // The data is materialized as entities. The entities are managed by
                // the DbContext instance.
                _context.Categories.Load();

                // Bind the categoryBindingSource.DataSource to
                // all the Unchanged, Modified and Added Category objects that
                // are currently tracked by the DbContext.
                // Note that we need to call ToBindingList() on the
                // ObservableCollection<TEntity> returned by
                // the DbSet.Local property to get the BindingList<T>
                // in order to facilitate two-way binding in WinForms.
                this.categoryBindingSource.DataSource =
                    _context.Categories.Local.ToBindingList();
            }

            private void categoryBindingNavigatorSaveItem_Click(object sender, EventArgs e)
            {
                this.Validate();

                // Currently, the Entity Framework doesn’t mark the entities
                // that are removed from a navigation property (in our example the Products)
                // as deleted in the context.
                // The following code uses LINQ to Objects against the Local collection
                // to find all products and marks any that do not have
                // a Category reference as deleted.
                // The ToList call is required because otherwise
                // the collection will be modified
                // by the Remove call while it is being enumerated.
                // In most other situations you can do LINQ to Objects directly
                // against the Local property without using ToList first.
                foreach (var product in _context.Products.Local.ToList())
                {
                    if (product.Category == null)
                    {
                        _context.Products.Remove(product);
                    }
                }

                // Save the changes to the database.
                this._context.SaveChanges();

                // Refresh the controls to show the values         
                // that were generated by the database.
                this.categoryDataGridView.Refresh();
                this.productsDataGridView.Refresh();
            }

            protected override void OnClosing(CancelEventArgs e)
            {
                base.OnClosing(e);
                this._context.Dispose();
            }
        }
    }

Windows Forms Uygulamasını test etmek

  • Uygulamayı derle ve çalıştır; işlevi test etmek için.

    Kaydetmeden Önce Form 1

  • Depo tarafından oluşturulan anahtarlar kaydeddikten sonra ekranda gösterilir.

    Kaydetmeden Sonra Form 1

  • Bu Code First kullandıysanız, sizin için bir WinFormswithEFSample.ProductContext veritabanı da oluşturulur.

    Sunucu Nesne Gezgini