Windows Forms'a Başlarken
Bu adım adım kılavuz, SQLite veritabanı tarafından desteklenen basit bir Windows Forms (WinForms) uygulamasının nasıl derlendiğini gösterir. Uygulama, veritabanından veri yüklemek, bu verilerde yapılan değişiklikleri izlemek ve bu değişiklikleri veritabanında kalıcı hale getirmek için Entity Framework Core (EF Core) kullanır.
Bu kılavuzdaki ekran görüntüleri ve kod listeleri Visual Studio 2022 17.3.0'dan alınmıştır.
İpucu
Bu makalenin örneğini GitHub'da görüntüleyebilirsiniz.
Önkoşullar
Bu kılavuzu tamamlamak için Visual Studio 2022 17.3 veya üzerini .NET masaüstü iş yükü seçili olarak yüklemeniz gerekir. Visual Studio'nun en son sürümünü yükleme hakkında daha fazla bilgi için bkz . Visual Studio'yu Yükleme.
Uygulamayı Oluşturma
Visual Studio’yu açın
Başlangıç penceresinde Yeni proje oluştur'u seçin.
Windows Forms Uygulaması'nı ve ardından İleri'yi seçin.
Sonraki ekranda projeye getStartedWinForms gibi bir ad verin ve İleri'yi seçin.
Sonraki ekranda, kullanılacak .NET sürümünü seçin. Bu izlenecek yol .NET 7 ile oluşturulmuştur, ancak sonraki sürümlerle de çalışması gerekir.
Oluştur’u seçin.
EF Core NuGet paketlerini yükleme
Çözüme sağ tıklayın ve Çözüm için NuGet Paketlerini Yönet... seçeneğini belirleyin .
Gözat sekmesini seçin ve "Microsoft.EntityFrameworkCore.Sqlite" araması yapın.
Microsoft.EntityFrameworkCore.Sqlite paketini seçin.
Sağ bölmedeki GetStartedWinForms projesini denetleyin.
En son sürümü seçin. Yayın öncesi sürümü kullanmak için Ön sürümü dahil et kutusunun işaretli olduğundan emin olun.
Yükle'ye tıklayın
Not
Microsoft.EntityFrameworkCore.Sqlite, EF Core'u SQLite veritabanıyla kullanmaya yönelik "veritabanı sağlayıcısı" paketidir. Diğer veritabanı sistemleri için de benzer paketler mevcuttur. Veritabanı sağlayıcısı paketinin yüklenmesi, EF Core'u bu veritabanı sistemiyle kullanmak için gereken tüm bağımlılıkları otomatik olarak getirir. Bu, Microsoft.EntityFrameworkCore temel paketini içerir.
Model Tanımlama
Bu kılavuzda "Code First" kullanarak bir model uygulayacağız. Bu, EF Core'un tanımladığınız C# sınıflarını temel alan veritabanı tablolarını ve şemasını oluşturacağı anlamına gelir. Bunun yerine var olan bir veritabanının nasıl kullanılacağını görmek için bkz . Veritabanı Şemalarını Yönetme.
Projeye sağ tıklayıp Ekle'yi ve ardından Sınıf... öğesini seçerek yeni bir sınıf ekleyin.
dosya adını
Product.cs
kullanın ve sınıfın kodunu şununla değiştirin:using System.ComponentModel; namespace GetStartedWinForms; public class Product { public int ProductId { get; set; } public string? Name { get; set; } public int CategoryId { get; set; } public virtual Category Category { get; set; } = null!; }
Aşağıdaki kodla oluşturmak
Category.cs
için yineleyin:using Microsoft.EntityFrameworkCore.ChangeTracking; namespace GetStartedWinForms; public class Category { public int CategoryId { get; set; } public string? Name { get; set; } public virtual ObservableCollectionListSource<Product> Products { get; } = new(); }
Products
sınıfındaki Category
özelliği ve Category
sınıfındaki Product
özelliği "gezintiler" olarak adlandırılır. EF Core'da gezintiler iki varlık türü arasında bir ilişki tanımlar. Bu durumda gezinti, Product.Category
belirli bir ürünün ait olduğu kategoriye başvurur. Benzer şekilde, koleksiyon gezintisi Category.Products
belirli bir kategoriye ilişkin tüm ürünleri içerir.
İpucu
Windows Forms kullanılırken, ObservableCollectionListSource
uygulamasını uygulayan IListSource
, koleksiyon gezintileri için kullanılabilir. Bu gerekli değildir, ancak iki yönlü veri bağlama deneyimini geliştirir.
DbContext'i tanımlama
EF Core'da, bir modeldeki varlık türlerini yapılandırmak ve veritabanıyla etkileşime geçmek için oturum görevi görmek için öğesinden DbContext
türetilen bir sınıf kullanılır. En basit durumda, bir DbContext
sınıf:
- Modeldeki her varlık türünün özelliklerini içerir
DbSet
. - Veritabanı sağlayıcısını
OnConfiguring
yapılandırmak için yöntemini geçersiz kılar ve kullanılacak bağlantı dizesi. Daha fazla bilgi için bkz . DbContext yapılandırma.
Bu durumda, DbContext sınıfı da uygulama için bazı örnek veriler sağlamak üzere yöntemini geçersiz kılar OnModelCreating
.
Aşağıdaki kodla projeye yeni ProductsContext.cs
bir sınıf ekleyin:
using Microsoft.EntityFrameworkCore;
namespace GetStartedWinForms;
public class ProductsContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlite("Data Source=products.db");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Category>().HasData(
new Category { CategoryId = 1, Name = "Cheese" },
new Category { CategoryId = 2, Name = "Meat" },
new Category { CategoryId = 3, Name = "Fish" },
new Category { CategoryId = 4, Name = "Bread" });
modelBuilder.Entity<Product>().HasData(
new Product { ProductId = 1, CategoryId = 1, Name = "Cheddar" },
new Product { ProductId = 2, CategoryId = 1, Name = "Brie" },
new Product { ProductId = 3, CategoryId = 1, Name = "Stilton" },
new Product { ProductId = 4, CategoryId = 1, Name = "Cheshire" },
new Product { ProductId = 5, CategoryId = 1, Name = "Swiss" },
new Product { ProductId = 6, CategoryId = 1, Name = "Gruyere" },
new Product { ProductId = 7, CategoryId = 1, Name = "Colby" },
new Product { ProductId = 8, CategoryId = 1, Name = "Mozzela" },
new Product { ProductId = 9, CategoryId = 1, Name = "Ricotta" },
new Product { ProductId = 10, CategoryId = 1, Name = "Parmesan" },
new Product { ProductId = 11, CategoryId = 2, Name = "Ham" },
new Product { ProductId = 12, CategoryId = 2, Name = "Beef" },
new Product { ProductId = 13, CategoryId = 2, Name = "Chicken" },
new Product { ProductId = 14, CategoryId = 2, Name = "Turkey" },
new Product { ProductId = 15, CategoryId = 2, Name = "Prosciutto" },
new Product { ProductId = 16, CategoryId = 2, Name = "Bacon" },
new Product { ProductId = 17, CategoryId = 2, Name = "Mutton" },
new Product { ProductId = 18, CategoryId = 2, Name = "Pastrami" },
new Product { ProductId = 19, CategoryId = 2, Name = "Hazlet" },
new Product { ProductId = 20, CategoryId = 2, Name = "Salami" },
new Product { ProductId = 21, CategoryId = 3, Name = "Salmon" },
new Product { ProductId = 22, CategoryId = 3, Name = "Tuna" },
new Product { ProductId = 23, CategoryId = 3, Name = "Mackerel" },
new Product { ProductId = 24, CategoryId = 4, Name = "Rye" },
new Product { ProductId = 25, CategoryId = 4, Name = "Wheat" },
new Product { ProductId = 26, CategoryId = 4, Name = "Brioche" },
new Product { ProductId = 27, CategoryId = 4, Name = "Naan" },
new Product { ProductId = 28, CategoryId = 4, Name = "Focaccia" },
new Product { ProductId = 29, CategoryId = 4, Name = "Malted" },
new Product { ProductId = 30, CategoryId = 4, Name = "Sourdough" },
new Product { ProductId = 31, CategoryId = 4, Name = "Corn" },
new Product { ProductId = 32, CategoryId = 4, Name = "White" },
new Product { ProductId = 33, CategoryId = 4, Name = "Soda" });
}
}
Bu noktada çözümü derlediğinden emin olun.
Forma denetim ekleme
Uygulama, kategorilerin ve ürünlerin listesini gösterir. İlk listede bir kategori seçildiğinde, ikinci liste bu kategoriye ilişkin ürünleri gösterecek şekilde değişir. Bu listeler ürün ve kategori eklemek, kaldırmak veya düzenlemek için değiştirilebilir ve bu değişiklikler Bir Kaydet düğmesine tıklanarak SQLite veritabanına kaydedilebilir.
Ana formun
Form1
MainForm
adını olarak değiştirin.Başlığı da "Ürünler ve Kategoriler" olarak değiştirin.
Araç Kutusu'nu kullanarak yan yana yerleştirilmiş iki
DataGridView
denetim ekleyin.İlk
DataGridView
öğesinin Özellikler bölümünde Ad değerini olarakdataGridViewCategories
değiştirin.İkincinin
DataGridView
Özellikler bölümünde Ad değerini olarakdataGridViewProducts
değiştirin.Ayrıca Araç Kutusu'nu kullanarak bir
Button
denetim ekleyin.Düğmeyi
buttonSave
adlandırın ve "Kaydet" metnini verin. Form şu şekilde görünmelidir:
Veri bağlama
Sonraki adım, modeldeki Product
ve Category
türlerini denetimlere bağlamaktır DataGridView
. Bu, EF Core tarafından yüklenen verileri denetimlere bağlar; böylece EF Core tarafından izlenen varlıklar denetimlerde görüntülenenlerle eşitlenmiş olarak tutulur.
İlk üzerinde Tasarımcı Eylem Karakteri'ne
DataGridView
tıklayın. Bu, denetimin sağ üst köşesindeki küçük düğmedir.Bu işlem, Seçilen Veri Kaynağı için açılan listenin erişilebildiği Eylem Listesi'ni açar. Henüz bir veri kaynağı oluşturmadık, bu nedenle en alta gidin ve Yeni Nesne Veri Kaynağı Ekle... öğesini seçin.
Kategoriler için nesne veri kaynağı oluşturmak üzere Kategori'yi seçin ve Tamam'a tıklayın.
İpucu
Burada veri kaynağı türü görünmüyorsa, projeye eklendiğinden
Category.cs
Product.cs
veProductsContext.cs
çözümün oluşturulduğundan emin olun.Şimdi Veri Kaynağı Seç açılan listesinde yeni oluşturduğumuz nesne veri kaynağı yer alır. Diğer Veri Kaynakları'nı genişletin, ardından Proje Veri Kaynakları'nı genişletin ve Kategori'yi seçin.
İkincisi
DataGridView
ürünlere bağlı olacaktır. Ancak, en üst düzeyProduct
türe bağlamak yerine, bunun yerine ilkDataGridView
bağlamasındanCategory
gezintiyeProducts
bağlanır. Bu, birinci görünümde bir kategori seçildiğinde, söz konusu kategoriye ilişkin ürünlerin ikinci görünümde otomatik olarak kullanılacağı anlamına gelir.İkincisinde
DataGridView
Tasarımcı Eylem Karakteri'ni kullanarak Veri Kaynağı Seç'i seçin, ardından öğesini genişletipcategoryBindingSource
öğesini seçinProducts
.
Görüntülenenleri yapılandırma
Varsayılan olarak, bağlı türlerin DataGridView
her özelliği için içinde bir sütun oluşturulur. Ayrıca, bu özelliklerin her birinin değerleri kullanıcı tarafından düzenlenebilir. Ancak, birincil anahtar değerleri gibi bazı değerler kavramsal olarak salt okunur olduğundan düzenlenmemelidir. Ayrıca, yabancı anahtar özelliği ve Category
gezinti gibi CategoryId
bazı özellikler kullanıcı için yararlı değildir ve bu nedenle gizlenmelidir.
İpucu
Gerçek bir uygulamada birincil anahtar özelliklerini gizlemek yaygın bir durumdur. EF Core'un arka planda neler yaptığını görmelerini kolaylaştırmak için burada görünür durumda kalırlar.
İlke
DataGridView
sağ tıklayın ve Sütunları Düzenle...'yi seçin.CategoryId
Birincil anahtarı temsil eden sütunu salt okunur yapın ve Tamam'a tıklayın.İkinciye
DataGridView
sağ tıklayın ve Sütunları Düzenle...'yi seçin.ProductId
Sütunu salt okunur yapın ve veCategory
sütunlarınıCategoryId
kaldırın, ardından Tamam'a tıklayın.
EF Core'a bağlanma
Uygulamanın artık EF Core'u veriye bağlı denetimlere bağlamak için az miktarda koda ihtiyacı vardır.
Dosyaya
MainForm
sağ tıklayıp Kodu Görüntüle'yi seçerek kodu açın.Oturum için öğesini tutmak
DbContext
için özel bir alan ekleyin ve veOnClosing
yöntemleri içinOnLoad
geçersiz kılmalar ekleyin. Kod şu şekilde görünmelidir:
using Microsoft.EntityFrameworkCore;
using System.ComponentModel;
namespace GetStartedWinForms
{
public partial class MainForm : Form
{
private ProductsContext? dbContext;
public MainForm()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.dbContext = new ProductsContext();
// Uncomment the line below to start fresh with a new database.
// this.dbContext.Database.EnsureDeleted();
this.dbContext.Database.EnsureCreated();
this.dbContext.Categories.Load();
this.categoryBindingSource.DataSource = dbContext.Categories.Local.ToBindingList();
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
this.dbContext?.Dispose();
this.dbContext = null;
}
}
}
OnLoad
Form yüklendiğinde yöntemi çağrılır. Şu anda
- Uygulamasının
ProductsContext
görüntülediği ürün ve kategorilerdeki değişiklikleri yüklemek ve izlemek için kullanılacak bir örneği oluşturulur. EnsureCreated
, henüz yoksa SQLite veritabanını oluşturmak için üzerinde çağrılırDbContext
. Bu, uygulamaları prototip oluştururken veya test ederken veritabanı oluşturmanın hızlı bir yoludur. Ancak model değişirse veritabanının yeniden oluşturulabilmesi için silinmesi gerekir. (UygulamaEnsureDeleted
çalıştırıldığında veritabanını kolayca silmek ve yeniden oluşturmak için satırın açıklaması kaldırılabilir.) Bunun yerine, veri kaybetmeden veritabanı şemasını değiştirmek ve güncelleştirmek için EF Core Migrations kullanmak isteyebilirsiniz.EnsureCreated
, yeni veritabanını yöntemindeProductsContext.OnModelCreating
tanımlanan verilerle de doldurur.Load
uzantı yöntemi, veritabanındaki tüm kategorileri içineDbContext
yüklemek için kullanılır. Bu varlıklar artık tarafından izlenecekDbContext
ve kategoriler kullanıcı tarafından düzenlendiğinde yapılan değişiklikleri algılayacak.categoryBindingSource.DataSource
özelliği tarafındanDbContext
izlenen kategorilere başlatılır. Bu, özelliğindeCategories
DbSet
çağrıLocal.ToBindingList()
yapılarak gerçekleştirilir.Local
izlenen kategorilerin yerel görünümüne erişim sağlar ve yerel verilerin görüntülenen verilerle eşitlenmiş durumda kalmasını sağlamak için olaylar bağlanmış durumdadır ve tam tersi de geçerlidir.ToBindingList()
bu verileri, Windows Forms veri bağlaması tarafından anlaşılan birIBindingList
olarak kullanıma sunar.
OnClosing
Form kapatıldığında yöntemi çağrılır. Şu anda, tüm veritabanı kaynaklarının DbContext
serbest bırakılmasını sağlayan atılır ve alan null olarak ayarlanır, dbContext
böylece yeniden kullanılamaz.
Ürünler görünümünü doldurma
Uygulama bu noktada başlatılırsa şuna benzer olmalıdır:
Kategorilerin veritabanından yüklendiğine, ancak ürünler tablosunun boş kaldığına dikkat edin. Ayrıca Kaydet düğmesi çalışmaz.
Ürünler tablosunu doldurmak için EF Core'un seçilen kategori için veritabanından ürün yüklemesi gerekir. Bunu başarmak için:
Ana formun tasarımcısında kategoriler için öğesini
DataGridView
seçin.için Özellikler
DataGridView
bölümünde olayları seçin (şimşek düğmesi) ve SelectionChanged olayına çift tıklayın.Bu, kategori seçimi her değiştiğinde tetiklenecek bir olay için ana form kodunda saplama oluşturur.
Olayın kodunu doldurun:
private void dataGridViewCategories_SelectionChanged(object sender, EventArgs e)
{
if (this.dbContext != null)
{
var category = (Category)this.dataGridViewCategories.CurrentRow.DataBoundItem;
if (category != null)
{
this.dbContext.Entry(category).Collection(e => e.Products).Load();
}
}
}
Bu kodda etkin (null olmayan) DbContext
bir oturum varsa, öğesinin seçili durumdaki Category
satırına DataViewGrid
bağlı örneği elde ederiz. (Bu, görünümdeki son satırın seçili olması ve yeni kategoriler oluşturmak için kullanılması olabilir null
.) Seçili bir kategori varsa, DbContext
bu kategoriyle ilişkili ürünleri yüklemesi istenir. Bu işlem şu şekilde yapılır:
- Örnek için
Category
almaEntityEntry
(dbContext.Entry(category)
) - EF Core'a bunun koleksiyon gezintisinde
Products
çalışmak istediğimiziCategory
bildirmek (.Collection(e => e.Products)
) - Ve son olarak EF Core'a bu ürün koleksiyonunu veritabanından yüklemek istediğimizi söylemek (
.Load();
)
İpucu
Çağrıldığında Load
, EF Core yalnızca henüz yüklenmemiş olan ürünleri yüklemek için veritabanına erişir.
Uygulama şimdi yeniden çalıştırılırsa, bir kategori seçildiğinde uygun ürünleri yüklemelidir:
Değişiklikler kaydediliyor
Son olarak, ürünlerde ve kategorilerde yapılan tüm değişikliklerin veritabanına kaydedilmesi için Kaydet düğmesi EF Core'a bağlanabilir.
Ana formun tasarımcısında Kaydet düğmesini seçin.
için Özellikler
Button
bölümünde olayları (şimşek düğmesi) seçin ve Tıklama olayına çift tıklayın.Olayın kodunu doldurun:
private void buttonSave_Click(object sender, EventArgs e)
{
this.dbContext!.SaveChanges();
this.dataGridViewCategories.Refresh();
this.dataGridViewProducts.Refresh();
}
Bu kod, SQLite veritabanında yapılan değişiklikleri kaydeden üzerinde DbContext
öğesini çağırırSaveChanges
. Hiçbir değişiklik yapılmadıysa, bu işlem yapılmaz ve veritabanı çağrısı yapılmaz. Kaydettikten sonra denetimler DataGridView
yenilenir. Bunun nedeni EF Core'un veritabanındaki tüm yeni ürünler ve kategoriler için oluşturulan birincil anahtar değerlerini okumasıdır. Çağrılması Refresh
, görüntüyü bu oluşturulan değerlerle güncelleştirir.
Son uygulama
Ana formun tam kodu aşağıdadır:
using Microsoft.EntityFrameworkCore;
using System.ComponentModel;
namespace GetStartedWinForms
{
public partial class MainForm : Form
{
private ProductsContext? dbContext;
public MainForm()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.dbContext = new ProductsContext();
// Uncomment the line below to start fresh with a new database.
// this.dbContext.Database.EnsureDeleted();
this.dbContext.Database.EnsureCreated();
this.dbContext.Categories.Load();
this.categoryBindingSource.DataSource = dbContext.Categories.Local.ToBindingList();
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
this.dbContext?.Dispose();
this.dbContext = null;
}
private void dataGridViewCategories_SelectionChanged(object sender, EventArgs e)
{
if (this.dbContext != null)
{
var category = (Category)this.dataGridViewCategories.CurrentRow.DataBoundItem;
if (category != null)
{
this.dbContext.Entry(category).Collection(e => e.Products).Load();
}
}
}
private void buttonSave_Click(object sender, EventArgs e)
{
this.dbContext!.SaveChanges();
this.dataGridViewCategories.Refresh();
this.dataGridViewProducts.Refresh();
}
}
}
Uygulama artık çalıştırılabilir ve ürünler ve kategoriler eklenebilir, silinebilir ve düzenlenebilir. Uygulamayı kapatmadan önce Kaydet düğmesine tıklanırsa, yapılan tüm değişikliklerin veritabanında depolanacağına ve uygulama yeniden başlatıldığında yeniden yüklendiğine dikkat edin. Kaydet'e tıklanmazsa, uygulama yeniden başlatıldığında tüm değişiklikler kaybolur.
İpucu
Denetimin en altındaki boş satır kullanılarak yeni bir DataViewControl
kategori veya ürün eklenebilir. Satır seçilerek ve Del tuşuna basılarak silinebilir.
Kaydetmeden önce
Kaydettikten sonra
Kaydet'e tıklandığında, eklenen kategori ve ürünler için birincil anahtar değerlerinin doldurulduğunu fark edin.