Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tento podrobný návod ukazuje, jak vytvořit jednoduchou aplikaci Windows Forms (WinForms) s podporou databáze SQLite. Aplikace používá Entity Framework Core (EF Core) k načtení dat z databáze, sledování změn provedených v těchto datech a zachování těchto změn zpět do databáze.
Snímky obrazovky a výpisy kódu v tomto návodu pocházejí ze sady Visual Studio 2022 17.3.0.
Návod
Ukázku pro tento článek najdete na GitHubu.
Požadavky
K dokončení tohoto návodu musíte mít nainstalovanou sadu Visual Studio 2022 17.3 nebo novější s vybraným .NET desktopovým pracovním vytížením. Další informace o instalaci nejnovější verze sady Visual Studio naleznete v tématu Instalace sady Visual Studio.
Vytvoření aplikace
Otevřete Visual Studio.
V úvodním okně zvolte Vytvořit nový projekt.
Zvolte Windows Forms aplikaci a poté vyberte Další.
Na další obrazovce zadejte název projektu, například GetStartedWinForms, a zvolte Další.
Na další obrazovce zvolte verzi .NET, která se má použít. Tento názorný postup byl vytvořen s .NET 7, ale měl by také fungovat s novějšími verzemi.
Zvolte Vytvořit.
Nainstalujte balíčky NuGet EF Core
Klikněte pravým tlačítkem na řešení a zvolte Spravovat balíčky NuGet pro řešení...
Zvolte kartu Procházet a vyhledejte Microsoft.EntityFrameworkCore.Sqlite.
Vyberte balíček Microsoft.EntityFrameworkCore.Sqlite.
Zkontrolujte projekt GetStartedWinForms v pravém podokně.
Zvolte nejnovější verzi. Pokud chcete použít předběžnou verzi, ujistěte se, že je zaškrtnuté políčko Zahrnout předběžné verze .
Klikněte na Nainstalovat.
Poznámka:
Microsoft.EntityFrameworkCore.Sqlite je balíček "poskytovatel databáze" pro použití EF Core s databází SQLite. Podobné balíčky jsou k dispozici pro jiné databázové systémy. Při instalaci balíčku zprostředkovatele databáze se automaticky zobrazí všechny závislosti potřebné k použití EF Core s tímto databázovým systémem. To zahrnuje základní balíček Microsoft.EntityFrameworkCore .
Definování modelu
V tomto názorném postupu implementujeme model pomocí kódu First. To znamená, že EF Core vytvoří databázové tabulky a schéma založené na definovaných třídách jazyka C#. Informace o tom, jak místo toho použít existující databázi, najdete v tématu Správa schémat databáze.
Klikněte pravým tlačítkem myši na projekt a zvolte Přidat, potom Třídu... a přidejte novou třídu.
Použijte název souboru
Product.csa nahraďte kód třídy takto: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!; }Opakujte vytvoření
Category.css následujícím kódem: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(); }
Vlastnost Products třídy Category a Category vlastnosti třídy Product se nazývají "navigace". Navigace v EF Core definují vztah mezi dvěma typy entit. V tomto případě navigace odkazuje na kategorii, Product.Category do které daný produkt patří.
Category.Products Podobně navigace v kolekci obsahuje všechny produkty pro danou kategorii.
Návod
Při použití Windows Forms lze ObservableCollectionListSource, který implementuje IListSource, použít pro navigaci v kolekci. To není nutné, ale vylepšuje prostředí obousměrných datových vazeb.
Definování DbContext
V EF Core se třída odvozená z DbContext používá ke konfiguraci typů entit v modelu a funguje jako session pro interakci s databází. V nejjednodušším případě je třída DbContext.
- Obsahuje
DbSetvlastnosti pro každý typ entity v modelu. - Přepíše metodu
OnConfiguring, aby nakonfigurovala zprostředkovatele databáze a připojovací řetězec, který se má použít. Další informace najdete v tématu Konfigurace DbContext .
V tomto případě dbContext třída také přepíše metodu OnModelCreating , aby poskytovala ukázková data pro aplikaci.
Přidejte do projektu novou ProductsContext.cs třídu s následujícím kódem:
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" });
}
}
Ujistěte se, že v tuto chvíli sestavíte řešení.
Přidání ovládacích prvků do formuláře
Aplikace zobrazí seznam kategorií a seznam produktů. Když je v prvním seznamu vybraná kategorie, změní se druhý seznam tak, aby zobrazoval produkty pro danou kategorii. Tyto seznamy lze upravit tak, aby přidávaly, odebíraly nebo upravovaly produkty a kategorie a tyto změny lze uložit do databáze SQLite kliknutím na tlačítko Uložit .
Změňte název hlavního formuláře z
Form1naMainForm.
A změňte název na Produkty a kategorie.
Pomocí panelu nástrojů přidejte dva
DataGridViewovládací prvky uspořádané vedle sebe.
Ve vlastnostech prvního
DataGridViewzměňte název nadataGridViewCategories.Ve Vlastnostech pro druhý
DataGridViewzměňte Název nadataGridViewProducts.Pomocí panelu nástrojů přidejte
Buttontaké ovládací prvek.Pojmenujte tlačítko
buttonSavea dejte mu text "Uložit". Formulář by měl vypadat nějak takto:
Datová vazba
Dalším krokem je připojení Product a Category typů z modelu k ovládacím prvkům DataGridView . Tím se sváže data načtená ef Core s ovládacími prvky, aby entity sledované EF Core byly synchronizované s těmi, které se zobrazují v ovládacích prvcích.
Klikněte na Glyph akce návrháře na první
DataGridView. Toto je malé tlačítko v pravém horním rohu ovládacího prvku.
Tímto se otevře Seznam akcí, odkud lze přistoupit k rozevíracímu seznamu Pro výběr zdroje dat. Ještě jsme nevytvořili zdroj dat, takže přejděte do dolní části a zvolte Přidat nový zdroj dat objektu....
Zvolte Kategorie , chcete-li vytvořit zdroj dat objektu pro kategorie, a klepněte na tlačítko OK.
Návod
Pokud se zde nezobrazují žádné typy zdrojů dat, ujistěte se, že
Product.cs,Category.csaProductsContext.csbyly přidány do projektu a že řešení bylo sestaveno.Teď rozevírací seznam Zvolit zdroj dat obsahuje právě vytvořený zdroj dat objektu. Rozbalte další zdroje dat, pak zdroje dat projektu a zvolte Kategorie.
Druhá
DataGridViewbude vázána na produkty. Místo toho, aby byla vázána naProductjako typ nejvyšší úrovně, bude připojena kProductsnavigaci zCategoryvazby prvníhoDataGridView. To znamená, že když je kategorie vybrána v prvním zobrazení, produkty pro tuto kategorii se automaticky použijí ve druhém zobrazení.Pomocí ikony akce návrháře Glyph na druhé
DataGridView, zvolte Zvolit Zdroj dat, pak rozbaltecategoryBindingSourcea zvolteProducts.
Konfigurace zobrazení obsahu
Ve výchozím nastavení je v DataGridView vytvořen sloupec pro každou vlastnost vázaných typů. Také hodnoty pro každou z těchto vlastností může uživatel upravit. Některé hodnoty, například hodnoty primárního klíče, jsou ale koncepčně jen pro čtení a proto by se neměly upravovat. Některé vlastnosti, například vlastnost cizího CategoryId klíče a Category navigace, nejsou užitečné pro uživatele, a proto by měly být skryté.
Návod
Vlastnosti primárního klíče je běžné skrýt v reálné aplikaci. Jsou zde viditelné, aby bylo možné snadno zjistit, co EF Core dělá na pozadí.
Klikněte pravým tlačítkem myši na první
DataGridViewa zvolte Upravit sloupce....
Nastavte
CategoryIdsloupec, který představuje primární klíč, jen pro čtení a klikněte na tlačítko OK.
Klikněte pravým tlačítkem myši na druhý
DataGridViewa zvolte Upravit sloupce.... Nastavte sloupecProductIdjako jen pro čtení a odeberte sloupceCategoryIdaCategory, pak klikněte na OK.
Připojení k EF Core
Aplikace teď potřebuje k připojení EF Core k ovládacím prvkům vázaným na data malé množství kódu.
MainFormOtevřete kód tak, že kliknete pravým tlačítkem myši na soubor a zvolíte Zobrazit kód.
Přidejte soukromé pole, které bude držet
DbContextpro relaci, a přidejte přepsání pro metodyOnLoadaOnClosing. Kód by měl vypadat takto:
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;
}
}
}
Metoda OnLoad je volána při načtení formuláře. V tuto chvíli
- Vytvoří se instance
ProductsContext, která se použije k načtení a sledování změn produktů a kategorií zobrazených aplikací. -
EnsureCreatedje volána naDbContextk vytvoření databáze SQLite, pokud ještě neexistuje. Jedná se o rychlý způsob, jak vytvořit databázi při vytváření prototypů nebo testování aplikací. Pokud se ale model změní, bude potřeba databázi odstranit, aby ji bylo možné vytvořit znovu. (ŘádekEnsureDeletedlze odkomentovat pro snadné odstranění a opětovné vytvoření databáze při spuštění aplikace.) Mohli byste místo toho chtít použít Migrace EF Core k úpravě a aktualizaci schématu databáze bez ztráty dat. -
EnsureCreatednaplní také novou databázi daty definovanými vProductsContext.OnModelCreatingmetodě. - Metoda
Loadrozšíření se používá k načtení všech kategorií z databáze doDbContext. Tyto entity budou nyní sledovány uživatelemDbContext, což rozpozná všechny změny provedené při úpravách kategorií uživatelem. - Vlastnost
categoryBindingSource.DataSourceje inicializována na kategorie, které sledujeDbContext. To se provádí voláním vlastnostiCategoriesDbSetnaLocal.ToBindingList().Localposkytuje přístup k místnímu zobrazení sledovaných kategorií, přičemž události jsou připojeny, aby se zajistila synchronizace místních dat se zobrazenými daty a naopak.ToBindingList()zveřejňuje tato data jakoIBindingList, která je kompatibilní s datovou vazbou Windows Forms.
Metoda OnClosing je volána při zavření formuláře. V tomto okamžiku je DbContext uvolněno, což zajišťuje, že všechny prostředky databáze budou uvolněny, a pole dbContext je nastaveno na hodnotu null, aby nemohlo být znovu použito.
Doplnění zobrazení produktů
Pokud je aplikace v tomto okamžiku spuštěná, měla by vypadat přibližně takto:
Všimněte si, že kategorie byly načteny z databáze, ale tabulka produktů zůstává prázdná. Tlačítko Uložit také nefunguje.
Pokud chcete naplnit tabulku produktů, ef Core musí načíst produkty z databáze pro vybranou kategorii. Chcete-li toho dosáhnout:
V návrháři hlavního formuláře vyberte
DataGridViewkategorií.V části Vlastnosti pro
DataGridViewvyberte události (tlačítko blesku) a dvojitým kliknutím otevřete událost SelectionChanged.
Tím se v kódu hlavního formuláře vytvoří zástupný prvek pro aktivaci události, kdykoli dojde ke změně výběru kategorie.
Vyplňte kód události:
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();
}
}
}
Pokud je v tomto kódu aktivní (nenulová) relace DbContext, pak získáme instanci vázanou k aktuálně vybranému řádku v DataViewGridCategory. (To může být null , pokud je vybrán poslední řádek v zobrazení, který slouží k vytvoření nových kategorií.) Pokud je vybraná kategorie, DbContext zobrazí se pokyn k načtení produktů přidružených k této kategorii. K tomu slouží:
-
EntityEntryZískáníCategoryinstance (dbContext.Entry(category)) - Dáme EF Core vědět, že chceme pracovat na kolekční navigaci tohoto
Category(.Collection(e => e.Products)) - A nakonec ef Core říkáme, že chceme načíst kolekci produktů z databáze (
.Load();)
Návod
Když je volána funkce Load, EF Core přistoupí k databázi, aby načetl produkty, pouze pokud ještě nebyly načteny.
Pokud je aplikace spuštěná znovu, měla by se načíst příslušné produkty vždy, když je vybrána kategorie:
Ukládání změn
Nakonec můžete tlačítko Uložit připojit k EF Core, aby se všechny změny provedené v produktech a kategoriích uložily do databáze.
V návrháři hlavního formuláře vyberte tlačítko Uložit .
Ve vlastnostech pro
Button, zvolte události (tlačítko s bleskem) a dvojitě klikněte na událost Click.
Vyplňte kód události:
private void buttonSave_Click(object sender, EventArgs e)
{
this.dbContext!.SaveChanges();
this.dataGridViewCategories.Refresh();
this.dataGridViewProducts.Refresh();
}
Tento kód volá SaveChanges na DbContext, což provede uložení všech změn v databázi SQLite. Pokud nebyly provedeny žádné změny, jedná se o operace typu no-op a nedojde k žádnému volání databáze. Po uložení se ovládací prvky DataGridView aktualizují. Důvodem je to, že EF Core čte hodnoty primárního klíče pro všechny nové produkty a kategorie z databáze. Volání Refresh aktualizuje zobrazení těmito vygenerovanými hodnotami.
Konečná aplikace
Tady je úplný kód hlavního formuláře:
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();
}
}
}
Aplikace se teď dá spustit a produkty a kategorie se dají přidávat, odstraňovat a upravovat. Všimněte si, že pokud tlačítko Uložit kliknete před zavřením aplikace, všechny provedené změny budou uloženy v databázi a znovu načteny při opětovném spuštění aplikace. Pokud na tlačítko Uložit není kliknuto, při opětovném spuštění aplikace dojde ke ztrátě změn.
Návod
Do DataViewControl lze novou kategorii nebo produkt přidat pomocí prázdného řádku ve spodní části ovládacího prvku. Řádek můžete odstranit tak, že ho vyberete a stisknete klávesu Del .
Před uložením
Po uložení
Všimněte si, že hodnoty primárního klíče pro přidanou kategorii a produkty se vyplní po kliknutí na tlačítko Uložit .