NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: Kam dávat data jen pro Entity framework

V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Petr Čech
Tvůrce
Avatar
Petr Čech:22.9.2015 20:09

Ahojte, dělám relativně jednoduchý prográmek, je jedno, co dělá. Narazil jsem ale na následující problém: mám určité datové struktury, které jsou víceméně univerzální (prostě třídy), a chci je ukládat pomocí EF. Problém je to, že se mi nechce třídu, která nemá s databází vůbec nic společného, kromě toho, že ji tam chci uložit, zatěžovat vlastnostmi a atributy, které se využijí jen v EF (třeba ID a pod.). Napadlo mě, že si udělám jiný namesace, kde vytvořím potomky těchto tříd a tam, kde to bude potřeba přidám vlastnosti a atributy navíc. Tyto třídy bych potom ukládal do DB. Jenže to se mi moc dělat nechce, protože se budou motat názvy a pod.

Odpovědět
22.9.2015 20:09
the cake is a lie
Avatar
Milan Křepelka
Tvůrce
Avatar
Milan Křepelka:23.9.2015 7:56

"Problém je to, že se mi nechce třídu, která nemá s databází vůbec nic společného, kromě toho, že ji tam chci uložit"

Tak to jsem se po ránu opravdu zasmál. Jelikož EF neslouží k ničemu jinému, než k ukládání tříd do databáze, tak mi ten ty tvoje požadavky přijdou úsměvné. Dítě poroditi při tom pannou býti ....

Navíc když je tam budeš chtít uložit, tak je pravděpodobně budeš chtít načíst a nějakým způsobem Identifikovat. Id(jedno číslo) bych tedy nebral jako extra zátěž, navíc se na něj nemusíš až tak vázat

https://msdn.microsoft.com/…j591583.aspx

 
Nahoru Odpovědět
23.9.2015 7:56
Avatar
Jan Vargovský
Tvůrce
Avatar
Odpovídá na Petr Čech
Jan Vargovský:23.9.2015 10:27

Však v aplikaci nepracujes s TOckama, ale s namapovanymi modely.

 
Nahoru Odpovědět
23.9.2015 10:27
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Petr Čech
David Hartinger:23.9.2015 12:58

Ano, tak je to správně, máš 2 třídy - jednu datovou jen pro EF a druhou aplikační. Datové třídy jsou typicky v jiném NS, dohromady se to nemíchá.

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
23.9.2015 12:58
New kid back on the block with a R.I.P
Avatar
Milan Křepelka
Tvůrce
Avatar
Odpovídá na David Hartinger
Milan Křepelka:23.9.2015 14:10

Myslím, že se pleteš. Velmi těžko můžeš v EF pracovat s dvěma třídama v rámci jednoho SETu. Primárně používám code first, ale co vím, tak model first vygeneruje jednu třídu jako partial "autogenerated" a tu druhou část si děláš jako "partial" součást té autogenerated. Tedy je to jedna třída, která ale fyzicky může být uložena ve více souborech.

 
Nahoru Odpovědět
23.9.2015 14:10
Avatar
Milan Křepelka
Tvůrce
Avatar
Odpovídá na Petr Čech
Milan Křepelka:23.9.2015 14:14

V kontextu Davidova příspěvku mi napadlo, že jsi nenapsal jaký přístup používáš. Pokud nepoužíváš Code First, tak se na něj soustřeď. Balast generuje jenom ten, který si sám napíšeš :-).

 
Nahoru Odpovědět
23.9.2015 14:14
Avatar
Michal Žůrek - misaz:23.9.2015 16:29

No já bych to řešil partial třídou. Příjde mi hloupé pak mít vesměs duplicitní třídu, jen kvůli databázi.

 
Nahoru Odpovědět
23.9.2015 16:29
Avatar
Petr Čech
Tvůrce
Avatar
Odpovídá na David Hartinger
Petr Čech:23.9.2015 16:34

takže to bude celé vypadat nějak takto?

