Diskuze: Entity Framework Code First a relace mezi tabulkami
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.


Zobrazeno 13 zpráv z 13.
K personalizaci obsahu a reklam, poskytování funkcí sociálních médií a analýze naší návštěvnosti využíváme soubory cookie. Informace o tom, jak náš web používáte, sdílíme se svými partnery pro sociální média, inzerci a analýzy. Partneři tyto údaje mohou zkombinovat s dalšími informacemi, které jste jim poskytli nebo které získali v důsledku toho, že používáte jejich služby.
Používáme nezbytné cookies pro fungování webu a s tvým souhlasem také analytické a marketingové cookies.
Zajišťují základní funkce, bezpečnost a služby, které sis vyžádal. Nelze je vypnout.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| ITnetwork | ITnetwork | Provoz webu, relace, přihlášení a uložení nastavení cookies. | PHPSESSID, auth_token, sid, itn_consent_impression, __Host-itn_consent | Relace až 1 rok |
| Google Tag Manager | Správa značek a načítání měřicích nástrojů webu. | Žádné | Neukládá se | |
| Google Fonts | Načítání typografie webu. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele | |
| Google Hosted Libraries | Načítání potřebných knihoven a stylů webu. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele | |
| Google reCAPTCHA | Ochrana formulářů a webu před zneužitím. | _GRECAPTCHA, rc::a, rc::b, rc::c, rc::f | Relace až 180 dní | |
| YouTube | Přehrávání vloženého video obsahu. | localStorage, IndexedDB; cookies after playback interaction | Relace až trvalé úložiště | |
| Vimeo | Vimeo | Přehrávání vloženého video obsahu. | __cf_bm, _cfuvid, vuid, localStorage, IndexedDB | Relace až 2 roky |
| Facebook Login | Meta | Přihlášení pomocí účtu třetí strany. | Úložiště řízené poskytovatelem | Relace až 1 rok |
| GoPay | GoPay | Zpracování uživatelem vyžádané platby. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele |
Pomáhají nám porozumět používání webu a zlepšovat ho.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| Google Analytics 4 | Měření návštěvnosti a používání webu. | _ga, _ga_* | Až 2 roky | |
| Microsoft Clarity | Microsoft | Měření návštěvnosti a používání webu. | _clck, _clsk, _cltk | Relace až 1 rok |
Slouží k měření kampaní, personalizaci reklamy a marketingové komunikaci.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| Google Ads | Měření kampaní, reklama a remarketing. | _gcl_au, _gcl_ls | Relace až 90 dní | |
| Meta Pixel | Meta | Měření kampaní, reklama a remarketing. | _fbp, _fbc, localStorage | Až 90 dní |
| Sklik | Seznam.cz | Měření kampaní, reklama a remarketing. | retargeting, sid, szn:* | Relace až trvalé úložiště |
| LinkedIn Insight | Měření kampaní, reklama a remarketing. | bcookie, li_gc, lidc, __cf_bm | Relace až 1 rok | |
| Ecomail | Ecomail.cz | Měření kampaní, reklama a remarketing. | ecmid, Úložiště řízené poskytovatelem | Dle podmínek poskytovatele |
| Atribuce kampaní ITnetwork | ITnetwork | Přiřazení návštěvy a objednávky ke kampani. | campaign_clid[*], user_session_context | Až 1 rok |
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.


