OleDbDataReader a jeho použití   otázka

VB.NET

Prosím o radu... mám databázi accdb, kde jsou použity datové typy integer, string a memo, kde jsem pomocí streamu a jeho konverzi na pole "byte()" uložil třeba celý pdf dokument.

Z databáze čtu data přes OleDbDataReader, pokud jde o datové typy Integer nebo String není problém, ale jak přečíst pole? Kód vypadá asi takto:

Form4.ID.Text = oleDbDataReader.GetInt32(0)
Form4.TSL.Text = oleDbDataReader.GetString(1)
Form4.RT.Rtf = oleDbDataReader.GetString(2)

Tohle funguje

Jak ale načíst obsah třeba sloupce 18 z tabulky dat do proměnné Dokument1, která je deklarována jako

Dim Dokument1 as byte()

Když totiž zadám

Dokument1 = oleDbDataReader.GetByte(18)

Tak mi to hlásí: "Value of type Byte cannot be converted to 1-dimensional Array of Byte.

Prosím poraďte, nejlépe i s ukázkou kódu

Děkuji

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Deklarujete pole bajtů (Dokument1 As Byte()), ale získáváte pouze jeden bajt z readeru: reader.GetByte(x). Potřebujete buď získat celé pole bajtů pomocí GetBytes() tak, aby seděly datové typy (pole a pole, ne pole a typ) a nebo můžete použít GetStream a číst si ze zdroje podle potřeby.

Dim length = reader.GetBytes(7, 0, Nothing, 0, 0) ' *
Dim buffer(length) As Byte
reader.GetBytes(7, 0, buffer, 0, length)
' nebo
Dim stream = reader.GetStream(7)
Using reader2 = New System.IO.StreamReader()
  MessageBox.Show(reader2.ReadToEnd())
End Using

Upozorňuji, že pokud budou data objemná, určitě se vyplatí je číst postupně a nekopírovat do bufferu vše naráz. Může to vypadat třeba takto:

Dim buffer(2048) As Byte ' 2kb buffer
Dim index = 0 ' pozice ve zdrojových datech
Dim read = reader.GetBytes(7, index, buffer, 0, buffer.Length)
While read > 0
  ' zpracování 2kb dat a pokračování na další 2kb
  ' zde lze třeba sekvenčně zapisovat do souboru a pod
  ' pokud chcete deserializovat data např. do obrázku,
  ' vyplatí se použít GetStream a přetížený konstruktor pro
  ' obrázek, jež daný stream vezme jako parametr
  index += read
  read = reader.GetBytes(7, index, buffer, 0, buffer.Length)
End While

*

http://msdn.microsoft.com/en-us/library/...

"If you pass a buffer that is null, GetBytes returns the length of the field in bytes."

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Asi si sedím na vedení, nešlo by to napsat tak, jak bych to potřeboval? Příslušná položka "memo" v tabulce databáze má index 18, Pole bajtů bych potřeboval dostat do proměnné Dokument1 ( jak jsem psal dříve, je deklarovaná jako Dim Dokument1 as Byte() ).

Co znamwená ta hodnota "7" v předchozím příkladu?

Děkuji

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Sedm je číslo sloupce, zvolil jsem jej náhodně, ale z dokumentace je vidět, že pořadí parametrů je číslo sloupce (v pořadí od nuly), index v bajtech z databáze, pole bajtů v programu, index v poli bajtů v programu a délka dat ke čtení. Problém je s tou délkou, nejdříve jí musíte zjistit tak, že místo pole dosadíte Nothing a GetBytes() pak nevrátí počet přečtených bajtů (což je výchozí stav), ale celkový počet bajtů.

http://msdn.microsoft.com/en-us/library/...

' 1. Zjistíme délku dat v DB:
Dim délka = oleDbDataReader.GetBytes(18, 0, Nothing, 0, 0)
' 2. Naalokujeme pole o té délce:
Dim Dokument1(délka) as byte
' 3. Přečteme pole bajtů z databáze do programu
oleDbDataReader.GetBytes(18, 0, Dokument1, 0, délka)
nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Princip jsem pochopil už prve, špatně jsem aplikoval Dokument1...atd.