public class A
        {
                public string Name { get; set; }
                public int Age { get; set; }
        }

        public class B : A
        {
                [Key]
                public int Id { get; set; }

                [Required]
                [Display(Name = "Name of property")]
                public new int Age { get; set; }

                public B() { }
                public B(A a,int id)
                {
                        PropertyInfo[] aprop = a.GetType().GetProperties();

                        foreach (var info in aprop)
                        {
                                GetType().GetProperty(info.Name).SetValue(this, info.GetValue(a));
                                //zkopírování stejných vlastností
                        }

                        Id = id;
                }
        }

        public class Context : DbContext
        {
                public DbSet<B> Bs { get; set; }
        }

        public static class DB
        {
                public static List<A> LoadAs()
                {
                        using (Context ctx=new Context())
                        {
                                List<A> lst = new List<A>();
                                foreach (B b in ctx.Bs)
                                {
                                        lst.Add(b);
                                }
                                return lst;
                        }
                }

                public static void SaveAs(ICollection<A> col)
                {
                        using (Context ctx = new Context())
                        {
                                ctx.Bs.RemoveRange(ctx.Bs);
                                List<B> lst = new List<B>();
                                for (int i = 0; i < col.Count; i++)
                                {
                                        lst.Add(new B(col.ElementAt(i), i));
                                }

                                ctx.SaveChanges();
                        }
                }
        }

Samozřejmě logika např. ukládání není dokonalá, ale to teď není důležité. A ano, používám code first.

Editováno 23.9.2015 16:36
Nahoru Odpovědět
23.9.2015 16:34
the cake is a lie
Avatar
Lako
Člen
Avatar
Odpovídá na Petr Čech
Lako:23.9.2015 16:34

Při použití EF bys měl mít vždycky Modelové třídy. Tedy třídy, které slouží primárně k ukládání do databáze. Defacto to kopíruje tabulku v databázi. Tuto třídu bys měl používat jenom k tahání dat a přesunutí jich do jakého ViewModelu...
Pokud budeš psát trošku složitější aplikaci, tak pořádek který ti to přinese bude daleko cennější, než nízký počet tříd/souborů.
Databázové třídy bys měl mít ve složce Models, popřípadě celou práci s dtb přesunutou do samostatného projektu (u větších aplikací) - a celé ti to pomůže vyvarovat se referencím v databázovém projektu na hlavní projekty (což je dobře)...
Je to prostě jenom návrhový vzor, který se vyplatí častokrát respektovat.

 
Nahoru Odpovědět
23.9.2015 16:34
Avatar
Milan Křepelka
Tvůrce
Avatar
Milan Křepelka:23.9.2015 18:33

Dlouho na to koukám. A nevím co mi na tom vadí. V původním příspěvku jsem si nevšiml tý dědičnosti a ani tak mi to nepřide moc dobrý nápad. Mám k tomu nějaký přirozený odpor. Ničeho valného nedosáhneš, tedy kromě toho že budeš mít jednu třídu navíc.

Proč tam máš vlastně toto ?

[Required]
[Display(Name = "Name of property")]
public new int Age { get; set; }

Myslím, že to je dobrý příklad programovat přes rozhraní. Ty se chceš vlastně nutně odstínit od databázového "bordelu".

Ven mimo ten databázový svět vytáhneš rozrhaní IA které bude mít tu stejnou signaturu jako třída A a budeš pracovat s rozhraním. Dosáhl jsi téhož při jedné třídě. S benefity programování přes rozhraní.

Ta DB logika nic moc. V podstatě by se dalo říct, že DB nepotřebuješ. Stačila by ti serializace objektů do souboru a takovýhle věci bys nemusel vůbec řešit s minimální pracností i toho ukládání. Tedy pokud DB neslouží i pro jiné části většího řešení.

 
Nahoru Odpovědět
23.9.2015 18:33
Avatar
Petr Čech
Tvůrce
Avatar
Odpovídá na Milan Křepelka
Petr Čech:23.9.2015 18:53

Vzhledem k tomu, že A má určitou funkcionalitu, tak rozhraní bohužel asi těžko.

[Required]
[Display(Name = "Name of property")]
public new int Age { get; set; }

Tohle je ukázka toho, jak natahám databázový bordel do modelu bez toho, aniž by se to povalovalo v samotném A.
A ano, klidně bych mohl použít serializaci do souboru, spíš mě zajímalo, jak má být správně, navíc se nemusím starat o takové kraviny jako uživatelská práva v adresářích, neexistující složky etc.
Databázová logika v příkladu je narychlo splácaná, ve výsledku to vylepším.

Nahoru Odpovědět
23.9.2015 18:53
the cake is a lie
Avatar
Milan Křepelka
Tvůrce
Avatar
Milan Křepelka:23.9.2015 19:25

To se vůbec nevylučuje. Ty bys používal IA, ale ve skutečnosti to jsou objekty B do kterých bys tu logiku samozřejmě napsal. Objekt A by vůbec neexistoval.