Máš to správně, myslím.
Kolekce se označují jako virtuální, aby se umožnil lazy-loading, ale
teoreticky není potřeba.
Hmm a jak teď vytvořím novou instanci Person s Kalendarem, protože když to zkouším, tak mi to nejde. A mám něco dávat do vlastností PersonId a Person? Nebo se to udělá automaticky?
using (var db = new PersonContext())
{
db.Persons.Add(new Person()
{
Jmeno = "Pavel",
Prijmeni = "Novak",
Vek = 20,
Kalendar = new Kalendar()
{
Udalost = "Schuzka",
Zprava = "Nejaka zprava",
}
});
}
Nooo.neukládáš to, musíš dát
db.SaveChanges();
No to sice taky, ale ještě předtím mi to začervení celý řádek, kde
se snažím vytvořit Kalendar a píše mi to:
"Cannot implicitly convert type 'DbModels.Models.Kalendar' to
'System.Collections.Generic.ICollection<DbModels.Models.Kalendar>'.
An explicit conversion exists (are you missing a cast?)"
Protože ty Kalendar je kolekce, ale ty se tam snažíš nacpat objekt. Měl bys změnit pojmenování.
using (var db = new PersonContext())
{
Person p=new Person()
{
Jmeno = "Pavel",
Prijmeni = "Novak",
Vek = 20,
Kalendar = new List<Kalendar>();
};
p.Kalendar.Add(new Kalendar()
{
Udalost = "Schuzka",
Zprava = "Nejaka zprava",
});
db.Persons.Add(p);
}
Vyřešil jsem to takto, a teď ještě jak ty data načíst zpět z databáze.
using (var db = new PersonContext())
{
db.Persons.Add(new Person()
{
Jmeno = "Pavel",
Prijmeni = "Novak",
Vek = 20,
Kalendar = new Collection<Kalendar>()
{
new Kalendar()
{
Udalost = "Schůzka",
Zprava = "V parku na náměstí",
Datum = "21.05.2016 12:00",
}
}
});
db.SaveChanges();
}
Třeba takto 
using (var db = new PersonContext())
{
List<Person> people=db.Persons.ToList();
}
Jo a ještě něco, když máš Id nějaké třídy, tak se nepoužívá
[Key]
public int MojeTridaId ...
ale
[Key]
public int Id ...
Je to sice jen konvence, ale přecijen to je dobré.
Ještě se pokouším udělat si servisní třídu na načítání dat (mělo by se jednat o DTO, pokud jsem ten koncept pochopil správně)
public class DataService : DataServiceBase
{
public IEnumerable<Person> GetPersons()
{
using (var db = CreateDataContext())
{
return db.Persons.Select(s => new Person()
{
Id = s.Id,
FirstName = s.FirstName,
LastName = s.LastName,
Address = s.Address
}).ToList();
}
}
a pak ve ViewModelu
private ObservableCollection<Person> personObs = new ObservableCollection<Person>();
public ObservableCollection<Person> PersonObs
{
get { return personObs; }
set { personObs = value; NotifyOfPropertyChange(() => PersonObs); }
}
DataService ds = new DataService();
protected override void OnInitialize()
{
PersonObs.Clear();
foreach (var item in ds.GetPersons())
{
personObs.Add(item);
}
}
Dostanu ale následující chybu
Additional information: The entity or complex type
'WPF_DatabaseApplication.Context.Person' cannot be constructed in a LINQ to
Entities query.
Pro jistotu ještě přidám modely (vztah mezi modely by měl být 1 ku 1)
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual Address Address { get; set; }
}
a
public class Address
{
[Key, ForeignKey("Person")]
public int PersonId { get; set; }
public string Street { get; set; }
public string City { get; set; }
public virtual Person Person { get; set; }
}
To totiž nejde, entita reprezentuje řádek v tabulce a ne objekt sám o
sobě a to by rozbilo spoustu věcí.
Podívej se sem: http://stackoverflow.com/…tities-query
1. odkaz z Googlu btw 
Ten odkaz jsem našel, ale nebyl jsem z něho právě moc chytrý. Proto se ptám i tady. Jak se to tedy řeší, když chci ty data z databáze dostat?
třeba takto:
var db = new PersonContext();
var osoba = db.Persons.FirstOrDefault();
to ti vytáhne první osobu z "tabulky" Persons...Pokud tam žádná není,
vrátí ti to null
A ten virtual tam je proto, aby jsi mohl přistoupit i k dalšímu objektu, tedy
v tomhle případě
var prvniKalendar= osoba.Kalendar.FirstOrDefault();
Pokud je osoba null, tak to žuchne.
ještě jedno upozornění: když máš kolekci tak jí nazývej množně, tedy Kalendare, takle se ti to akorát zamotá...
Ahoj, mám takový dojem, že to nebude to, na co se ptal.
Pro Milan:
Entity by ti nikdy neměly "probublávat" do uživatelského rozhraní. Je pro
to lepší využít právě DTO, na které se ptáš. Ty modely Person a Address
jsou v podstatě jen jakési šablony tabulek pro databázi (jak už uvedl
czubehead) a nic složitějšího, bys s nimi neměl dělat.
Pokud chceš mít nějakou třídu, která ti bude obsluhovat DAL (Data Access Layer), pak si vytvoř v projektu novou složku a tu nazvi například "DTO" a zde si založ třídu "PersonDTO" a "AddressDTO". Obě tyto třídy budou obsahovat jen ty property, které chceš ze svého modelu dostat. Takže např.:
public class AddressDTO
{
public string Street { get; set; }
public string City { get; set; }
}
public class PersonDTO
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
A pak následně vé tvé třídě DataService, bude metoda pro získání dat vypadat nějak takto:
public IEnumerable<PersonDTO> GetPersons()
{
using (var db = CreateDataContext())
{
return (from s in db.Persons
select new PersonDTO
{
Id = s.Id,
FirstName = s.FirstName,
LastName = s.LastName
}).ToList();
}
}
public IEnumerable<AddressDTO> GetAddress(int id)
{
using (var db = CreateDataContext())
{
return (from s in db.Addresses where s.PersonId == id
select new AddressDTO
{
City = s.City,
Street = s.Street
}).ToList();
}
}
Samozřejmě nezapomeň, že pokud to budeš ukládat do nějakého listu a zobrazovat třeba ve WPF DataGridu, tak ten list musí být rovněž datového typu PersonDTO a AddressDTO. Doufám, že to je to, co jsi chtěl vědět a pokud jsem zde napsal nějakou hloupost, tak prosím někoho fundovanějšího o opravu.
Zobrazeno 13 zpráv z 13.