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í.
Avatar
Luboš Hnědý:21.10.2018 1:27

Zdravím. Potřeboval bych poradit. Programuji v .net mvc a používám entity framework. Mám napsanou precudur která mi vrátí kategorii a její podkategorie. Vypadá to zhruba takto.

ID Name ID_Parent
1 Cat1 NULL
2 Cat2 1
3 Cat3 1
4 Cat4 3
5 Cat5 3

A já bych z toho potřeboval udělat tree menu, které bude vypadat zhruba takto:
Cat1
Cat2
Cat3
Cat4
Cat5

Vůbec nevím jak to do této podoby dostat... Zkouším to celý den a prostě to nejde....

Zkusil jsem: Hledat na google, ale nic moc jsem nenašel

Chci docílit: Vytvořit funkční metodu. Může to mít podobu například modelu.
public Test {
int ID
string Name
List<Test>
}

Opravdu budu rád za jakoukoli radu opravdu už prostě nevím....

 
Odpovědět
21.10.2018 1:27
Avatar
vajkuba1234
Člen
Avatar
Odpovídá na Luboš Hnědý
vajkuba1234:21.10.2018 3:47

Jde ti o to mit kategorii, ktera ma pak n podkategorii? Co ti brani udelat nasledujici? Viz

public class Section
{
        public int ID { get; set; }
        public string Name { get; set; }
        public List<Category> Categories { get; set; }
}

public class Category
{
        public int ID { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public string Content { get; set; }
}

Pak si v DbContextu udelas vazby a proste je plnis. V cem je konkretne problem?

Editováno 21.10.2018 3:48
Nahoru Odpovědět
21.10.2018 3:47
No hope, no future, JUST WAR!
Avatar
Odpovídá na Luboš Hnědý
don.jarducius:21.10.2018 20:24

Ahoj, to co hledáš je rekurze, buď si ji můžeš udělat v C# viz. třeba. … sice v javě (C# je hodně podobný)
nebo
MSSQL podporuje tuším od verze 2008 rekurzivní SQL dotazy... Viz. třeba...

To ti pomůže vytvořit tebou požadované podklady pro menu.

Nahoru Odpovědět
21.10.2018 20:24
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Avatar
Jirka
Člen
Avatar
Odpovídá na don.jarducius
Jirka:21.10.2018 20:36

Ahoj,
don.jardacius má pravdu. Ten MS SQL Server to nativně umí od verze 2005 a ve verzi MSSQLServer2016 jde ještě o hodně dále. Také to umí MariaDB, která je zdarma dostupná jako XAMPP ( https://www.apachefriends.org ).

Nahoru Odpovědět
21.10.2018 20:36
Kdo nic nedělá, nic nezkazí.
Avatar
Jirka
Člen
Avatar
Odpovídá na Jirka
Jirka:21.10.2018 20:44

Ještě bych dodal, že pokud to budeš chtít realizovat bez pomoci databáze, tak základní struktura (binárního) stromu má tvar:

class uzel
{
        int info;
        uzel levy;
        uzel pravy;
}
Nahoru Odpovědět
21.10.2018 20:44
Kdo nic nedělá, nic nezkazí.
Avatar
Odpovídá na don.jarducius
Luboš Hnědý:22.10.2018 8:56

Všem moc děkuji za odpověď. :) Rekurzi znám a vím, že se to dá udělat i v MsSql. Já to dokonce v MsSql dělám. Vrátí mi kategorii a všechny její podkategorie, to je v pohodě. Problém ale nastává teď. Data mi přišli ve struktuře jak jsem psal výše. A chtěl bych z toho udělat TreeMenu. A nějak jsem se do toho zamotal a prostě nevím. Je mi jasný že tam půjde o rekurzi, ale nemůžu nějak přijít na to jak to co nejlíp udělat. Víceméně z tohoto výstupu budu dělat html.
<li>Kat1</li>
<li>Kat2</li>
<ul>Kat3
<li>Kat4</li>
<li>Kat5</li>
<ul>

atd. atd. Takže bych spíše potřeboval poradit jak vytvořit funkci, která mi to přežvejká a převede do následující podoby. Předem díky

Editováno 22.10.2018 8:56
 
Nahoru Odpovědět
22.10.2018 8:56
Avatar
Odpovídá na Luboš Hnědý
don.jarducius:22.10.2018 9:28

V tom případě mi přijde rekurze na SQL zbytečná a udělal bych ji až na úrovni C#, jinak by jsi ji dělal vlastně 2x.
Natáhni si z SQL pouze potřebné sloupce celého menu a udělej si rekurzi až na úrovní C# při generování menu.

Nahoru Odpovědět
22.10.2018 9:28
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Avatar
Jirka
Člen
Avatar
Odpovídá na Luboš Hnědý
Jirka:22.10.2018 12:18

Ahoj,
kdysi jsem to dělal, tak jsem našel a lehce upravil jeden SQL kód, který vrací hierarchii, jako asi potřebuješ. Má to chybku, že to nesetřídí hierarchicky, ale to jde dobře dodělat.

create procedure GetFullHierarchy
(
        @topic int output -- real 'selected' record
)
as
begin

begin try

begin transaction

declare @root int;
set @root = (select min(ID) from topics where UP is NULL);
if (@topic = -1) set @topic = @root;

with TopicsTemp2(ID, UP, lvl)
as
(
        select ID, UP, cast(0 as int)
        from topics
        where ID = @root
        union all
        select X.ID, X.UP, cast(Y.lvl+1 as int)
        from topics as X join TopicsTemp2 AS Y on X.UP = Y.ID
)
,
TopicsTemp2b(ID)
as
(
        select ID
        from topics
        where ID = @root
        union all
        select X.ID
        from topics as X join TopicsTemp2b AS Y on X.UP = Y.ID
)
select A.*, B.*
from TopicsTemp2 as A
left join TopicsTemp2b as B on A.ID = B.ID
join topics as C on A.ID = C.ID
-- order by lvl asc, lvlpos asc
option (maxrecursion 16);

commit transaction

set @topic = @root;

end try
begin catch

declare @systemerror int;
set @systemerror = @@ERROR;
rollback transaction;
return @systemerror;

end catch

end
go

Funguje to tak, že to získá jako parametr nebo selectem vybere root, tedy vrchol hierarchie. Od něho se potom vyberou všechny podřízené větve, do konce. Při tom se ke každému řádku počítá i odsazení pro zobrazení menu.

Editováno 22.10.2018 12:20
Nahoru Odpovědět
22.10.2018 12:18
Kdo nic nedělá, nic nezkazí.
Avatar
Odpovídá na Jirka
Luboš Hnědý:22.10.2018 12:35

Moc ti děkuji za odpověď. Podívám se na to a určitě dám vedět. :) Mohl by si mi prosím tě poslat jak vypadá výstup?

 
Nahoru Odpovědět
22.10.2018 12:35
Avatar
Jirka
Člen
Avatar
Odpovídá na Luboš Hnědý
Jirka:22.10.2018 13:38

Rádo se stalo.

Co se týče výstupu, ten se mi momentálně nedaří automaticky vygenerovat. Ale hlavní myšlenka je v tom prvním bloku WITH, který vytváří první virtuální tabulku TopicsTemp2, která má sloupce ID, UP a lvl (což je hloubka odsazení).

Druhý blok WITH vytváří tabulku TopicsTemp2b, která poskytuje sloupec ID. Tyto dvě virtuální tabulky (TopicsTemp2 a TopicsTemp2b) pak slouží za zdroj výslednému SELECTu na konci složeného příkazu.

Nahoru Odpovědět
22.10.2018 13:38
Kdo nic nedělá, nic nezkazí.
Avatar
Jirka
Člen
Avatar
Odpovídá na Luboš Hnědý
Jirka:22.10.2018 15:07

Tak ještě jednou a lépe:

with TopicsTemp2(ID, UP, lvl)
as
(
        select ID, UP, cast(0 as int)
        from topics
        where ID = @root
        union all
        select X.ID, X.UP, cast(Y.lvl+1 as int)
        from topics as X join TopicsTemp2 AS Y on X.UP = Y.ID
)
,
TopicsTemp2b(ID)
as
(
        select ID
        from topics
        where ID = @root
        union all
        select X.ID
        from topics as X join TopicsTemp2b AS Y on X.UP = Y.ID
)
select A.ID, A.UP, case when B.ID is NULL then cast(1 as bit) else cast(0 as bit) end as SELECTED, A.lvl,
case
        when (select count(*) from TopicsTemp2 where C.ID = UP) > cast(0 as int) or (select count(*) from topics where UP = @root AND C.ID = UP) > cast(0 as int) then cast(2 as int)
        when (select count(*) from topics where C.ID = UP) > cast(0 as int) then cast(1 as int)
        else cast(0 as int)
