Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: VB.NET Tietokantayhteyden hallinta

Sivun loppuun

Physix [03.07.2013 13:39:30]

#

Moi,

Olen tässä nyt tuota VB.NET opiskellut ja tehnyt sovelluksia jotka käyttävät JET 4.0 tietokantaa (Access 2000). Yhtäaikaisten käyttäjien ollessa noin 5-10, niin yhteys serverillä sijaitsevaan tietokantaan hidastuu.
.LDB tiedosto sisältää useita kertoja samoja käyttäjiä, esim.

KÄYTTÄJÄ1 ADMIN
KÄYTTÄJÄ2 ADMIN
KÄYTTÄJÄ1 ADMIN
KÄYTTÄJÄ3 ADMIN
KÄYTTÄJÄ2 ADMIN

Nyt olen siis miettinyt, että jääkö sovellukseni luomat yhteydet päälle useaan kertaan? Aloin tässä miettimään, että mikä on hyvä käytäntö käyttää yhteyttä tietokantaan.

Eli ohjelmassa valitaan tietokanta openfiledialogilla, tällöin

Määritetty "Yleiset" -moduulissa

        Public kantaPath As String
		Public Yhteys As OleDb.OleDbConnection

Kun tietokanta valitaan:

		Try
            kantaPath = OpenFileDialog1.FileName
            Dim yhteysString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & kantaPath & ";User ID=Admin;Password=;"
            Yhteys = New OleDb.OleDbConnection(Kanta)
        Catch
            MsgBox(Err.Description)
            Exit Sub
        End Try

Kannasta haetaan tavaraa formille:

		Using cmd As New OleDbCommand("SELECT * FROM EQUIPMENT WHERE ID = @ID", Yhteys)
                        Dim myParm As OleDbParameter = cmd.Parameters.Add("@ID", OleDbType.Integer)
                        myParm.Value = NodeID
                        Try
                            Yhteys.Open()
                            cmd.ExecuteNonQuery()
                            Using myReader As OleDbDataReader = cmd.ExecuteReader()
                                If myReader.Read() Then
                                    If Not IsDBNull(myReader(myReader.GetOrdinal("ITEM"))) Then
                                        txtItemName.Text = myReader.GetString(myReader.GetOrdinal("ITEM"))
                                    Else
                                        txtItemName.Text = ""
                                    End If
                                End If
                            End Using
                        Catch ex As Exception
                            MsgBox(ex.ToString)
                        Finally
                            Yhteys.Close()
                        End Try
        End Using

Vai olisko viisaampaa säilyttää connectionstringiä ja määrittää yhteys aina kun tietokantaan ollaan yhteydessä?

Public kantaPath As String
			Public yhteysString As String
kantaPath = OpenFileDialog1.FileName
yhteysString  = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & kantaPath & ";User ID=Admin;Password=;"
	Using Yhteys as New OleDbConnection = OleDbConnection(yhteysString)
		Using cmd As New OleDbCommand("SELECT * FROM EQUIPMENT WHERE ID = @ID", Yhteys)
                        Dim myParm As OleDbParameter = cmd.Parameters.Add("@ID", OleDbType.Integer)
                        myParm.Value = NodeID
                        Try
                            Yhteys.Open()
                            cmd.ExecuteNonQuery()
                        Catch ex as Exception
                            MsgBox(ex.ToString)
                        End Try
                        Using myReader As OleDbDataReader = cmd.ExecuteReader()
                                If myReader.Read() Then
                                    If Not IsDBNull(myReader(myReader.GetOrdinal("ITEM"))) Then
                                        txtItemName.Text = myReader.GetString(myReader.GetOrdinal("ITEM"))
                                    Else
                                        txtItemName.Text = ""
                                    End If
                                End If
                        End Using
        End Using
	End Using

Grez [03.07.2013 15:35:13]

#

Physix kirjoitti:

Olen tässä nyt tuota VB.NET opiskellut ja tehnyt sovelluksia jotka käyttävät JET 4.0 tietokantaa (Access 2000).

Suositus olisi, että jos yhtäaikaisia käyttäjiä on enemmän kuin 1, niin käyttäisit jotain kunnollista tietokantaa. JETiä en nykyään käyttäisi edes 1 käyttäjän softiin, mutta koskaan sen käyttäminen ei ole ollut järkevää useamman käyttäjän sovelluksissa.

VB.Netissä on paljon parempi tukikin esim. SQL Serverille kuin JETille ja tuskin kuitenkaan yli 10 gigan kantoja käytät jos kerran JET ei vielä ole solmussa, niin kustannuskin on sama.

neau33 [03.07.2013 19:41:30]

#

Moi Physix!

