Close
Duke shfaqur rezultatin -19 deri 0 prej 1
  1. #1
    i/e regjistruar Maska e Borix
    Anėtarėsuar
    17-01-2003
    Postime
    2,316

    Post VB - Shtimi dhe Nxjerrja e Objekteve BLOB nga Databaza

    Shtimi dhe Nxjerrja e Objekteve BLOB nga Databaza

    "Si mund te ruaj nje foto (imazh) ose nje artikull te madh ne databaze dhe si ta mundesoj nxjerrjen (leximin) e saj nga databaza ne programin tim?" eshte nje pyetje qe behet shpesh edhe nga programues me nje eksperience jo fare te shkurter, per arsye se jo shpesh hasen specifikime te tilla nga pjesa me e madhe e perdorueseve te ardhshem te sistemit.

    Fare thjesht, mendimi i pare qe te vjen ndermend, eshte te ruash vetem adresen e objektit (fotos ose artikullit) ne nje kolone te tabeles perkatese. (Me 'adrese' nenkuptojme vendndodhjen fizike, duke perfshire edhe shtegun ne nje kompjuter). Megjithate, ky trajtim ka pasojat e veta. Se pari, nese vendndodhja e objektit ndryshon (pra, objekti fshihet, levizet ne nje vend tjeter), atehere adresa e ruajtur ne databaze nuk mund te azhurnohet automatikisht. Kjo do te thote se, per nje numer te madh rekordesh, adresat perkatese te objekteve te tyre humbasin 'koherencen' me vete objektet, duke sjelle nje humbje te kontrollit te programit (pra, te perdoruesit) mbi keto objekte. Se dyti, nese programi mundeson ruajtjen e objekteve ne te njejtin server ku gjendet databaza, atehere per cdo objekt te ri duhet mundesuar edhe kopjimi (ose levizja) automatike ne server. Kjo mund te kete pasoja te paparashikueshme.

    Zgjidhja tjeter ka te beje me transferimin e objektit (permbajtjen e tij) nga vendndodhja fizike e dhene ne fushen e tabeles perkatese ne databaze. Ne kete artikull do te paraqes disa koncepte kryesore, ndonje leksion nga eksperienca ime, si dhe kodin (VB6/ADO2.6) per procedurat per shtimin/nxjerrjen e objekteve "te medha" nga databaza. (Kodi eshte bazuar plotesisht ne artikullin e MS Knowledge Base http://support.microsoft.com/kb/194975, por me modifikime te pershtatura. Te njejtat procedura per VB.NET/ADO.NET mund t'i gjeni ne http://support.microsoft.com/kb/317034/EN-US/.) Per thjeshtesi, do t'i referohemi emrave te tipeve te perdorura nga SQL 2000/.NET.


    C'eshte tipi BLOB?

    BLOB eshte akronimi i Binary Large OBjects, perkthyer Objekte te Medha Binare, i cili identifikon imazhet dhe sasite e medha te karaktereve te nderlidhura. Ne gjuhen e databazes, tipet e kolonave te nje tabele te identifikuara si IMAGE, TEXT dhe NTEXT nenkuptojne objekte BLOB. (Fusha NTEXT perdoret per karaktere UNICODE. Diskutimi per UNICODE bie jashte sferes se ketij artikulli; per me teper mund te lexoni ne shqip kete artikull.)

    Active Data Objects (ADO)

    ADO eshte objekti qe mundeson lidhjen me databazen (fale objektit Connection), nxjerrjen e nje bashkesie rekordesh (fale objektit Command), manipulim i ketyre rekordeve (fale objektit RecordSet). Me pak fjale, ADO mundeson te katerta veprimet e mundshme mbi nje databaze: SELECT (nxjerrja e rekordeve), INSERT (shtimi i rekordeve), DELETE (fshirja e rekordeve), dhe UPDATE (azhurnimi i rekordeve).

    Nga kendveshtrimi hierarkik, objekti RecordSet permban nje koleksion objektesh te tipit Field, pra, te gjitha fushat e rekordeve te zgjedhura. Me ane te ketij objekti, ne mund te lexojme, nder te tjera, emrin dhe vleren e cdo fushe te cdo rekordi te nxjerre nga databaza. Tre nga metodat kryesore te objektit Field qe nevojiten per qellimin e ketij artikulli jane AppendChunk(), GetChunk(), dhe Update(). (Perkthyer ne menyre literale, fjala 'chunk' do te thote 'llokėm' (si ne 'llokem mishi') ose 'copė'.) Metodat AppendChunk() dhe GetChunk() marrin si parameter gjatesine (ne bajte) te "llokmes" se te dhenave qe do te shtohen/nxirren ne fushen e dhene. Keto procedura kerkojne madhesine e fushes, e cila mund te merret fale vecorise ActualSize te objektit Field. Ndersa, metoda e paparametrizuar Update azhurnon te dhenat e nje fushe te caktuar. Sic vetekuptohet, dy metodat e para do te perdoren per shtimin/nxjerrjen e objekteve BLOB nga databaza.


    Shtimi i te Dhenave BLOB


    Para se nje objekt BLOB te shtohet ne databaze, duhet qe objekti te ruhet ne forme fizike ne nje disk. Pra, supozohet qe te dhenat te ekzistojne fizikisht. Pershembull, nje foto e sapo-skanuar ka emrin borix.jpg dhe eshte ruajtur ne direktorine C:\. (Ia vlen te permendet fakti se ekstensioni i skedarit te tipit imazh nuk ka rendesi per procedurat e leximit te bajteve ne te. Pra, 'borix.jpg' mundet fare mire te jepet si 'borix.tmp' ose vetem 'borix'. Ne cdo rast, bajtet ekzistojne te mbeshtjella ne objekt, per sa kohe qe nuk ka pesuar ndonje nderhyrje manuale.)

    Meqenese cdo informacion ne kompjuter ruhet ne forme dysore (binare), metodat AppendChunk dhe GetChunk kerkojne si parameter nje bllok te caktuar bajtesh (ose 8 bitesh). Artikulli nga Knowledge Base rekomandon nje madhesi prej dy ne fuqi te katermbedhjete (2^14) ose 16384 bajtesh. (Na nevojitet njesia bajt, sepse imazhi lexohet me kete njesi.)

    Kodi i meposhtem paraqet nje procedure File2BLOB(), me keto parametra:
    FName - shtegu dhe emri i skedarit (psh.: C:\borix.tmp)
    fld - reference e objektit Field, pra fusha ku do te shtohet BLOB-i.
    Threshold - kufiri i madhesise se skedarit. Nese skedari ka nje madhesi me te vogel se sa kjo vlere konstante, atehere te dhenat BLOB mund te shtohen direkt ne fushe, pa patur nevoje te therritet metoda AppendChunk.

    Kodi:
    ' Deklarime te pergjithshme:
    Global Const BLOCK_SIZE = 16384   ' 2^14 bajte
    Kodi:
    Public Sub File2Blob(ByVal FName As String, fld As ADODB.Field, _
                   Optional Threshold As Long = 1048576)
    
    ' Supozime: Skedari ekziston. Me kete procedure do te azhurnohet (UPDATE) fusha.
    ' Madhesia eshte jo me e madhe se 2 Gb.
    
       On Error GoTo err_log
    
       Dim f As Long, Data() As Byte, FileSize As Long
       f = FreeFile
       
       Open FName For Binary As #f
       
       FileSize = LOF(f) ' length of file - percakton madhesine
       
       Select Case fld.Type
         Case adLongVarBinary ' nese eshte imazh (foto)
           If FileSize > Threshold Then
             ' Skedari eshte me i madh se vlera kufizuese Threshold,
             ' prandaj duhet thirrur metoda AppendChunk, e cila gjendet
             ' ne proceduren Read2Binary():
             Call Read2Binary (f, fld, FileSize)
           Else
             ' madhesia e skedarit eshte e pranueshme, prandaj
             ' te dhenat BLOB te shtohen drejtperdrejt ne fushen fld
             Data = InputB(FileSize, f) ' InputB nenkupton Input Bajte
             fld.value = Data ' Data eshte nje vektor bajtesh (shih deklarimin)
           End If
         Case adLongVarChar, adLongVarWChar ' nese eshte TEXT, NTEXT
           If FileSize > Threshold Then
             ' Kemi te bejme me karaktere TEXT/NTEXT, prandaj
             ' therritet procedura Read2Text, e cila permban metoden
             ' AppendChunk
             Call Read2Text (f, fld, FileSize)
           Else
             fld.value = Input(FileSize, f)
           End If
       End Select
       
       Close #f
       
       Exit Sub
    
    err_log:
       MsgBox "Gabim ne ruajtjen e te dhenave.", vbOKOnly + vbInformation, App.Title
         
    End Sub
    
    Public Sub Read2Binary(ByVal f As Long, fld As ADODB.Field, _
                     ByVal FileSize As Long)
    ' Procedure per te shtuar nje objekt BLOB te tipit IMAGE   
    
       Dim Data() As Byte, BytesRead As Long
       
       Do While FileSize <> BytesRead
         If FileSize - BytesRead < BLOCK_SIZE Then
           Data = InputB(FileSize - BytesRead, f)
           BytesRead = FileSize
         Else
           Data = InputB(BLOCK_SIZE, f)
           BytesRead = BytesRead + BLOCK_SIZE
         End If
     
         ' Shto "llokmat" e imazhit per sa kohe qe
         ' bajtet e lexuara (BytesRead) jane me te vogla
         ' se madhesia e skedarit.
         Call fld.AppendChunk(Data)
         
       Loop
       
    End Sub
    
    Public Sub Read2Text(ByVal f As Long, fld As ADODB.Field, _
                   ByVal FileSize As Long)
    ' Procedure per te shtuar nje objekt BLOB te tipit TEXT/NTEXT
       
       Dim Data As String, CharsRead As Long
       
       Do While FileSize <> CharsRead
         If FileSize - CharsRead < BLOCK_SIZE Then
           Data = Input(FileSize - CharsRead, f)
           CharsRead = FileSize
         Else
           Data = Input(BLOCK_SIZE, f)
           CharsRead = CharsRead + BLOCK_SIZE
         End If
         
         ' Shto "llokmat" e te dhenave per sa kohe qe
         ' karakteret e lexuara (CharsRead) jane me te vogla
         ' se madhesia e skedarit.
         Call fld.AppendChunk(Data)
         
       Loop
       
    End Sub

    Nxjerrja (Leximi) e te Dhenave BLOB

    Kjo procedure eshte pothuaj e anasjellta e procedures se mesiperme. Me pak fjale, dhene nje fushe qe permban te dhena BLOB, keto te transferohen ne nje skedar ne nje shteg te dhene. Skedari krijohet automatikisht, pra, supozohet qe nuk ekziston.

    Funksioni BLOB2File transferon informacionin e nje fushe te referuar ne nje skedar ne shteg fizik fale metodes GetChunk(). Ne artikullin perkates tek MS Knowledge Base, BLOB2File eshte dhene si nje procedure SUB. Megjithate, nisur nga disa probleme hasa gjate implementimit, e konvertova ne nje funksion qe kthen nje velre Byte. Funksioni kthen vleren 1 nese objekti BLOB u transferua me sukses ne skedar, dhe vleren 100 nese ndodhi ndonje gabim gjate rruges. Parametrat e funksionit jane:
    fld - fusha qe i referohet objektit te paracaktuar Field
    FileName - shtegu dhe emri i skedarit ku do te ruhen te dhenat BLOB
    FieldSize - madhesia e fushes qe mund te jepet me ane te vecorise ActualSize. Dhenia e vleres se ketij parametri ne menyre eksplicite eshet fakultative, pasi funksioni ne fjale therret nje procedure te vecante kur madhesia e fushes nuk dihet.
    Threshold - i njejti variabel si ne proceduren File2BLOB

    Kodi:
    Public Function Blob2File(fld As ADODB.Field, ByVal FName As String, _
                   Optional FieldSize As Long = -1, _
                   Optional Threshold As Long = 1048576) As Byte
    
       ' Supozime: Skedari fizik nuk ekziston. 
       ' Madhesia e objektit eshte jo me e madhe se 2 Gb.
       ' Kthen vleren 1 nese nxjerrja e objektit BLOB kaloi me sukses
    
       Dim f As Long, bData() As Byte, sData As String
    
       On Error GoTo err_log
       
       f = FreeFile
       
       Open FName For Binary As #f
       
       Select Case fld.Type
         Case adLongVarBinary  ' konstantja qe identifikon tipin IMAGE
           If FieldSize = -1 Then   ' madhesia e fushes nuk eshte dhene/nuk njihet
             Call WriteFromUnsizedBinary(f, fld)
           Else                     ' madhesia eshte dhene me ane te ActualSize
             If FieldSize > Threshold Then   ' madhesia ka kaluar kufirin
               Call WriteFromBinary (f, fld, FieldSize)
             Else                            ' te dhena BLOB te vogla
               bData = fld.value
               Put #f, , bData  ' mbingarkese po te perdoret fld.Value ne vend te bData
             End If
           End If
         Case adLongVarChar, adLongVarWChar ' tipet TEXT, NTEXT
           If FieldSize = -1 Then
             Call WriteFromUnsizedText(f, fld)
           Else
             If FieldSize > Threshold Then
               Call WriteFromText(f, fld, FieldSize)
             Else
               sData = fld.value
               Put #f, , sData  ' mbingarkese po te perdoret fld.Value ne vend te sData
             End If
           End If
       End Select
       
       Close #f
       Blob2File = 1 ' sukses
       
       Exit Function
       
    err_log:
       MsgBox "Gabim ne leximin e plote te te dhenave.", vbOKOnly + vbInformation, App.Title
       Close #f
       Blob2File = 100 ' gabim
       
    End Function
    
    Public Sub WriteFromBinary(ByVal f As Long, fld As ADODB.Field, _
                        ByVal FieldSize As Long)
       
       Dim Data() As Byte, BytesRead As Long
       
       Do While FieldSize <> BytesRead
         If FieldSize - BytesRead < BLOCK_SIZE Then
           Data = fld.GetChunk(FieldSize - BLOCK_SIZE)
           BytesRead = FieldSize
         Else
           Data = fld.GetChunk(BLOCK_SIZE)
           BytesRead = BytesRead + BLOCK_SIZE
         End If
         
         Put #f, , Data
       Loop
       
    End Sub
    
    Public Sub WriteFromUnsizedBinary(ByVal f As Long, fld As ADODB.Field)
       Dim Data() As Byte, Temp As Variant
       
       Do
          Temp = fld.GetChunk(BLOCK_SIZE)
          If IsNull(Temp) Then Exit Do
          Data = Temp
          Put #f, , Data
       Loop While LenB(Temp) = BLOCK_SIZE
       
    End Sub
    
    Public Sub WriteFromText(ByVal f As Long, fld As ADODB.Field, _
                      ByVal FieldSize As Long)
       
       Dim Data As String, CharsRead As Long
       
       Do While FieldSize <> CharsRead
          If FieldSize - CharsRead < BLOCK_SIZE Then
             Data = fld.GetChunk(FieldSize - BLOCK_SIZE)
             CharsRead = FieldSize
          Else
             Data = fld.GetChunk(BLOCK_SIZE)
             CharsRead = CharsRead + BLOCK_SIZE
          End If
         
          Put #f, , Data
         
       Loop
       
    End Sub
    
    Public Sub WriteFromUnsizedText(ByVal f As Long, fld As ADODB.Field)
       
       Dim Data As String, Temp As Variant
       
       Do
         Temp = fld.GetChunk(BLOCK_SIZE)
         If IsNull(Temp) Then Exit Do
         Data = Temp
         Put #f, , Data
       Loop While Len(Temp) = BLOCK_SIZE
       
    End Sub

    Disa Vrojtime Perfundimtare


    Konstantet adLongVarBinary, adLongVarChar, dhe adLongVarWChar jane konstante te percaktuara ne ADO per tipet IMAGE, TEXT, dhe NTEXT, perkatesisht. (Germa 'W' ne ADO nenkupton UNICODE, ashtu si germa 'N' ne SQL). Per tipet IMAGE, vecojme perdorimin e funksionit InputB(), i cili perdoret per te lexuar bajte nga nje skedar i dhene. Gjithashtu, procedura Put() shkruan te dhena ne nje skedar te caktuar. Ne rastin e nje objekti BLOB te tipit IMAGE, ne proceduren Put perdoret nje vektor bajtesh, jo drejtperdrejt vlera e fushes, pasi shkakton nje mbingarkese te konsiderueshme gjate shkrimit te te dhenave.

    Duhet bere kujdes me perdorimin e vecorise ActualSize te objektit Field kur tentohet te jepet madhesia e nje fushe BLOB ne rastin kur kolona perfaqesuese eshte e tipit TEXT dhe NTEXT. Ne rastin e tipit TEXT, nje karakter ruhet me nje bajt njesi. Ne rastin NTEXT, karakteri ruhet me dy bajte. Per kete arsye, zhvilluesi duhet te gjykoje nese parametri i madhesise duhet te jepet si ActualSize apo si ActualSize/2. Nese nuk behet kujdes, gabimi qe lind thote se "llokma" qe po kerkohet te lexohet eshte e pavlefshme ose e pacaktuar (NULL).

    Megjithese kodi i mesiperm kryen punen sakte dhe shpejt, inkorporimi i tij ne pjesen tjeter te sistemit qe po zhvillohet shkakton nje rritje ne shkallen e veshtiresise. Per shembull, supozojme se ne nje tabele te dhene ekziston nje number i caktuar fushash jo BLOB, dhe dy fusha te tjera BLOB te tipeve IMAGE dhe/ose TEXT/NTEXT. Supozojme gjithashtu se ne zhvilluesi ka shkruar nje Stored Procedure qe pranon n+2 parametra me mendimin se do t'i jape procedures te gjitha vlerat e parametrave pernjeheresh. Kjo do te shkaktoje problem, sepse nuk ekziston ndonje menyre e tille; objektet BLOB duhet te kalohen drejtperdrejt nga objekti Field me ane te metodes Update. Pra, procedura SQL duhet modifikuar qe te pranoje te gjithe parametrat e jo BLOB. Fillimisht shtohen vlerat e n parametrave. Me tej, krijohet nje objekt i ri RecordSet, i cili permban vetem rekordin e sapo-shtuar. Me RecordSet-in e ri, identifikojme te dy fushat BLOB dhe ia kalojme procedures File2BLOB. Pasi kjo procedure mbaron me sukses, therrasim metoden Update te fushes perkatese dhe informacioni BLOB shtohet eventualisht. Ketu mund te linde ndonje mbingarkese, sepse databaza "shqetesohet" dy here pa nderprerje. Gjithesesi, bazuar edhe mbi eksperiencen time, kjo procedure eshte nga me te suksesshmet qe ekziston.

    Sigurisht, cdo sugjerim ne kod dhe ide eshte i mirepritur.
    Ndryshuar pėr herė tė fundit nga Borix : 28-06-2007 mė 09:58
    "The rule is perfect: in all matters of opinion our adversaries are insane." (M. Twain)

Tema tė Ngjashme

  1. 2 muaj para zgjedhjeve
    Nga Alienated nė forumin Bashkėpatriotėt e mi nė botė
    Pėrgjigje: 41
    Postimi i Fundit: 18-02-2009, 07:16

Regullat e Postimit

  • Ju nuk mund tė hapni tema tė reja.
  • Ju nuk mund tė postoni nė tema.
  • Ju nuk mund tė bashkėngjitni skedarė.
  • Ju nuk mund tė ndryshoni postimet tuaja.
  •