Nicméně hned po prvním příkazu "Dim délka...." mi to hlásí chybu: č.13, Určené přetypování není platné." Nemám nejmenší tušení odkud se tato chyba generuje...

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Zkoušel jsem to i s tím bufferováním, na řádku Dim read = oleDbDataReader.GetBytes(18, index, buffer, 0, buffer.Length) mi to ohlásí stejnou chybu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nemáte v databázi null? Musíte to nejdříve ověřit, než budete nad daty provádět nějaké operace.

If Not reader.IsDBNull(18) Then
  ' ...
End If

Také, pokud budete mít třeba sloupec UserId a bude typu integer a zároveň bude moct být null (ale tohle platí obecně, nejen pro integer samozřejmě), musíte použít Nullable(Of T).

Dim value As Int32? = reader.GetInt32(18)
' Nebo value As Nullable(Of Int32)
If value.HasValue Then

Else
  MessageBox.Show("Prázdná hodnota!")
End If

Edit: A přijdejte tuto kontrolu na všechna pole, kde může být null, ne jen na to, kde Vám to teď hází chybu, jinak se může stejná věc stát později s jinou sadou dat. Dokonce ničemu neuškodí, když tuhle kontrolu provedete na úplně všech sloupcích, aplikace tak bude odolnější proti změnám v návrhu databáze (když se později někdo rozhodne, že sloupec A najednou null bude moct být).

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Tak nevím... tahle kostrukce hlásí stejnou chybu:

If Not oleDbDataReader.IsDBNull(18) Then
' 1. Zjistíme délku dat v DB:
Dim delka = oleDbDataReader.GetBytes(18, 0, Nothing, 0, 0)
' 2. Naalokujeme pole o té délce:
Dim Dokument1(delka) As Byte
' 3. Přečteme pole bajtů z databáze do programu
oleDbDataReader.GetBytes(18, 0, Dokument1, 0, delka)
Else
a = MsgBox("Hodnota je DBNull")
End If

Zhavaruje na

Dim delka = oleDbDataReader.GetBytes(18, 0, Nothing, 0, 0)

se stejnou chybovou hláškou... už opravdu nevím

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ještě upřesním, když zadám:

Dim delka = oleDbDataReader.GetDataTypeName(18)

tak to vypíše: DBTYPE_WLONGWARCHAR

je možné použít

Dim delka = oleDbDataReader.GetBytes(18, 0, Nothing, 0, 0)

nebo se musí udělat nějaké šachy s konverzemi typů...?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

CHAR v názvu typu značí, že jde o textový sloupec, ne o binární sloupec a proto předpokládám, že to půjde přečíst pomocí GetString a ani nebudete muset předem zjišťovat délku, prostě volání GetString jako jste to měl u ostatních sloupců. Nicméně textová a binární reprezentace není totéž a já se obávám, že máte Váš sloupec špatně otypovaný, pokud v něm chcete ukládat binární data. Naneštěstí se v Microsoft Access vůbec nevyznám, takže Vám nemůžu posyktnout přesné informace, ale k ukládání binárních dat by měl sloužit typ OleObject. Ten pak snad už půjde přečíst výše uvedenými postupy.

http://answers.yahoo.com/question/index?...

http://support.microsoft.com/kb/103257

Edit: Z různých online zdrojů jsem také vyčetl, že Memo typ Vám asi nedovolí více, než 255 znaků, což je další komplikace, se kterou se možná budete potýkat při použití GetString na sloupci typu Memo.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Už mi to funguje... problém byl v definici záznamu v tabulce access. Místo "MEMO" jsem musel deklarovat v access "OBJEKT OLE"...a jde to jak má.

Moc děkuji za ochotu, trpělivost, za pomoc a návod k pochopení problematiky.

Lze se na Vás případně obrátit i přímo třeba mailem, pokud budu potřebovat pomoc? Moc by mi to pomohlo :-)

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Nemusíte děkovat, od toho tu fórum je. :-) Pokud položíte dotaz zde a já na něj budu schopný odpovědět, odpovím na něj. Pokud se tak nestane, buď odpověď neznám a nebo nejsem aktuálně k dispozici. Preferujte prosím fórum jako komunikační kanál, protože informace, které tu sdílíme se můžou jistě hodit i ostatním uživatelům.

Přesto, kontakt na mě je následující: alex.clarai (na) gmail.com, nicméně jak jsem již předeslal, pokud nebudu na fóru, pravděpodobně Vám nebudu moci pomoci ani na tomto mailu. Výjimkou jsou placené konzultace a zakázkový software, ale to už je jiná pohádka.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback