Chci geek triko! Chci geek triko!
Extra 10 % bodů navíc a tričko zdarma při zadání kódu "TRIKO10"
Avatar
Luboš Hnědý:21. října 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. října 1:27
Avatar
vajkuba1234
Člen
Avatar
Odpovídá na Luboš Hnědý
vajkuba1234:21. října 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. října 3:48
Nahoru Odpovědět 21. října 3:47
No hope, no future, JUST WAR! For world peace Israel must be DESTROYED!
Avatar
Odpovídá na Luboš Hnědý
don.jarducius:21. října 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  +2 21. října 20:24
Avatar
Jirka
Člen
Avatar
Odpovídá na don.jarducius
Jirka:21. října 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. října 20:36
Kdo nic nedělá, nic nezkazí.
Avatar
Jirka
Člen
Avatar
Odpovídá na Jirka
Jirka:21. října 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. října 20:44
Kdo nic nedělá, nic nezkazí.
Avatar
Odpovídá na don.jarducius
Luboš Hnědý:22. října 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. října 8:56
 
Nahoru Odpovědět 22. října 8:56
Avatar
Odpovídá na Luboš Hnědý
don.jarducius:22. října 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. října 9:28
Avatar
Jirka
Člen
Avatar
Odpovídá na Luboš Hnědý
Jirka:22. října 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. října 12:20
Nahoru Odpovědět 22. října 12:18
Kdo nic nedělá, nic nezkazí.
Avatar
Odpovídá na Jirka
Luboš Hnědý:22. října 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. října 12:35
Avatar
Jirka
Člen
Avatar
Odpovídá na Luboš Hnědý
Jirka:22. října 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. října 13:38
Kdo nic nedělá, nic nezkazí.
Avatar
Jirka
Člen
Avatar
Odpovídá na Luboš Hnědý
Jirka:22. října 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í
+1 bodů
Řešení problému
Nahoru Odpovědět 22. října 15:07
Kdo nic nedělá, nic nezkazí.
Avatar
Jirka
Člen
Avatar
Odpovídá na Luboš Hnědý
Jirka:22. října 15:25

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

Nahoru Odpovědět 22. října 15:25
Kdo nic nedělá, nic nezkazí.
Avatar
Marek Kočí
Redaktor
Avatar
Marek Kočí:22. října 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. října 15:46
 
Nahoru Odpovědět  +1 22. října 15:44
Avatar
don.jarducius:22. října 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. října 20:26
Avatar
don.jarducius:22. října 20:33

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

 
Nahoru Odpovědět 22. října 20:33
Avatar
don.jarducius:22. října 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. října 20:37
Avatar
Odpovídá na Jirka
Luboš Hnědý:27. října 11:59

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

 
Nahoru Odpovědět 27. října 11:59
Avatar
Jirka
Člen
Avatar
Odpovídá na Luboš Hnědý
Jirka:28. října 16:44

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

Nahoru Odpovědět 28. října 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.