Nyt on niin, että access kanta voi olla käytössä vain yhdelle käyttäjälle kerrallaan. Eli jos yhdellä ohjelmalla on yhteys avoinna tietokantaan ja toinen ohjelma yrittää käyttää~muokata samaa jo avoinna olevaa tietokantaa niin systeemi jumiutuu jossain vaiheessa takuuvarmasti. Homma saadaan halutessa kuitenkin toimimaan jotakuinkin "joustavasti" esim. tsekkaamalla löytyykö samasta hakemistosta saman nimistä .ldb tai .laccdb -päätteistä (locked database) tiedostoa, kuin avattava .mdb tai .accdb tiedosto. Access (Jet engine) ei virheestä johtuen kuitenakaan välttämättä poista .ldb/.laccdb tiedostoa aina, kun tietokanta suljetaan. Tämä ongelma voidaan hoidella yrittämällä ko. lukitustiedoston poistoa virheenkäsittelyrutiinissa ennen varsinaisen tietokantatiedoston avaamista, elikäs...

kantaPath = OpenFileDialog1.FileName
Dim pos As integer = kantaPath.LastIndexOf(".")
Dim extlen As Integer = kantaPath.Length - pos
Dim ext As String = kantaPath.ToLower.Substring(pos, extlen)

Try
    Select Case ext
        Case ".mdb"
            If Dir(dbPath.ToLower.Replace(ext, ".ldb")) <> String.Empty Then
                Kill(kantaPath.ToLower.Replace(ext, ".ldb"))
            End If
        Case ".accdb"
            If Dir(dbPath.ToLower.Replace(ext, ".laccdb")) <> String.Empty Then
                Kill(kantaPath.ToLower.Replace(ext, ".laccdb"))
            End If
        Case Else
            MsgBox("Tiedosto ei ole MSACCESS tietokantatiedosto")
            Exit Sub
    End Select
Catch ex As Exception
    MsgBox("Tietokanta on jo avoinna, yritä myöhemmin uudelleen...")
    Exit Sub
End Try

Grez [03.07.2013 20:21:46]

#

neau33 kirjoitti:

Eli jos yhdellä ohjelmalla on yhteys avoinna tietokantaan ja toinen ohjelma yrittää avata samaa jo avoinna olevaa tietokantaa niin systeemi jumiutuu takuuvarmasti.

No en mä nyt sanois takuuvarmasti, on noita systeemeitä nähty missä samaa access-kantaa käytetään yhtäaikaisesti kahdelta eri koneelta. Mutta tosiaan niissä tulee helposti kikkailutarvetta, esim. voi olla että täytyy ensin käynnistää softa koneella X ja sitten vasta koneella Y. Edelleen luonnehtisin lähinnä omaan jalkaan ampumiseksi ylipäätään käyttää Access-kantaa monen yhtäaikaisen käyttäjän järjestelmässä.

Lisäys:

Sitten toinen juttu että toi koodi ei varmasti toimi .accdb -päätteisille tiedostoille:

neau33 kirjoitti:

Select Case kantaPath.ToLower.SubString(kantaPath.Length - 4), 4)
    Case ".mdb"
        Kill(kantaPath.ToLower.Replace(".mdb", ".ldb"))
    Case ".accdb"
        Kill(kantaPath.ToLower.Replace(".accdb", ".accde"))
    Case Else
        MsgBox("Tiedosto ei MSACCESS tietokantatiedosto")
        Exit Sub
End Select

Pitäisin tässä tapauksessa If Else -rakennetta tässä tapauksessa Select Case rakennetta helpompana.

If kantaPath.ToLower().EndsWith(".mdb") Then
    Kill(kantaPath.ToLower.Replace(".mdb", ".ldb"))
ElseIf kantaPath.ToLower().EndsWith(".accdb") Then
    Kill(kantaPath.ToLower.Replace(".accdb", ".accde"))
Else
    MsgBox("Tiedosto ei MSACCESS tietokantatiedosto")
    Exit Sub
End If

neau33 [03.07.2013 21:02:18]

#

MOI!

Grez kirjoitti:

...toi koodi ei varmasti toimi .accdb -päätteisille tiedostoille

no joo tuli vahingossa lähetettyä kesken editoinnin, mutta nyt toimii...

Jet UserRoster mahdollistaa myös jonkintason kikkailun

Physix [03.07.2013 22:17:25]

#

Kiitoksia vastauksista ja vinkeistä. Tuo systeemi toimii tällä hetkellä nopeasti Accessin kautta, käyttäjämäärän tosin ollessa max 10.

Ongelmaksi muodostuu, kun kaikkea tietoa kannasta ei muokata tämän sovelluksen kautta, vaan joitakin tietoja lisätään ja muokataan MS Accessin kautta.

Jos siirryn tuohon SQL Server expressiin, onnistuuko MS Accessin frontendinä käyttäminen kuinka hyvin?

Tulisiko tuota using statementiä käyttää aina kuin mahdollista? Onko tuossa yhteyden säilömisestä publicina jotain väärää (GC ei disposee sitä koskaan?), vai tulisko se aina määrittää sitä käytettäessä ja dispose ASAP (esim. using statement)?

Blaze [03.07.2013 23:34:40]

#

Jos minä olisin diktaattori, kieltäisin Accessin käytön aina ja kaikkialla.

groovyb [31.07.2013 02:59:03]

#

jos tarpeena on vain paikallinen kanta, on hyvänä vaihtoehtona myös SQLite etc. accessin korvikkeena.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta