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
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.
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
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
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
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.