Diskuze: Výpis podkategorií
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 18 zpráv z 18.
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
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?
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.
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 ).
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;
}
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
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.
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.
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?
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.
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.
Ještě tu jsem s návrhem (diagramem) hierarchii podporující tabulkou, podobnou, jako těžím dotazem.
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.
Ok... co takhle… viz. obrázek. Rekurzi na úrovni SQL nedělej, udělej ji až při vykreslení.
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>
}
Super tak nakonec jsem to nějak překopal a funguje díky moc.
Ahoj, díky za uznání a trpělivost. Jsem rád, že Ti to pomohlo.
Zobrazeno 18 zpráv z 18.