IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
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: ASP.NET Core 2.0 - Jak použít DbContext mimo Controller

Aktivity
Avatar
Michael K.
Člen
Avatar
Michael K.:18.2.2018 9:05

Ahoj,

chtěl jsem se zeptat, jak se dá vytvořit instance vlastního DbContextu v ASP NET Core 2 ? (mám jej vygenerovaný pomocí Scaffold-Dbcontext ...

V Controlleru to je v pohodě, nicméně, já bych potřeboval pracovat s databází v souboru, který není controller.

Zde mám controller, kde používám svůj DbContext.

// PurchaseInventoryController.cs
public class PurchaseInventoryController : Controller
    {
        private readonly PurchaseInventoryContext context;
        public PurchaseInventoryController(PurchaseInventoryContext context)
        {
            this.context = context;
        }

Ve Startup.cs, mám přidanou tuto službu:

services.AddDbContext<PurchaseInventoryContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Default")));

Podle tohoto návodu: http://www.c-sharpcorner.com/…et-core-mvc/

Jsem chtěl vytvořít svůj View Component. Jen v tom návodu přeskočte na část, kde je soubor ArticlesServic­s.cs. Autor návodu tam dává nějaká sample data, já bych chtěl ta data vytáhnout z databáze, nicméně, nemohu zde použít svůj DbContext, který jsem vytvořil výše. Prakticky jej mohu používat jen v Controlleru.

Když se pokusím vytvořit ctor třídy ArticleServices.cs, tak stejně, jako v Controlleru, začne mi při vytváření instance této třídy kompilátor křičet, že mu chybí parametr DbContextOptions..

A to je problém, který už druhý den nemohu vyřešit.

Pokud by někdo věděl jak na to, byl bych velice rád :)

Děkuji

 
Odpovědět
18.2.2018 9:05
Avatar
Lako
Člen
Avatar
Lako:18.2.2018 14:52

Můj skromný názor je ten, že bys dbContext neměl používat jinde než v controlleru... - To je podstata celé té architektury... Controller ti přijme požadavek, sosne data z db, hodí je do servisy, ta je zpracuje (vytvoří viewModely), vrátí controlleru, ten je nacpe do view..

 
Nahoru Odpovědět
18.2.2018 14:52
Avatar
Michael K.
Člen
Avatar
Michael K.:18.2.2018 15:46

Ahoj, děkuji za reakci :)

Asi budeš mít v tomto pravdu a nejspíše proto jde ten DbContext použít jen v controlleru.

Já chci ale mít na webu panel, dejme tomu TOP 5 Nejnovějších článků, nebo na ten způsob něco takového. Prakticky Částečné zobrazení, díval jsem se na net a nikde jsem právě nenašel návod, kde použít PartialVie tak, abych mohl použít databázi a tam kde srovnávali PartialView s View Componentem bylo psáno, že ViewComponent má prakticky takový MiniController.

Zkrátka, jak udělat částečné zobrazení, kde částečné zobrazení bude tahat data z SQL pomocí EF ?

Děkuji

 
Nahoru Odpovědět
18.2.2018 15:46
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Lako
David Hartinger:18.2.2018 15:50

Podstata MVC architektury je snad pracovat s databází v modelech, ne v kontrolerech :) Co jsem dělal v ASP.NET, tak se v modelech normálně vytvořila nová instance DbContext v bloku using a pomocí ní se potom s databází pracovalo. Něco podobného jde určitě udělat i teď.

Nahoru Odpovědět
18.2.2018 15:50
New kid back on the block with a R.I.P
Avatar
Michael K.
Člen
Avatar
Michael K.:18.2.2018 15:56

Ahoj,

sjel jsem právě dost tutoriálů a článků a většina tahala data z databáze v Controlleru (do IEnumebrable kolekce například) a danou kolekci předala přes return View() do Viewu. Ale je pravda, že pokud jsem četl teorii, všude bylo psáno, že lézt do DB by se mělo v Modelu, ale v praktických příkladech jsem všude viděl, že data tahají z Controlleru :D Každopádně, lézt do DB raději v modelu, nebo viewmodelu ?

Zkusím to skrze ten using blok a dám echo :)

Zatím díky

 
Nahoru Odpovědět
18.2.2018 15:56
Avatar
Michael K.
Člen
Avatar
Michael K.:18.2.2018 16:00

Nemohu editovat ppředchozí zprávu, tak se omlouvám za doublepost.

Například v Controlleru mám tento kód:

[HttpGet]
        public IActionResult Index()
        {
            List<VMPurchaseInventoryIndex> ViewModelList = new List<VMPurchaseInventoryIndex>();
            var PNs = context.PurchaseInventoryProduct.OrderByDescending(x => x.Priority);
            var Colors = context.PurchaseModelColor.ToList();
            foreach (PurchaseInventoryProduct x in PNs) {
                ViewModelList.Add(new VMPurchaseInventoryIndex { Id = x.Id, Model = x.Model, PartNumber = x.Part_Number, Priority=x.Priority });
            }
            foreach (VMPurchaseInventoryIndex VMPII in ViewModelList) {
                foreach (PurchaseModelColor PMC in Colors) {
                    if (PMC.Model == VMPII.Model) {
                        VMPII.Color = PMC.Color;
                    }
                }
            }
            return View(ViewModelList);

Je to špatně a data bych měl tahat v Modelu ?

Editováno 18.2.2018 16:00
 
Nahoru Odpovědět
18.2.2018 16:00
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Michael K.
David Hartinger:18.2.2018 16:03

Ty LINQ dotazy by měly být určitě v nějaké servise. Do kontroleru je možná vygeneruje nějaký scaffolder nebo jsi to tak viděl v nějakých tutoriálech, kde to chtěli mít rychle hotové nebo se tam dělalo jen něco malého, pro co by se jim nevyplatilo dělat servisu.

Nahoru Odpovědět
18.2.2018 16:03
New kid back on the block with a R.I.P
Avatar
Marian Benčat:18.2.2018 16:29

Ano, v tutoriálech najdeš použití contextu rovnou v controlleru a bohužel to najdeš i ve scaffoldnutých aplikacích CLIčkem / Visual Studiem.

Je to velký bullshit, za který microsoft dostává vlnu kritiky..

ještě větší bullshit je, až zjistíš - že bys měl používat cosi, čemu se říká UOW a pak zajdeš na stránky Microsoftu a zjistíš, že to tam implementují jako service locator a něco co porušuje miliardu principů včetně open-closed principle.

Takže poučení pro tebe je:

  1. DBContext v controllerech až u něčeho opravdu jednoduchého, třeba u vygenerované CRUD appky na základě DB scxhématu
  2. DBContext rozhodně nemá být POUZE v contorllerech
  3. Nedělej obrovské architektonické řešení, dokud ho nepotřebuješ, každé rozhnodnutí a vrstva navíc, by měla mít svoje opodstatnění
  4. V momentě kdy usoudíš. že potřebuješ něco jako UOW, jsou vesměs 2 správné implementace..
    1. UOW, které posíláš do repository v parametru a abstrahuje DBContext EF - protože už samotný DBContext je ve skutečnosti UOW. Tedy něco jako:

      using (uow = uow.Create()) {
      repor.x(..., uow);
      repor2.y(..., uow);

}
s tím, že je ještě dobré, aby ta metoda ve které to máš, měla nullable parametr UOW tak, aby si ho mohl "dědit":

methodA(Uow? parentuow) {

bool own = false;
Uow ownUOW = null;
  // pokud je prebrane UOW, tak prebrat, jinak si vytvorit vlastni
  if (parentuow==null) {
     ownUow = new UOW();
     ownUOW = true;
  } else {
    ownUow = parentuow;
}

     repor.x(..., uow);
     repor2.y(..., uow);
   // commit / dispose pokud je vlastni (a neni parent)
  if (own ) {
    ownUow .Commit();
    ownUow .Dispose();
  }
}

je to z toho duvodu, aby si mohl dedit ten logicky celek a  pak delat:
  using (uow = new UOW()) {
   anotherService.methodA(uow);
   anotherService2.methodXYZ(uow);
}

a jelo ti to pod stejnou transakci

to je ale pomerne voser, takze se to resi třeba přes nějaké aspekty a method interception, případně pomocí metody 2
2) Najdeš si nějaké úložiště, kam si šoupeš ty UOW do stacku, při usingu se to do stacku vkládá, na konci usingu (dochází k automatickému dispose) se z toho stacku vybírá a dělá se commit (samozřejmě je tam ještě nějaká logika nad tím, kde se kontroluje jestli nemá sdílet parent UOW atd.)


Není to úplně jednoduché vymyslet dobře (obzvláště ve webovém prostředí vzhledem k synchronization contextu) ani pro zkušeného programátora a architekta,-- obzvláště, pokud má být jednoduché třeba pak vyměnit Entity Framework a SQL za NoSQL a Mongo.. :-)

Proto bych ti doporučil si do začátků klidně vytvářet EF v controlleru.. Ono stejně 99% transakcí odpovídá 1 requestu. Takže vytváření v controlleru (nebo třeba nějaký IOC container s PerRequest resolverem, není uplně pekelná volba - ale ani ne nejlepší)

