Fakturační systém v C# .NET - LocalDB a Entity Framework

C# .NET Databáze Fakturační systém v C# .NET - LocalDB a Entity Framework

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V tomto tutoriálu se naučíme vytvářet lokální databázi pro desktopovou aplikaci a její namapování na objekty pomocí Entity Frameworku. Půjde o jednoduché účetnictví. Je požadována alespoň základní znalost databází, SQL a práce s kolekcemi.

SQL CE

Do vydání Visual Studia 2013 se pro malé databáze desktopových programů používal SQL Server Compact Edition - jednoduchá verze SQL serveru tvořená pouze DLL soubory. Nepodporuje pohledy, uložené procedury, triggery a další. To nám u malé DB pro jednoduché ukládaní dat většinou stačí. Instalační soubor SQL CE má pouze kolem 2MB.

LocalDB

Od VS2013 nejde standardně vytvořit .sdf databáze pro SQL CE. Už se s CE nepočítá, i když to jde obejít pluginy. Proto si ukážeme, jak vytvořit lokální databázi LocalDB. Ta je už plnohodnotná (jako SQL server Express) a pro její spuštění na běžném PC (bez VS a SQL severu) musíme nainstalovat +- 30MB instalační soubor. Viz. tady(ENG).

Vytvoření databáze

Vytvoříme si nový konzolový projekt. Pro přidání databázového souboru máme pouze jednu možnost - soubor mdf.

Přidání databázového souboru v C# .NET

Nastavíme property databáze, aby se nám databáze přepsala pouze při změně její struktury a ne dat.

Vlastnosti databáze v C# .NET

Tvorba tabulek pro fakturační systém

Mějme tabulku faktura, která má dva cizí klíče na tabulku osoba. Ta reprezentuje dodavatele nebo odběratele.

Vytvoříme novou tabulku přes Server Explorer.

Vytvoření nové databázové tabulky

Tabulky můžeme naklikat nebo přímo napsat v SQL .

Tvorba databázových tabulek ve Visual Studio

Samotné SQL

CREATE TABLE [dbo].[Person]
(
    [Id] INT NOT NULL PRIMARY KEY IDENTITY,
    [Name] NVARCHAR(100) NULL,
    [Surname] NVARCHAR(100) NOT NULL,
    [ICO] INT NULL,
    [DIC] NVARCHAR(20) NULL,
    [Street] NVARCHAR(100) NOT NULL,
    [City] NVARCHAR(100) NOT NULL,
    [PSC] INT NOT NULL,
    [Email] NVARCHAR(50) NOT NULL,
    [IsDeleted] TINYINT NOT NULL DEFAULT 0
)

CREATE TABLE [dbo].[Invoice]
(
    [Id] INT NOT NULL PRIMARY KEY IDENTITY,
    [Supplier] INT NOT NULL,
    [Customer] INT NOT NULL,
    [Price] INT NOT NULL,
    [Service] NVARCHAR(200) NOT NULL,
    [Date] DATETIME NOT NULL,
    [InvoiceNumber] INT NOT NULL,
    [IsDeleted] TINYINT NOT NULL DEFAULT 0,
    CONSTRAINT [FK_Supplier] FOREIGN KEY ([Supplier]) REFERENCES [Person]([Id]),
    CONSTRAINT [FK_Customer] FOREIGN KEY ([Customer]) REFERENCES  [Person]([Id])
)

Parametr IDENTITY přidá autoinkrement primárního klíče. DEFAULT 0 nastaví defaultní hodnotu na 0. Propojení cizího klíče s primárním by vám mělo být jasné.

Entity Framework

Databázi máme hotovou. Nyní potřebujeme přistupovat k DB objektově.

Do projektu přidáme nový item ADO.NET Entity Data Model. Automaticky nám vygeneruje třídy a jejich vztahy podle DB. Je tu ještě možnost - vybrat EF DbContext Generator, ale tím se zde nebudeme zabývat (podle napsaných tříd přistupuje k DB nebo DB může i vygenerovat).

Entity Framework v C# .NET

Vybereme generování z databáze.

Entity Framework v C# .NET

Vybereme naši databázi

Entity Framework v C# .NET