end as PACKED,
row_number() over(partition by C.UP order by TITLE) as lvlpos, C.TITLE as TopicName
from TopicsTemp2 as A
left join TopicsTemp2b as B on A.ID = B.ID
join topics as C on A.ID = C.ID
order by lvl asc, lvlpos asc
option (maxrecursion 16);

Změny: Doplnil jsem v předchozím příkladě zbytečně vynechaný kód, odkomentoval jsem řazení. Je to prakticky ve stavu, jako to dříve fungovalo. Ale nemám možnost to ověřit.

Asi vím, co Tě teď brzdí, hierarchický návrh tabulky. Sice to je snadné, ale asi se mi to nepodaří zopakovat.

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
22.10.2018 15:07
Kdo nic nedělá, nic nezkazí.
Avatar
Jirka
Člen
Avatar
Odpovídá na Luboš Hnědý
Jirka:22.10.2018 15:25

Ještě tu jsem s návrhem (diagramem) hierarchii podporující tabulkou, podobnou, jako těžím dotazem.

Nahoru Odpovědět
22.10.2018 15:25
Kdo nic nedělá, nic nezkazí.
Avatar
Marek Kočí
Tvůrce
Avatar
Marek Kočí:22.10.2018 15:44

Kdysi dávno jsem zplodil toto: TreeView ve WEBFORMS ASP.NET a hierarchická data v jedné tabulce ,

je to sice vbnet, ale přepsat to je otázka minut.

Editováno 22.10.2018 15:46
 
Nahoru Odpovědět
22.10.2018 15:44
Avatar
don.jarducius:22.10.2018 20:26

Ok... co takhle… viz. obrázek. Rekurzi na úrovni SQL nedělej, udělej ji až při vykreslení.

Nahoru Odpovědět
22.10.2018 20:26
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Avatar
don.jarducius:22.10.2018 20:33

Sorry už blbnu ... tady je to správně ...

Nahoru Odpovědět
22.10.2018 20:33
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Avatar
don.jarducius:22.10.2018 20:37

Model menu

public class MenuModel
{
    public int ID { get; set; }
    public int Nadrazeny_ID { get; set; }
    public string Nazev { get; set; }
}

Hlavní stránka

@model int
@{Layout = ""; }
@{
    ViewData["Title"] = "Home Page";
    var menuItems = ViewData["MenuItems"] as List<MenuModel>;
}
<div class="dropdown-menu">
    <ul>
        @foreach (var hlavni in menuItems.Where(x => x.Nadrazeny_ID == Model))
        {
            <li>
                @hlavni.Nazev
                @{ await Html.RenderPartialAsync("PodPolozkaMenu", hlavni.ID, ViewData); }
            </li>
        }
    </ul>
</div>

Partial stránka pro rekurzi

@model int
@{
    var menuItems = ViewData["MenuItems"] as List<MenuModel>;
    var aktualniUrovne = menuItems.Where(x=>x.Nadrazeny_ID == Model).ToList();
}
@if (aktualniUrovne.Count > 0)
{
    <ul>
        @foreach (var uroven in menuItems.Where(x => x.Nadrazeny_ID == Model))
        {
            <li>
                @uroven.Nazev
                @{await Html.RenderPartialAsync("PodPolozkaMenu", uroven.ID, ViewData);}
            </li>
        }
    </ul>
}
Nahoru Odpovědět
22.10.2018 20:37
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Avatar
Odpovídá na Jirka
Luboš Hnědý:27.10.2018 11:59

Super tak nakonec jsem to nějak překopal a funguje díky moc. :)

 
Nahoru Odpovědět
27.10.2018 11:59
Avatar
Jirka
Člen
Avatar
Odpovídá na Luboš Hnědý
Jirka:28.10.2018 16:44

Ahoj, díky za uznání a trpělivost. Jsem rád, že Ti to pomohlo. :)

Nahoru Odpovědět
28.10.2018 16:44
Kdo nic nedělá, nic nezkazí.
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 18 zpráv z 18.