Geek tričko zdarma Geek tričko zdarma
Tričko zdarma! Stačí před dobitím bodů použít kód TRIKO15. Více informací zde

Diskuze: SqlDataReader a dva SELECTy

Aktivity (4)
Avatar
Veronika Kotrcová:30.9.2018 17:19

Ahoj,

nejde mi vytvořit SqlDataReader, který by vrátil metodou Read() výsledek prvního SELECTu a tento výsledek použít pro druhý SELECT. Potřebovala bych poradit jakým způsobem uložit výsledek prvního SELECTu do proměnné, kterou bych mohla použít jako podmínku pro druhý SELECT.
Předem moc děkuji za radu. Určitě tam mám začátečnické chyby.

Zkusil jsem: Zkoušela jsem vnořit druhý SELECT do metody Read() prvního SELECTu, ale dočetla jsem se, že musí být metoda Read() ukončena, aby se mohla spustit nová.

Chci docílit: První SELECT by měl najít ID nadřazeného požadavku a metodou Read() uložit do proměnné parentTicketId. (Uložení do proměnné je hlavní problém.). Následuje podmínka, která se vykoná, pokud proměnná parentTickedId není nulová. Pokud není nulová, spustí se druhý SELECT, který vyhledá všechny otevřené požadavky, které jsou zároveň podřazené požadavku z prvního SELECTu. Atd...

                        int parentTicketId; // Deklarace proměnné pro id nadřazeného ticketu.

                        // Načtení dat (id nadřazeného požadavku).
                        using (SqlCommand Cmd = new SqlCommand(@"SELECT BeginHdTicketId
                        FROM TicketRelation TR JOIN tHdTicket T ON T.iHdTicketId = TR.BeginHdTicketId
                        WHERE TR.EndHdTicketId = @iHdTicketId AND TR.TicketRelationTypeId = 2 AND T.dHdTicketResolved IS NULL", con, trans))
                        {
                            Cmd.Parameters.Add("@iHdTicketId", SqlDbType.Int).Value = ticketId;
                            using (SqlDataReader reader = Cmd.ExecuteReader())
                            {
                                if (reader.Read())
                                {
                                    parentTicketId = int.Parse((reader["BeginHdTicketId"]).ToString());
                                }
                                reader.Close();
                            }
                        }
                        if (parentTicketId != null)
                        {
                                // Načtení dat (všechny otevřené podřazené požadavky nadřazeného požadavku z předchozího dotazu).
                                using (SqlCommand Cmd = new SqlCommand(@"SELECT EndHdTicketId
                                FROM TicketRelation TR JOIN tHdTicket T ON T.iHdTicketId = TR.EndHdTicketId
                                WHERE TR.BeginHdTicketId = @iHdTicketId AND TR.TicketRelationTypeId = 2 AND T.dHdTicketResolved IS NULL", con, trans))
                                                        {
                                Cmd.Parameters.Add("@iHdTicketId", SqlDbType.Int).Value = parentTicketId;
                                using (SqlDataReader reader = Cmd.ExecuteReader())
...
 
Odpovědět 30.9.2018 17:19
Avatar
Jirka
Člen
Avatar
Jirka:30.9.2018 17:50

Ahoj,
já raději odladím SQL kód v manageru, třeba jako testovací uloženou proceduru, kterou bych si tam spouštěl. Určitě by se ten kód zjednodušil a ve výsledku asi i zrychlil.

Nahoru Odpovědět  +1 30.9.2018 17:50
Kdo nic nedělá, nic nezkazí.
Avatar
Jirka
Člen
Avatar
Odpovídá na Veronika Kotrcová
Jirka:30.9.2018 19:38

Nevím, jaké je zadání, ale řekl bych, že ten vnořený select má být přímo součástí prvního selectu, takže výsledkem by mohl být z pohledu C# jediný SQL-příkaz, třeba takto:

SELECT EndHdTicketId
FROM TicketRelation TR
JOIN tHdTicket T ON T.iHdTicketId = TR.EndHdTicketId
WHERE TR.TicketRelationTypeId = 2
AND T.dHdTicketResolved IS NULL
AND  TR.BeginHdTicketId =
(
SELECT BeginHdTicketId
FROM TicketRelation TR
JOIN tHdTicket T ON T.iHdTicketId = TR.BeginHdTicketId
WHERE TR.TicketRelationTypeId = 2
AND T.dHdTicketResolved IS NULL
AND TR.EndHdTicketId = @iHdTicketId
);

A doporučuju zkusit ten SQL Manager :)

Editováno 30.9.2018 19:40
Nahoru Odpovědět 30.9.2018 19:38
Kdo nic nedělá, nic nezkazí.
Avatar
TomášT
Člen
Avatar
TomášT:30.9.2018 19:42

Napsat SQL příkaz takhle natvrdo rovnou do inicializace commandu je docela drsné, ale když ti to vyhovuje...

Ale k problému:

  • SQL příkaz zkopíruj do SQL Managera, předřaď mu DECLARE @iHdTicketId int =...; a vyzkoušej, zda to vrací to, co si představuješ.
  • pokud ano, hoď si na using breakpoint a následný kód si prokrokuj a najdi, kde se tvoje představa o správném fungování rozejde se skutečností.

Jinak jsem přesvědčený, že pokud nepotřebuješ parentTicketId k nějakým dalším věcem v kódu, tak by z těch dvou volání SQL šlo udělat jediné vracející rovnou cílový seznam.

 
Nahoru Odpovědět 30.9.2018 19:42
Avatar
Odpovídá na Veronika Kotrcová
don.jarducius:30.9.2018 19:42

Ahoj, nevím přesně kde má být chyba...
Znamená to, že ti první select nevrátí hodnotu, nebo že ti proběhne druhý select špatně a nevloží se ti správně hodnota z prvního selectu?

Nehlási ti náhodou překladač chybu na řádku

if (parentTicketId != null)

???

Máš tam totiž neinicializovanou proměnou typu int, která musí mít vždy hodnotu. Změň si deklaraci z

int parentTicketId;
 na
int? parentTicketId = null;

nebo
int parentTicketId = 0;
// a pak testuj jestli je != 0 namísto null

Typ int (Int32) je totiž non nullable typ, tzn. že musí mít hodnotu. Typ int? - ten otazník je důležitý,obalí typ a přidá možnost mít null u non nullable typů... vnitřní struktura je pak trochu odlišná, přidá vlastnost HasValue (má/nemá hodnotu) a Value - Value je pak hodnota původního typu, v tomto případě int (při pokusu o přístup k hodnotě, která je null, vyhodí exception)

 
Nahoru Odpovědět 30.9.2018 19:42
Avatar
Veronika Kotrcová:1.10.2018 20:59

Dekuji vsem za rady. Jednotlive selecty mam otestovane a vraci, co maji. Jen mi to nejde spojit, tj. vysledek prvniho vlozit do podminky druheho. Urcite zitra vyzkousim upravit deklaraci promenne a priradit ji hodnotu 0. Pokud to nepomuze, zamyslim se nad spojenim obou selectu. Jinak to asi nepujde... Dam vam vedet, jak to dopadlo. A jeste jednou dekuji za ochotu.

 
Nahoru Odpovědět 1.10.2018 20:59
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 6 zpráv z 6.