Už jsem přišel na to co mi na tom vadí.Tohle není moc dobrý příklad jako používat "jednonásobnou" dědičnost. Je to vlastně pojmutý tak nějak obráceně.

Ty objektům na "konci" řetězce v hiearchii dědičnosti, přidáváš funcionalitu kterou by měly mít společnou... umění se uložit do DB.

Tedy budeš mít N tříd, které budou mít to samé.

[Key]
                public int Id { get; set; }

Přitom "normálně" by měla existovat jedna třída s Id od které by ostatní dědily.

 
Nahoru Odpovědět
23.9.2015 19:25
Avatar
Neaktivní uživatel:23.9.2015 19:44

Nevím, proč by měl být problém mít prostě jednu třídu, bez dalších zbytečných potomků nebo rozhraní. Pokud chceš něco ukládat do databáze, tak říct že to s ní nesouvisí je snad oxymóron :-P

Nahoru Odpovědět
23.9.2015 19:44
Neaktivní uživatelský účet
Avatar
Petr Čech
Tvůrce
Avatar
Odpovídá na Milan Křepelka
Petr Čech:23.9.2015 19:52

Ale to bych měl zase všude vlastnost Id, která nemá se samotnou třídou nic společného.

Nahoru Odpovědět
23.9.2015 19:52
the cake is a lie
Avatar
Petr Čech
Tvůrce
Avatar
Odpovídá na Neaktivní uživatel
Petr Čech:23.9.2015 19:54

Nejde o to, že by to nešlo, samozřejmě to jde, ale třída např. uživatel by neměla vědět o tom, že je určená k uložení v databázi, to by se mělo řešit mimo ní.

Nahoru Odpovědět
23.9.2015 19:54
the cake is a lie
Avatar
Odpovídá na Petr Čech
Neaktivní uživatel:23.9.2015 20:01

Chápu, ale zdá se mě to zbytečné. Naopak, podle mě by třída uživatel měla vědět, že je určená k uložení v databázi, přijde mě úplně zcestné to řešit jinde

Nahoru Odpovědět
23.9.2015 20:01
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Patrik Valkovič:23.9.2015 20:05

Na jednu stranu souhlasím, třída User by vážně neměla vědět, že je určena k uložení k databázi. Dávalo by tedy smysl od ní dědit třídu, která by počítala s tím, že bude uložena v databázi.
Ale s pár výhradami - neměla by jít vytvořit v aplikaci. S odvozenou třídou by mělo jít pracovat pouze tam, kde se pracuje zároveň s databází. Ale jak to vyřešit, mě moc nenapadá. Skrýt konstruktor, vytvořit faktorku. Eventuelně použít jiné assemble?

Nahoru Odpovědět
23.9.2015 20:05
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Jan Vargovský
Tvůrce
Avatar
Odpovídá na Michal Žůrek - misaz
Jan Vargovský:23.9.2015 20:46

Hloupé to není. Až budeš mít model, který třeba bude reprezentovat nějakého usera, tak bude mít x atributů a ve view budeš zobrazovat jeden z nich, taky budeš pořád pracovat s tím TOčkem? To je celkem bad practice. Vždycky vytáhneš data z db a přemapuješ to na model, který je 1:1 ke tvému view.

Editováno 23.9.2015 20:48
 
Nahoru Odpovědět
23.9.2015 20:46
Avatar
Odpovídá na Patrik Valkovič
Neaktivní uživatel:23.9.2015 21:38

Zdá se mě, že poslední dobou lidi vážně vymýšlí příliš komplikovaná řešení na triviální problémy...

Nahoru Odpovědět
23.9.2015 21:38
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Patrik Valkovič:23.9.2015 21:44

Jako z hlediska správného návrhu programu to smysl dává. Otázka je, jestli si tím komplikovat práci.

Nahoru Odpovědět
23.9.2015 21:44
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Milan Křepelka
David Hartinger:23.9.2015 22:45

Ne, to je špatný přístup, míchat se to nesmí. View by nemělo přistupovat vůbec k entitám, někdy se na to používá automapper, někdy se to mapuje ručně. Každopádně na to máš ViewModely. Do EF tříd se také nepíše logika, je rozdíl mezi datovým a doménovým modelem. máš tu tedy Entitu, Model a ViewModel - 3 různé věci, které se někdy míchají dokonce do jedné. mají být ale oddělené, to jsou best practices. Doporučuji si o tom něco nastudovat, není to úplně triviální záležitost. Zde jsou nějaké odkazy:

