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 TryKannasta 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 UsingVai 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 UsingPhysix 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.
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 Tryneau33 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 IfMOI!
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
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)?
Jos minä olisin diktaattori, kieltäisin Accessin käytön aina ja kaikkialla.
jos tarpeena on vain paikallinen kanta, on hyvänä vaihtoehtona myös SQLite etc. accessin korvikkeena.
Aihe on jo aika vanha, joten et voi enää vastata siihen.