Editováno 18.2.2018 16:32
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
18.2.2018 16:29
Totalitní admini..
Avatar
Marian Benčat:18.2.2018 16:33

Zároveň se omlouvám za chyby ve zdorojáku, bohužel tento portál z nějakého - již rok a půl mně neznámého důvodu, neumožňuje zeditovat 2x příspěvek, případně po delší době. Pointu zdrojáku, ale jistě pochopíš.

Nahoru Odpovědět
18.2.2018 16:33
Totalitní admini..
Avatar
Michael K.
Člen
Avatar
Michael K.:18.2.2018 16:48

@David:
Zkoušel jsem to pomocí bloku using, nicméně narazil jsem an stejný problém - kompilátor křičí, že mi chybí parametr, kterým je DbContextOptions, a právě nemám ponětí, jak tento parametr vytvořit :(

O těch servisech slyším prvně, asi to budu muset dostutovat. Nějaká klíčová slova, pod čím to najít, nebo jak se tato problematika nazývá ?

@Marian
Nooo, abych pravdu řekl, mám teď v tom trochu guláš, respektive, hodně pojmů. které jsi použil neznám, ale pogooglím, zkusím pochopit a pak mi to bude dávat snad větší smysl :)

Jedu i hodně podle dokumentace od Microsoftu, tam také v Controlleru tahají data z DB.

Na ten EF jsem si docela zvykl, snažím se dělat i ve WPF, tam jej také používám a docela mi vyhovuje.

Zatím mi právě jde o to, jak udělat PartialView / ViewComponent tak, abych si mohl vytáhnout nějaká data z databáze. Momentálně nejideálnější by pro mě bylo, v modelu si vytvořit instanci dbcontextu, nicméně nemám ponětí jak tam narvat DBContextOptions, jak jsem psal výše.

Jak říkám, zkusím ještě prohledat web, tutoriály, nové pojmy a principy, které zde zazněly a snad budu o něco chytřejší.

Zatím děkuji všem :)

EDIT: Tak jsem to obešel tak, že jsem zrušil u ctoru DbContextu parametr DbContextOptions a vyřešil to skrze přepsání funkce onconfigure.

 
Nahoru Odpovědět
18.2.2018 16:48
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Marian Benčat
David Hartinger:18.2.2018 17:15

Jestli cokoli nefunguje, tak to reportuj a nepiš to jako offtopic do fóra, to už bys mohl vědět. Na takovéhle výkřiky obvykle nebude nikdo reagovat, to platí obecně, nejen tady.

Nahoru Odpovědět
18.2.2018 17:15
New kid back on the block with a R.I.P
Avatar
Odpovídá na David Hartinger
Marian Benčat:18.2.2018 18:03

Myslíš třeba takto?
https://www.itnetwork.cz/…9a3d62180c2e

Editováno 18.2.2018 18:06
Nahoru Odpovědět
18.2.2018 18:03
Totalitní admini..
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Marian Benčat
David Hartinger:18.2.2018 18:06

Ne, myslím jako chybu, jedině tak se to totiž může opravit, pokud to nefunguje.

Nahoru Odpovědět
18.2.2018 18:06
New kid back on the block with a R.I.P
Avatar
Odpovídá na David Hartinger
Marian Benčat:18.2.2018 18:08

Já ti nevím davide, ale pokud mi portál zobrazí přímo hlášku:

"Byl překročen časový limit na editaci zprávy nebo na ni nemáš oprávnění."
Nebo mi poměrně úmyslně nezobrazí ikonku k editaci - tak obzvláště toho, že je to tu tak rok s půl a těžko si toho nikdo nevšimnul, to beru spíše jako featuru, než-li bug. Proto jsem to psal jako dotza od ostatní.

Takže to mám brát tk, že sekce Ostatní ignorujete?

Nahoru Odpovědět
18.2.2018 18:08
Totalitní admini..
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na Marian Benčat
David Hartinger:18.2.2018 18:17

To mi nepiš sem co ti zobrazí nebo nezobrazí, je to komplexní software a já ho už nevyvíjím, pokud si myslíš, že je něco špatně, tak to reportuj a náš programátor to posoudí. Je to poměrně jednoduché a funguje to takhle všude. Ignorujeme tu toho spoustu, protože tu je 100 tisíc lidí. Kdybych do vlákna sám nepřispěl, tak jsem si ani nevšiml, že jsi sem něco takového psal. Proto je tu bugtracker a sekce Chyby, kterou náš vývojář pravidelně čte.

Nahoru Odpovědět
18.2.2018 18:17
New kid back on the block with a R.I.P
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 15 zpráv z 15.