Vybereme tabulky do kterých chceme přistupovat, zaškrtneme generování množných čísel u názvů objektů a klikneme na finish.

Entity Framework v C# .NET

Zobrazí se diagram naší databáze. Přejmenujeme si názvy referencí (Person1, Invoices1) ať se v tom pak vyznáme.

Entity Framework v C# .NET

Používání Entity Frameworku

Použití EF je velice jednoduché. Vytvoříme si instanci třídy DbInvoiceEntities. Ta obsahuje kolekce záznamů jednotlivých tabulek. Kolekce můžeme filtrovat, prohledávat atd. viz. zdejší tutoriály.

Přidání nového záznamu.

DbInvoiceEntities db = new DbInvoiceEntities();

Person newPerson = new Person();
newPerson.Name = "Jméno";
newPerson.Surname = "Příjmení";
newPerson.Street = "Ulice";
newPerson.City = "Město";
newPerson.PSC = 73601;
newPerson.ICO = 78321456;
newPerson.DIC = "CZ78321456";
newPerson.Email = "[email protected]";

db.Persons.Add(newPerson);
db.SaveChanges();

Pokud objektu newPerson nenastavíme nějakou not null property, při spuštění se zobrazí výjimka.

Entity Framework v C# .NET

Jednoduchý výpis v konzoli s hledáním.

Console.WriteLine("Persons: ");
foreach (Person p in db.Persons)
{
    Console.WriteLine(p.Surname + " " + p.Name + ", city: " + p.City);
}
Console.WriteLine(Environment.NewLine);

Console.WriteLine("Invoices: ");
foreach (Invoice i in db.Invoices)
{
    Console.WriteLine("Price: " + i.Price + ", date: " + i.Date);
}
Console.WriteLine(Environment.NewLine + "Search Pepa: ");

Person foundPerson = db.Persons.FirstOrDefault(p => p.Name.Contains("pepa"));
Console.WriteLine(foundPerson.Surname + " " + foundPerson.Name + ", city: " + foundPerson.City);

Závěrem

V tomto tutoriálu jsme si ukázali, jak se v C# .NET vytváří a pracuje s lokální databází. Vytvořili jsme databázi a ORM pro jednoduchý fakturační systém. V dalším tutoriálu přidáme grafické rozhraní skrze Windows Presentation Foundation.

Pokuď vám něco nefunguje nebo něčemu nerozumíte, napište do diskuze, ať to můžu v článku případně poupravit.


 

Stáhnout

Staženo 906x (10.45 MB)

 

 

Článek pro vás napsal Petr Domes (petrds)
Avatar
Jak se ti líbí článek?
12 hlasů
Programuji v .NET. Ovládám C#, .ASP, WF, WPF, SQL
Aktivity (2)

 

 

Komentáře
Zobrazit starší komentáře (48)

Avatar
slezak-petr
Člen
Avatar
slezak-petr:29.10.2017 10:46

Ahoj potřeboval bych poradit s Exception, nějak nevidím chybu, zdroj chyby je tady, to je OK:

1/

try {
    db.Activities.Add(ac);
    db.SaveChanges();
}
catch (DbEntityValidationException e)
{
    if (true)
    {
        // 1.A True
        MyDbEntityValidationException ex = new MyDbEntityValidationException(e);
        Console.WriteLine(Environment.NewLine + "Err.:" + Environment.NewLine + ex.Message);
    // << Entita "Ucto.Activity" událost "Added" nastala(y) následující chyba(y) (validace):
    // Vlastnost: "Activity_abbreviation", Hodnota: "", Chyba: "Pole Activity_abbreviation je povinné." >>
        }
    else
    {
        // 1.B False
        Console.WriteLine(Environment.NewLine + "Err.:" + Environment.NewLine + e.Message);
    // << Validation failed for one or more entities. See 'EntityValidationErrors' property for more details. >>
    }
}

Pak je třída DbEntityValida­tionException, která parsuje Exception, a vrací hezčí výsledek,
pokud ji použiji v kódu nahoře viz 1.A tak to funguje jak má

Pak je ale použití v přepsání SaveChanges(), kde očekávám, že to vybublá do kódu 1/ viz nahoře
ale ono se mi to kousne na throw newException; viz toto:

