Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Vložení dat do databáze pomocí EF

Aktivity
Avatar
Petr Kasnal
Člen
Avatar
Petr Kasnal:4.4.2018 18:49

Ahoj používám Entity Framework ve WPF MVVM a mám jednu otázku budu se jí snažit vysvětlit co nejlépe. :D Mám tabulku User a tabulku UserPhoto vazba 1:N a všechno funguje jak má. Ale když si vytvořím nový obejkt UserPhoto a má všechny property nastavený tj. Name, Document, User a User_ID ale když dám _userService.U­serPhotos.Add(ne­wUserPhoto) tak to spadne s hláškou: An entity object cannot be referenced by multiple instances of IEntityChange­Tracker chápu proč je to kvůli tomu že tam posílám i ten objekt User dá se to nějak obejít ? Nebo musím udělat

_userService.UserPhotos.Add(new UserPhoto() {
        Name = ....,
        Document = ....,
        User_ID = ....
});

Předem díky za jakoukoli radu či vysvětlení :)

 
Odpovědět
4.4.2018 18:49
Avatar
xpoproci
Člen
Avatar
Odpovídá na Petr Kasnal
xpoproci:4.4.2018 19:13

skús tam neposielať ten User object, jednoducho tam pošli null. Možno by bolo fajn tu hodiť aj jednotlivé kódy týchto entít. a service ak tak.

Nahoru Odpovědět
4.4.2018 19:13
Motto
Avatar
Petr Kasnal
Člen
Avatar
Odpovídá na xpoproci
Petr Kasnal:4.4.2018 22:38

Děkuju za odpověď. Ale musím říct, že mi příliš nepomohla přesně todle jsem totiž napsal já. Že vím že se to dá udělat že tam ten obejkt vůbec nepošlu a vlastně naplním to ostatní ale já se ptám zda se nějak nedá udělat to že tam pošlu všechno a ono to samo pozná že ten obejtk nechce.

 
Nahoru Odpovědět
4.4.2018 22:38
Avatar
xpoproci
Člen
Avatar
Odpovídá na Petr Kasnal
xpoproci:5.4.2018 7:21

bez kódu veľa vody nenamútime. Riešenie je použiť 2 contexty. Z jedného vytiahnuť Usera a do druhého zapísať UserPhoto. Lenže nemáme veľmi odkiaľ vedieť, čo sa tam vlastne deje.

Nahoru Odpovědět
5.4.2018 7:21
Motto
Avatar
Odpovídá na xpoproci
Marian Benčat:5.4.2018 7:29

mít více DBContextu - obzvláště při jedné logické transakci je naprosto fantastický způsob, jak si nasr*t do bot :-)

Nahoru Odpovědět
5.4.2018 7:29
Totalitní admini..
Avatar
Petr Kasnal
Člen
Avatar
Odpovídá na Marian Benčat
Petr Kasnal:6.4.2018 12:01

Ano to vím no že mít více DBContextu by se nemělo úplně dělat a to také dodržuji. A bez kódu myslel jsem, že je to jasné kód by mohl vypadat následovně:

var newUserPhoto = new UserPhoto() {
        Name = "Photo2",
        Document = "photo.jpg",
        User = .... (Objekt uživatele)
        User_ID = (Objekt uživatele).ID
};

//Co bych chtěl
_userPhotoService.UserPhotos.Add(newUserPhoto);

//Co musím udělat
_userPhotoService.UserPhotos.Add(new UserPhoto() {
        Name = newUserPhoto.Name,
        Document = newUserPhoto.Document,
        User_ID = newUserPhoto.ID,
        //User = newUserPhoto - todle právě nejde udělat proto nemůžu použít to co chci.
});

Stačí todle jako příklad ? Když použiju to co bych chtěl vyhodí to tuto hlášku: An entity object cannot be referenced by multiple instances of IEntityChange­Tracker

 
Nahoru Odpovědět
6.4.2018 12:01
Avatar
Odpovídá na Petr Kasnal
Marian Benčat:6.4.2018 12:28
  1. Kde ti vzniká DBContext
  2. Kde ti vznikl User, odkud si ho vzal?