http://stackoverflow.com/…siness-logic

I would keep my Entities as POCO's(Plain Old Class Objects, classes with only properties) and have a Repositary do methods like Insert / Update.

http://cpratt.co/…-not-models/
http://www.codeguru.com/…ications.htm
https://www.google.cz/webhp?…

Bude tu na to seriál.

Nahoru Odpovědět
23.9.2015 22:45
New kid back on the block with a R.I.P
Avatar
Milan Křepelka
Tvůrce
Avatar
Odpovídá na Jan Vargovský
Milan Křepelka:24.9.2015 7:32

Co to je TOčko. To bude nějaká super zkratka?

Editováno 24.9.2015 7:33
 
Nahoru Odpovědět
24.9.2015 7:32
Avatar
Milan Křepelka
Tvůrce
Avatar
Odpovídá na David Hartinger
Milan Křepelka:24.9.2015 7:57

Jednáte z přesvědčení, že vůbec dělá nějakou MVC aplikaci. Není vůbec zřejmé že potřebuje zvtah DB (Entita,Model), ViewModel.

 
Nahoru Odpovědět
24.9.2015 7:57
Avatar
Jan Vargovský
Tvůrce
Avatar
Odpovídá na Milan Křepelka
Jan Vargovský:24.9.2015 8:15

Transfer Object. Normální zkratka každého developera.

 
Nahoru Odpovědět
24.9.2015 8:15
Avatar
Milan Křepelka
Tvůrce
Avatar
Odpovídá na Jan Vargovský
Milan Křepelka:24.9.2015 8:40

Raději používej celá slova. Hovoříš k lidem, kteří je nejspíš je nebudou znát. Jo a normální developeři používají DTO jako Data Tranfer Object. To tvoje TO je "self made" zkratka.

 
Nahoru Odpovědět
24.9.2015 8:40
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Milan Křepelka
David Hartinger:24.9.2015 9:02

MVC je dnes již všude, ať dělá ASP nebo WPF.

Nahoru Odpovědět
24.9.2015 9:02
New kid back on the block with a R.I.P
Avatar
Milan Křepelka
Tvůrce
Avatar
Odpovídá na David Hartinger
Milan Křepelka:24.9.2015 9:17

To je implikace postavená na vodě. Napsal že dělá jednoduchý prográmek. Tahat to toho tyhle vzory bude spíše zbytečnost. MVC je ve WPF je spíše podivný návštěvník. Nicméně je pravda, že ta "modelová" část je s MVVM prakticky stejná záležitost.

 
Nahoru Odpovědět
24.9.2015 9:17
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Milan Křepelka
David Hartinger:24.9.2015 9:28

Není to podivný návštěvník, ale základní princip toho, jak ten framework funguje.

Nahoru Odpovědět
24.9.2015 9:28
New kid back on the block with a R.I.P
Avatar
Milan Křepelka
Tvůrce
Avatar
Odpovídá na David Hartinger
Milan Křepelka:24.9.2015 9:31

Pouze pokud si pleteš MVC a MVVM.

 
Nahoru Odpovědět
24.9.2015 9:31
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Milan Křepelka
David Hartinger:24.9.2015 9:36

