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.
Tvůrce
Zobrazeno 43 zpráv z 43.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
"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
Však v aplikaci nepracujes s TOckama, ale s namapovanymi modely.
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á.
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.
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š .
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.
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.
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.
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í.
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.
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.
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
Ale to bych měl zase všude vlastnost Id, která nemá se samotnou třídou nic společného.
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í.
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
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?
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.
Zdá se mě, že poslední dobou lidi vážně vymýšlí příliš komplikovaná řešení na triviální problémy...
Jako z hlediska správného návrhu programu to smysl dává. Otázka je, jestli si tím komplikovat práci.
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.
Co to je TOčko. To bude nějaká super zkratka?
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.
Transfer Object. Normální zkratka každého developera.
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.
MVC je dnes již všude, ať dělá ASP nebo WPF.
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.
Není to podivný návštěvník, ale základní princip toho, jak ten framework funguje.
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.
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í
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í.
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.
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.
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
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.
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.
Z té entity se nedědí, jaký by to mělo smysl? Nejčastěji máš Entitu, ViewModel a repozitář.
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.
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ý.
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.
Zobrazeno 43 zpráv z 43.