Nahoru Odpovědět
6.4.2018 12:28
Totalitní admini..
Avatar
Petr Kasnal
Člen
Avatar
Odpovídá na Marian Benčat
Petr Kasnal:8.4.2018 13:46
public class DatabaseContext : DbContext
{
    public DbSet<Work> Works { get; set; }
    public DbSet<WorkDay> WorkDays { get; set; }
    public DbSet<Log> Logs { get; set; }

    public DatabaseContext() : base("WorkContext")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

2. User mi vzniká v oknu kde si vyplňuju uživatelovo jmeno a dokument pak je prave poslan ten newUserPhoto to je ten objekt. Napsal jsem to tkhle rychle jenom abych to zkrátil jak jsem dal ten priklad tk to Photo2 atd. je vlastně brano z textboxu, ktere jsou napojeny na newUserPhoto

 
Nahoru Odpovědět
8.4.2018 13:46
Avatar
lukasko.simon:17.4.2018 11:28

posielaj tam len user ID, User objekt tam vobec nemusis nastavovat EF si ho vie pri SaveChanges sam doplnit resp. ho vobec nepotrebuje ak ma cudzi kluc.

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
 
Nahoru Odpovědět
17.4.2018 11:28
Avatar
Petr Kasnal
Člen
Avatar
Odpovídá na lukasko.simon
Petr Kasnal:17.4.2018 13:25

Jj díky nakonec jsem to tk udělal, ale příde mi to zvláštní. User si ulozim do pomocny proměny a u objektu ktery vkladam do db nastavim user na null a pak ho tam za vratim.

 
Nahoru Odpovědět
17.4.2018 13:25
Avatar
Odpovídá na Petr Kasnal
Michal Štěpánek:18.4.2018 7:25

Nějak pořád nechápu, proč do toho objektu "UserPhoto" pořád tlačíš celý objekt "User"? K čemu to tam potřebuješ, když přeci v DB máš referenci na User pomocí cizího klíče, ne? Pohodlně tam stačí mít ID_user a všechno musí makat OK...

Nahoru Odpovědět
18.4.2018 7:25
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Odpovídá na Michal Štěpánek
Marian Benčat:18.4.2018 14:10

Todle je skutečně problém EF a nejen EF.. je to problém obecně ORM ( i kdžy todle je zrovna asi specifické pro EF a tuším že i doctrine) .. nikdy sis nekladl otázku:

"a proč to jako nemůžu udělat?"
Ty bys měl být schopný todle udělat.. problém je, že tě nedostatečně ten EF odstiňuje od databáze a od toho jak uvnitř funguje (od identity mapy).

proto první věc, co zkušený člověk udělá, když začne pracovat s nějakým ORM a myslí to vážně (třeba při použití DDD) je, že vypne:

  • lazy loading
  • dynamic proxies
  • automaticky tracking

Případně.. to nechá zapnuté, ale rozhodně z DAL vstvy nevrací žádný "entity object".

Tedy - pokud už má potřčbu dělat dynamický repository.. nemá
Repository<T> where T: entita

ale

Repository<TEntita, TModel> where T:entita, TModel:DomainOb­ject.:
A uvnitř toho repository - jeste pred tim, než se ten objekt navratí se to mapuje..

Hodně jednoduše (a ne ideálně) to jde udělat pomocí Automapperu, lépe to jde udělat pomocí Select() expressionu.

Stejně tak samozřejmě tvůj DAL přijímá doménový objekt, uvnitř ho mapuje na Entitu a to stylem:

  1. Get from DB
  2. Update property
  3. Save to DB

Jedině tak totiž uděláš opravdu funkční abstrakci.

Nahoru Odpovědět
18.4.2018 14:10
Totalitní admini..
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 12 zpráv z 12.