// https://stackoverflow.com/questions/7795300/validation-failed-for-one-or-more-entities-see-entityvalidationerrors-propert
// spolu s: MyDbEntityValidationException

public partial class DbUctoEntities : DbContext
{

    // obyčejná Exception vrací:
    // << Validation failed for one or more entities. See 'EntityValidationErrors' property for more details. >>

    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException e)
        {
            // MyDbEntityValidationException parsuje Exception a vrací:
            // << Entita "Ucto.Activity" událost "Added" nastala(y) následující chyba(y) (validace):
            // Vlastnost: "Activity_abbreviation", Hodnota: "", Chyba: "Pole Activity_abbreviation je povinné." >>
            var newException = new MyDbEntityValidationException(e);
            throw newException; // <<<<<<<<<<<<<<<<<<<
        }

    }

}

Nevím proč, když mám zakomentovanou (REM) SaveChanges() tak je to OK
... nevím ...

Odpovědět 29.10.2017 10:46
Čím víc se učím, tím víc mi přijde, že toho ještě mnoho neumím
Avatar
Odpovídá na slezak-petr
Ondřej Štorc:29.10.2017 12:09

Koukni se na tohle nastavení: Debug->Exceptions->Check Thrown/User-Unhandled

Odpovědět 29.10.2017 12:09
Život je příliš krátký na to, abychom bezpečně odebírali USB z počítače..
Avatar
slezak-petr
Člen
Avatar
Odpovídá na Ondřej Štorc
slezak-petr:29.10.2017 12:20

Díky za radu ale mám české VS, a nemohu to najít, asi jsem slepý
Soubor | Upravit | Zobrazit | Projekt | Sestavit | Ladit | Tým | Nástroje | Test | Analyzovat | Okno | Nápověda

Odpovědět 29.10.2017 12:20
Čím víc se učím, tím víc mi přijde, že toho ještě mnoho neumím
Avatar
Michaal.K
Člen
Avatar
Michaal.K:19. července 12:38

Ahoj,
mám problém s přidáním dat do lokální databáze DbInvoice.mdf. Pokud přidám nového uživatele v programu přes tento kód:

DbInvoiceEntities db = new DbInvoiceEntities();

Person newPerson = new Person();
newPerson.Name = "Jméno";
newPerson.Surname = "Příjmení";
newPerson.Street = "Ulice";
newPerson.City = "Město";
newPerson.PSC = 73601;
newPerson.ICO = 78321456;
newPerson.DIC = "CZ78321456";
newPerson.Email = "[email protected]";

db.Persons.Add(newPerson);
db.SaveChanges();

a spustím aplikaci a vypíši takto data:

foreach (Person p in db.People)
{
        Console.WriteLine(p.Surname + " " + p.Name + ", city: " + p.City);
}

Tak se mi v programu zobrazí nově založený uživatel. Ale pokud ukončím aplikaci a v Server Explorer dám na připojené databázi zobrazit data tabulky Person, tak je prázdná.
Takže nově zadaný uživatel přes program není uložen v databázi.
Nevíte někdo jakto? Díky za pomoc.....

 
Odpovědět 19. července 12:38
Avatar
Matej Horniak:22. července 10:56

Zdravim chcel by som sa spytat, mam VS 2017 a neukazuje mi tam rovnake moznosti pri tvorbe databazi ako boli v tutorialy preto sa chcem poradit po vybrati tohto modelu pre databazu mi tento riadok kodu ukazuje ze je zly

DbInvoiceEntities db = new DbInvoiceEntities();