Aha a ta vrstva s CodeBehind je co? Pracuje s logikou a předává ji pohledu (XAMLu), nedělá to náhodou kontroler? :-` Že se to tak nejmenuje neznamená, že to není MVC architektura.

Nahoru Odpovědět
24.9.2015 9:36
New kid back on the block with a R.I.P
Avatar
Neaktivní uživatel:24.9.2015 9:39

Popravdě, já osobně nevidím problém s business logikou v entitách a zdá se mě, že tyhle samý návrhový vzory to jenom komplikujou a výhody nepřidávají

Nahoru Odpovědět
24.9.2015 9:39
Neaktivní uživatelský účet
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Neaktivní uživatel
David Hartinger:24.9.2015 9:41

Dělej si to jak chceš, třeba si to piš neobjektově. My se jen vyjadřujeme k tomu, jak se tom má dělat správně. A komplikované to není, je to jednoduché rozdělení.

Nahoru Odpovědět
24.9.2015 9:41
New kid back on the block with a R.I.P
Avatar
Milan Křepelka
Tvůrce
Avatar
Milan Křepelka:24.9.2015 9:50

Autobus není auto i přes to, že má 4kola a motor. MVC, MVP, MVVM jsou stejná rodina, ale ty rozdíly jsou určující právě z pohledu technologie kterou zajišťije databinding ve WPF. Hovořit o MVC se spojením s WPF je lehce mimo. Měl by sis všimnout, že mnoho ostatních mezi tím vidí rozdíly.

 
Nahoru Odpovědět
24.9.2015 9:50
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Milan Křepelka
David Hartinger:24.9.2015 9:52

Tady si nerozumíme, já neříkám, že MVC a MVVM je to samé. Já říkám, že ve WPF máš principy MVC i MVVM. Stejně jako tomu tak je v ASP.NET.

Nahoru Odpovědět
24.9.2015 9:52
New kid back on the block with a R.I.P
Avatar
Odpovídá na David Hartinger
Neaktivní uživatel:24.9.2015 10:01

Jak se to dělat má... No i na stackoverflow se o tom lidi hádají a sice je pravda že převládá názor, že z hlediska puristického přístupu by odděleny být měli, tak z hlediska pragmatismu nemusí. Zvlášť pokud jde o menší aplikaci. Někteří lidé říkali i to, že právě v EF je možné mít to v jedné entitě a že je na to EF i připravenej

Nahoru Odpovědět
24.9.2015 10:01
Neaktivní uživatelský účet
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Neaktivní uživatel
David Hartinger:24.9.2015 10:03

Lidé se hádají pořád, na základě toho bych si určitě nestavěl názor ;-) Mně je to jedno, napsal jsem vám jak to je správně, dělejte si to jak chcete, to už je vaše věc, vaše projekty a vaše chyby.

Nahoru Odpovědět
24.9.2015 10:03
New kid back on the block with a R.I.P
Avatar
Milan Křepelka
Tvůrce
Avatar
Odpovídá na Neaktivní uživatel
Milan Křepelka:24.9.2015 10:04

O to taky problém není. Dělat jakousi zcela prázdou "Entitu" abys ji mohl podědit a napsat do ní nějakou logiku je pitomost. Nedádá to elementární smysl.

 
Nahoru Odpovědět
24.9.2015 10:04
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Milan Křepelka
David Hartinger:24.9.2015 10:12

Z té entity se nedědí, jaký by to mělo smysl? Nejčastěji máš Entitu, ViewModel a repozitář.

Nahoru Odpovědět
24.9.2015 10:12
New kid back on the block with a R.I.P
Avatar
Milan Křepelka
Tvůrce
Avatar
Odpovídá na David Hartinger
Milan Křepelka:24.9.2015 10:22

Ale o tom je tento dotaz. Uživatel dělá potomky tříd a tys mu tento postup vlastně potvrdil. Ale jinak si myslím, že z větší části rozporů jde o zmatení pojmosloví mezi "entitou", modelem, viewmodelem a dokonce se nám tu objevili DTO objekty.

Nejlepší na toto je, je praxe. Pak si člověk uvědomí co je co. Míru odpovědnosti a názor si utříbí vlastně sám.

 
Nahoru Odpovědět
24.9.2015 10:22
Avatar
Milan Křepelka
Tvůrce
Avatar
Odpovídá na Milan Křepelka
Milan Křepelka:24.9.2015 10:28

Uživatel == czubehead

 
Nahoru Odpovědět
24.9.2015 10:28
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Milan Křepelka
David Hartinger:24.9.2015 10:31

To potvrzení jsem myslel na to, že to má oddělit. Děděním se nic nevyřeší, je to to samé jako by to napsal do jednoho nebo udělal partial. Máš pravdu, že z této diskuze nejde moc poznat jak to má tedy být, padlo tu spoustu pojmů, tohle je problematika na celý seriál, který se mimochodem sepisuje, je asi z 50% hotový.

Editováno 24.9.2015 10:32
Nahoru Odpovědět
24.9.2015 10:31
New kid back on the block with a R.I.P
Avatar
Petr Čech
Tvůrce
Avatar
Petr Čech:24.9.2015 14:19

Děkuji všem za zpětnou vazbu. Vzhledem k tomu, že ta appka je opravdu jednoduchá (3 "hlavní" třídy), napíšu to prostě do těch tříd a až budu dělat něco složitějšího, budu to dělat správně. Jsem si vědom toho, že to je z hlediska návrhu špatně, ale moc nevěřím tomu, že u této konkrétní aplikace by to byl problém. Až bude hotový seriál, rád si ho přečtu.

Nahoru Odpovědět
24.9.2015 14:19
the cake is a lie
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 43 zpráv z 43.