a tym padom neviem nic dalej robit

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FakturacnySystem
{
    class Program
    {
        static void Main(string[] args)
        {
            DbInvoiceEntities db = new DbInvoiceEntities();

            Person newPerson = new Person();
            newPerson.Name = "Jméno";
            newPerson.Surname = "Příjmení";
            newPerson.Street = "Ulice";
            newPerson.City = "Město";
            newPerson.PSC = 73601;
            newPerson.ICO = 78321456;
            newPerson.DIC = "CZ78321456";
            newPerson.Email = "[email protected]";

            db.Persons.Add(newPerson);
            db.SaveChanges();

            Console.WriteLine("Persons: ");
            foreach (Person p in db.Persons)
            {
                Console.WriteLine(p.Surname + " " + p.Name + ", city: " + p.City);
            }
            Console.WriteLine(Environment.NewLine);

            Console.WriteLine("Invoices: ");
            foreach (Invoice i in db.Invoices)
            {
                Console.WriteLine("Price: " + i.Price + ", date: " + i.Date);
            }
            Console.WriteLine(Environment.NewLine + "Search Pepa: ");

            Person foundPerson = db.Persons.FirstOrDefault(p => p.Name.Contains("pepa"));
            Console.WriteLine(foundPerson.Surname + " " + foundPerson.Name + ", city: " + foundPerson.City);

            Console.ReadLine();
        }
    }
}
 
Odpovědět 22. července 10:56
Avatar
Karel Labonek:7. srpna 15:11

Ahoj,
omlouvám se asi se ptám špatně, ale mám problém s vytvořením tabulky asi mi něco uniklo.
Dle tutoriálu jdu krok po kroku a narazím na problém s uložením nové tabulky. Konkrétně "add new Table" pak vyplním pár "Name" a "Data type" no a když chci uložit např. křížkem karty tak mi to nabízí : chcete uložit změny? dám ok no a pak se otevře okno s cestou k uložení, mě to nabízí cestu k OneDrive\dokumenty. No evidentně je něco špatně pokud cestu nechám, ale i když ji změním třeba na "D:...něco" tak se mi tabulka nezobrazuje v "Server Explorer" ani po refleši. Děkuji za pomoc :).

 
Odpovědět 7. srpna 15:11
Avatar
Odpovídá na Karel Labonek
Karel Labonek:7. srpna 16:02

Omlouvám se, ale zase jsem se dříve zeptal než jsem měl. Pravě jsem našel na netu u Microsoftu návod dokonce v češtině "":https://docs.microsoft.com/…g-a-designer no a problém se vyřešil zřejmě to bylo řečeno již někde dříve tak se omlouvám, ale mě to uniklo konkrétně mi chybělo přidat zdroj dat (to add a data sorce) po tom už tabulku vidím v "Server Explorer" a z ukládáním nových dat není problém. Nevím jestli jsem sem tento můj koment měl psát, ale třeba to pomůže zase někomu jinému kdo je stejný začátečník jako já :) .

 
Odpovědět 7. srpna 16:02
Avatar
Karel Labonek:7. srpna 18:55

Ahoj,
jak jsem si všiml tak jsi problém vyřešil, rád bych tě požádal tedy o radu. Mám stejný problém s databází a s uložením dat do ní přes EF tak výpis ok ale v Server Explorer nic. Ty jsi měl problém že to zapisovalo někam jinam jak to mám prověřit či opravit? Předem děkuji za pomoc jsem začátečník tak mi některé věci dochází pomalu :( .

 
Odpovědět 7. srpna 18:55
Avatar
Karel Labonek:8. srpna 19:21

Ahoj,
nechci bejt neodbytný, ale potřebuji se hnout z místa. Tak ještě jednou vás zkušenější žádám o radu. Zkusím to lépe formulovat. Dle tohoto tutoriálu se pokouším měnit data v databázi pomocí EF. Za běhu aplikace běží vše ok. Po uzavření app. Zjistím přes Server Explorer že nedochází k propagaci new dat do databáze. Při opětovném spuštění app. jsem znovu na začátku a tabulka je prázdná. Opačně to funguje pokud tabulku naplním přes Server Explorer, tak se data následně objeví i ve výpisu v app. Moc děkuji za vaše případné rady.

 
Odpovědět 8. srpna 19:21
Avatar
Karel Labonek:8. srpna 19:26

Ahoj,
jak jsem si všiml tak jsi problém vyřešil, rád bych tě požádal tedy o radu. Mám stejný problém s databází a s uložením dat do ní, přes app a EF a její výpis je vše ok ale v Server Explorer pak nic. Ty jsi měl problém že to zapisovalo někam jinam jak to mám prověřit či opravit? Předem děkuji za pomoc jsem začátečník tak mi některé věci dochází pomalu :( .

 
Odpovědět 8. srpna 19:26
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 58. Zobrazit vše