Avatar billede sune56 Nybegynder
11. november 2008 - 23:36 Der er 36 kommentarer og
1 løsning

Concurrency-fejl når jeg tilgår Access database

Hej eksperter...

Jeg er en nybegynder i programmering, og for at lære at programmere i C#, er jeg ved at udvikle et program til at lave vagtplaner og optælling af timer for medarbejdere.

I den første fase af udviklingen, benyttede jeg en SQL Server 2005 til at gemme og hente oplysninger om bl.a. medarbejdere og medarbejderes timer. Jeg opererede med 6 forskellige database-tables, og 8 forskellige datasets med udtræk heraf.

Jeg besluttede mig for at gå over til at bruge en Access fil som database i stedet (ikke af driftsmæssige årsager) og så opstod en række problemer. Det største problem lige nu er, at jeg bliver tæppebombet med concurrency-fejl; ved operationer hvor jeg tilgår databasen og vil opdatere en række, får jeg smidt en concurrency violation (updated 0 out of expected 1 rows) i hovedet, og under NOGLE operationer hvor jeg vil oprette en ny række, bliver jeg mødt med en OleDbException fordi at jeg prøver at oprette duplicate values af min primary id kolonne.

Jeg har prøvet en række forskellige ting for at få koden til at virke på baggrund af de løsninger jeg har kunne læse på engelsk-sprogede fora:

- sat datasettenes id-kolonnes properties "AutoIncrementSeed" og "AutoIncrementStep" til 0 hhv. 1, 1 hhv 1 samt sat begge til negative værdier

- skiftet Id-kolonner i alle tables i Access-databasen til number (altså IKKE autogenererede numre)

Sidstnævnte gjorde at jeg kunne oprette NOGLE rækker i NOGLE Datasets (og opdatere dem til databasen) men jeg bliver stadigvæk mødt af mange exceptions...

Mit spørgsmål er nu:

Er der ikke en måde at få Access til at opføre sig lidt mere modent og være lidt SQL Server 2005- agtig?

Programmet er ikke tiltænkt at skulle tilgåes af mere end en bruger, men jeg er ikke interesserede i at have en Id-kolonne med der tillader duplikerede værdier...

Al hjælp vil være påskønnet... Venlig hilsen Sune
Avatar billede aaberg Nybegynder
12. november 2008 - 08:49 #1
For at være helt ærlig, lyder det mere som om det er noget i din kode som giver problemer, fremfor Access databasen. Kan vi eventuelt se lidt af den kode som skriver til databasen?
Avatar billede sune56 Nybegynder
12. november 2008 - 22:16 #2
Jo selvfølgelig... Men jeg har svært ved at se at det skulle være min kode der er årsag til problemet, da den fungerede fint med med SQL Server 2005...

Her opretter jeg en ny række i et database-table:

DageOpgoerelser.DageOpgoerelserRow ny = dageOpgoerelser._DageOpgoerelser.NewDageOpgoerelserRow();
                        //ny["Id"] = (object)++IdIDataSet;
                        ny.Dato = DateTime.Parse(dage[opdaterAlleDage] + " " + "00:00");
                        ny.MedarbejderId = PersonId[medarbejderCounter];
                        ny.AntalPlanlagteTimer = (decimal)dagsOpgoerelser[opdaterAlleDage];
                        ny.AntalPlanlagteTTAA = (decimal)TTAAdaogsopgoerelse[opdaterAlleDage];
                        ny.PlanlagtStart = DateTime.Parse(dage[opdaterAlleDage] + " " +
                                vagtUgeDataGridView.Rows[navneRaekke].Cells[gridOps.FindKolonneNrUdfraDato(dage[opdaterAlleDage], 2, 12, 2) - 1].Value.ToString());
                        ny.PlanlagtSlut = DateTime.Parse(dage[opdaterAlleDage] + " " +
                                vagtUgeDataGridView.Rows[navneRaekke].Cells[gridOps.FindKolonneNrUdfraDato(dage[opdaterAlleDage], 2, 12, 2)].Value.ToString());
                        dageOpgoerelser._DageOpgoerelser.Rows.Add(ny);

Her opdaterer jeg til databasen: (jeg får en exception ved update-kaldet)



dageOpgoerelserTableAdapter.Update(dageOpgoerelser._DageOpgoerelser);
dageOpgoerelser.AcceptChanges();

Venlig hilsen Sune
Avatar billede sune56 Nybegynder
12. november 2008 - 22:17 #3
Kommentaren //ny["Id"] = ....

er en gammel hænger fra som jeg ikke har fået slettet... Det er som sagt en kommentar
Avatar billede aaberg Nybegynder
13. november 2008 - 12:26 #4
Har du sat primærnøgler i Access databasen? Der bliver nød til at være primærnøgler på Access, for at man kan bruge en tableadapter til opdatering.

Hvis det ikke er det som er problemet, kan du da poste hele fejlmeddelelsen?
Avatar billede sune56 Nybegynder
13. november 2008 - 21:24 #5
Hej aaberg..

Jeg har sat primærnøgler på alle tables i min database.

Fejlen jeg får ved updates af databasen er:

DBConcurrencyException:
Concurrency violation: the UpdateCommand affected 0 of the expected 1 records.

Jeg har fundet en løsning som virker nogenlunde, og det er at kalde en .Clear() på datasettet efter hver update, og så fylde det igen, men jeg frygter at det vil blive meget ressourcekrævende når antallet af rækker i nogle af tables f.eks. runder de 10.000.

Et andet problem jeg er stødt på, er at Access har ændret Id-kolonnen i nogle af mine datasets´ AutoNumber indstilling, til at generere random-værdier. Jeg kan ikke ændre det tilbage igen, da "random-valued AutoNumber fields ikke kan ændres til incremental AutoNumber fields"

Venlig hilsen Sune
Avatar billede aaberg Nybegynder
13. november 2008 - 22:51 #6
Jeg må indrømme at jeg ikke har hørt om sådan et problem før! Det virker lidt som en bug i TableAdapter klassen. Hvis du får performanceproblemer med mange rækker, kan du overveje og droppe brugen af TableAdapter, og arbejde direkte med ADO.NET klasserne. Her er et eksempel:



OleDbConnection connection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\temp\\db1.mdb;User Id=admin;Password=;");
OleDbCommand selectCommand = connection.CreateCommand();

selectCommand.CommandText = "select * from sheet1";
OleDbDataAdapter adapter = new OleDbDataAdapter(selectCommand);

OleDbCommandBuilder cmdBuilder = new OleDbCommandBuilder(adapter);
cmdBuilder.GetInsertCommand();

adapter.Update(theDS.Sheet1);


I eksemplet er theDS mit dataset. sheet1 er tabellen i databasen jeg inserter i. Jeg testede med at inserte 10000 rækker i en tabel, og det tog 7 sekunder. Alternativt kan det gøres uden at bruge dataadapteren. Nedenstående ekstempel insertede 10000 rækker på 3,5 sekunder:

OleDbConnection connection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\temp\\db1.mdb;User Id=admin;Password=;");
OleDbCommand command = connection.CreateCommand();

command.CommandText = "insert into sheet1(id, name) values(@id, @name)";

OleDbParameter idParam = new OleDbParameter("@id", OleDbType.Integer);
OleDbParameter nameParam = new OleDbParameter("@name", OleDbType.WChar, 255);

command.Parameters.Add(idParam);
command.Parameters.Add(nameParam);

try
{
    connection.Open();
    command.Transaction = connection.BeginTransaction();

    foreach (TestDataSet.Sheet1Row row in theDS.Sheet1.Rows)
    {
        idParam.Value = row.id;
        nameParam.Value = row.name;

        command.ExecuteNonQuery();
    }

    command.Transaction.Commit()
}
finally
{
    connection.Close();
    connection.Dispose();
}

Access er uanset en super langsom database. Jeg prøvede at køre samme eksempel imod en SQLite database, som er en filbaseret database ligesom Access. Denne tog 300 millisekunder. Samme eksempel, bare med en million rækker, tog 10 sekunder i SQLite. Jeg tør slet ikke køre dette eksempel imod Access, da det sikkert kommer til at tage mere end 20 minutter, hvis det overhovedet kan lade sig gøre.

Hvis du er interesseret kan finde SQLite for .NET her:
http://sqlite.phxsoftware.com/

Og et SQLite database værktøj her:
http://sqliteadmin.orbmu2k.de/
Avatar billede aaberg Nybegynder
13. november 2008 - 22:52 #7
Problemet med random-valued AutoNumber fields, har jeg desværre ingen anelse om hvordan man løser, men du bliver nok nød til at oprette tabellen forfra.
Avatar billede sune56 Nybegynder
13. november 2008 - 23:28 #8
Hej aaberg...

Som rookie har det været super-lækkert at arbejde med et visuelt interface som table-adapteren, men jeg kan godt se, at jeg nok bliver nødt til at bevæge mig ud på mere usikkert farvand, og skrive mine egne connection-strings osv....

Angående SQlite:
Pointen med at overgå til Access-databasen, var at brugeren ville have filen liggende decentralt på sin egen computer (eller netværks-drev), uden at skulle installere en masse ekstra software. Ville jeg kunne opnå samme effekt med SQLite? For så tror jeg helt klart at jeg vil overveje at skifte...

Som sagt er jeg ikke synderligt rutineret udi den her kunst, så det vil nok tage mig (minimum) nogle dage at efterprøve dine råd. Det lyder dog til at jeg ved at arbejde på minimum én af de valgmuligheder du foreslår vil kunne nå frem til en løsning, så jeg ser ingen grund til at du skal vente på dine point. Hvis du sender mig et svar, tilskriver jeg dig pointene...

Venlig hilsen Sune
Avatar billede aaberg Nybegynder
14. november 2008 - 10:03 #9
SQLite er endnu nemmere at bruge end Access. For at bruge Access fra .NET, skal Microsoft Jet være installeret. Microsoft Jet er som default installeret i Windows, men man hører indimellem om maskiner hvor den ikke er installeret. Med SQLite, skal du bare følge det første link jeg angav i min tidligere kommentar og downloade SQLite-1.0.60.0-setup.exe filen, og installere på din udviklingsmaskine. For at bruge SQLite i dit program, skal du tilføje en reference til System.Data.SQLite. Når dit projekt skal køre på andre maskiner, skal du bare sørge for at System.Data.SQLite.DLL filen bliver kopieret sammen med exe filen. Der skal ikke installeres noget på de maskiner som skal køre dit program.

Hvis du skal bruge en connectionstring til en eller anden database, kan jeg anbefale dig at se på denne side:
www.connectionstrings.com
Jeg kan se at siden er nede lige nu, men når den virker er det en god reference.

Hvis du vil, kan jeg godt lave et lille simpelt SQLite eksempel til dig?
Avatar billede aaberg Nybegynder
14. november 2008 - 10:03 #10
Og svaret :-)
Avatar billede sune56 Nybegynder
15. november 2008 - 00:05 #11
Endnu en gang tak for hjælpen...

Jeg tror ikke at det bliver nødvendigt med et SQLite eksempel, men tak for tilbuddet. Jeg vil følge dit råd, og gå med SQLite, og så ellers tage det i stiv arm derfra...

Venlig hilsen Sune
Avatar billede aaberg Nybegynder
15. november 2008 - 16:34 #12
Ok, held og lykke med programmeringen :-).

...og bare spørg hvis du kommer i problemer.
Avatar billede arne_v Ekspert
24. november 2008 - 00:06 #13
Det er ikke altid at SQLite er super hurtig.

Jeg lavede en lille test.

Resultat:

MS Access : 7,00 seconds
SQLite : 67,80 seconds
SQLServer CE : 0,97 seconds
Firebird : 16,95 seconds
MS Access : 6,81 seconds
SQLite : 62,39 seconds
SQLServer CE : 0,80 seconds
Firebird : 16,72 seconds
MS Access : 6,83 seconds
SQLite : 65,02 seconds
SQLServer CE : 0,80 seconds
Firebird : 18,53 seconds
Avatar billede arne_v Ekspert
24. november 2008 - 00:07 #14
Koden er ikke på nogen måde speciel:

using System;
using System.Data;
using System.Data.Common;

namespace E
{
    public class Program
    {
        private const int NREC = 10000;
        private static void Test(IDbConnection con, bool unicode)
        {
            using(IDbCommand cre = con.CreateCommand())
            {
                if(unicode)
                {
                    cre.CommandText = "CREATE TABLE test (f1 NVARCHAR(10) NOT NULL PRIMARY KEY, f2 NVARCHAR(50))";
                }
                else
                {
                    cre.CommandText = "CREATE TABLE test (f1 VARCHAR(10) NOT NULL PRIMARY KEY, f2 VARCHAR(50))";
                }
                cre.ExecuteNonQuery();
            }
            using(IDbCommand ins = con.CreateCommand())
            {
                ins.CommandText = "INSERT INTO test VALUES(@f1, @f2)";
                IDbDataParameter p1 = ins.CreateParameter();
                p1.ParameterName = "@f1";
                p1.DbType = DbType.String;
                p1.Size = 10;
                ins.Parameters.Add(p1);
                IDbDataParameter p2 = ins.CreateParameter();
                p2.ParameterName = "@f2";
                p2.DbType = DbType.String;
                p2.Size = 50;
                ins.Parameters.Add(p2);
                for(int i = 0; i < NREC; i++)
                {
                    ((IDbDataParameter)ins.Parameters["@f1"]).Value = "K" + i;
                    ((IDbDataParameter)ins.Parameters["@f2"]).Value = "Dette er bare en lille test";
                    ins.ExecuteNonQuery();
                }
            }
            using(IDbCommand drp = con.CreateCommand())
            {
                drp.CommandText = "DROP TABLE test";
                drp.ExecuteNonQuery();
            }
        }
        private static void Test(string name, string prov, string constr, bool unicode)
        {
            DateTime t1 = DateTime.Now;
            DbProviderFactory dbf = DbProviderFactories.GetFactory(prov);
            using(IDbConnection con = dbf.CreateConnection())
            {
                con.ConnectionString = constr;
                con.Open();
                Test(con, unicode);
            }
            DateTime t2 = DateTime.Now;
            Console.WriteLine(name + " : " + (t2 - t1).TotalSeconds.ToString("0.00") + " seconds");
        }
        private static void Test()
        {
            Test("MS Access", "System.Data.OleDb", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=SpeedTest.mdb", false);
            Test("SQLite", "System.Data.SQLite", "Data Source=SpeedTest.db;Version=3;", false);
            Test("SQLServer CE", "System.Data.SqlServerCe", "Data Source=SpeedTest.sdf", true);
            Test("Firebird", "FirebirdSql.Data.FirebirdClient", "ServerType=1;Database=SpeedTest.fdb", false);
        }
        private const int REP = 3;
        public static void Main(string[] args)
        {
            for(int i = 0; i < REP; i++)
            {
                Test();
            }
        }
    }
}
Avatar billede aaberg Nybegynder
24. november 2008 - 08:46 #15
Hej Arne_v. Prøv at wrappe dine queries i en transaction, så vil SQLite koden garanteret køre hurtigst af alle databaser du har testet. Det er et kendt spidsfindighed ved SQLite, at den er langsom til at oprette transaktioner. I dit eksempel opretter og comitter den 10000 transaktioner.

Jeg har prøvet at køre din test, hvor den eneste ændring er en transaktion rundt om løkken som kalder ExecuteNonQuery(), som vist herunder. Derudover har jeg fjernet firebird fra teste, da jeg ikke har denne database på min maskine.

using (IDbTransaction transaction = con.BeginTransaction())
{
    ins.Transaction = transaction;
    for (int i = 0; i < NREC; i++)
    {
        ((IDbDataParameter)ins.Parameters["@f1"]).Value = "K" + i;
        ((IDbDataParameter)ins.Parameters["@f2"]).Value = "Dette er bare en lille test";
        ins.ExecuteNonQuery();
    }
    transaction.Commit();
}

Resultatet:
MS Access : 3,72 seconds
SQLite : 0,45 seconds
SQLServer CE : 0,87 seconds
MS Access : 3,67 seconds
SQLite : 0,67 seconds
SQLServer CE : 0,73 seconds
MS Access : 3,14 seconds
SQLite : 0,52 seconds
SQLServer CE : 0,75 seconds

Jeg prøvede at køre testen med 100000 rækker.
MS Access : 37,41 seconds
SQLite : 3,14 seconds
SQLServer CE : 7,29 seconds
MS Access : 35,36 seconds
SQLite : 3,19 seconds
SQLServer CE : 7,22 seconds
MS Access : 32,66 seconds
SQLite : 3,53 seconds
SQLServer CE : 7,33 seconds
Avatar billede aaberg Nybegynder
24. november 2008 - 08:59 #16
Og testen med en million rækker (Dog uden Access, for det orker jeg ikke at vente på :-)

SQLite : 35,81 seconds
SQLServer CE : 94,90 seconds
SQLite : 48,77 seconds
SQLServer CE : 89,62 seconds
SQLite : 38,26 seconds
SQLServer CE : 88,04 seconds
Avatar billede groyk Novice
27. november 2008 - 14:37 #17
Hmm.

Prøver at indsætte ca. 25 MB data i SQLite, men kan det godt passe det skal tage flere timer!!
Avatar billede aaberg Nybegynder
27. november 2008 - 14:52 #18
Nej, så gør du helt sikkert noget forkert.

Hvis du skal indsætte mange rækker i en SQLite database, bør indsætte alle rækkerne i en transaktion. SQLite er forholdsvis langsom til at oprette og committe transaktioner, så hvis du indsætter mange rækker uden at gøre det i en transaktion, vil SQLite oprette en transaktion for hver række.

25 MB data bør ikke tage mange sekunder.
Avatar billede groyk Novice
27. november 2008 - 15:25 #19
OK Takker

Læste lige hele spørgsmålet igennem igen, nu spiller det.

Hvordan sørger jeg egentlig for at æ, ø og å bliver importeret rigtigt, samt at special chars escapes eller slettes?

Bruger godt nok vb.net ikke C# (Skulle være muligt at forstå aligevel)
Avatar billede aaberg Nybegynder
27. november 2008 - 15:50 #20
Jeg går ud fra at du mener importen fra databasen til en webside, eller? Hvis det er det du mener, så tror jeg du bliver nød til at håndtere det selv.

SQLite databasen gemmer tekst encoded som UTF-8, så der skal ikke være nogen problemer med at gemme danske tegn i databasen.
Avatar billede groyk Novice
27. november 2008 - 16:02 #21
Problemet opstår når jeg importere data fra en tekstfil til databasen, kan selvfølgelig godt være SQLite Administratoren der ikke viser tegnene rigtigt.

Prøver lige at lave en søgning
Avatar billede groyk Novice
27. november 2008 - 16:03 #22
Men har stadig problemer med nogle tegn den ikke vil spise fra mine inserts!

I PHP bruger jeg normalt add_slashes() eller escape_string(), men hvad skal jeg bruge i VB.net?
Avatar billede arne_v Ekspert
27. november 2008 - 16:24 #23
parameters
Avatar billede arne_v Ekspert
27. november 2008 - 16:24 #24
Og i PHP bør du bruge det samme - det kaldes dog prepared statement i PHP.
Avatar billede arne_v Ekspert
28. november 2008 - 01:36 #25
Med hensyn til performance så er jeg ikke vildt imponeret af at den gode performance
kun er ved bulk load. Det er ikke nogen særlig typisk brug.
Avatar billede aaberg Nybegynder
28. november 2008 - 08:56 #26
Det er vel heller ikke nogen særlig typisk brug, med 10000 transaktioner i minuttet!? Desuden har SQLite i de fleste tilfælde også bedre performance i selects og joins, end de andre databaser vi sammenligner med.

Det er klart at der er situationer, hvor SQLite ikke er en optimal database at bruge, men når man sammenligner med Access og SQL Server CE, synes jeg ikke der er tvivl om hvilken database der er den bedste. Hvis man har brug for en database med flere features end SQLite, og som håndhæver relationer og datatyper, synes jeg Firebird er et meget godt alternativ. Firebird er dog lidt mere besværlig end SQLite at sætte op til at køre embedded.

Efter at dette spørgsmål blev oprettet, har jeg testet lidt på VistaDB. VistaDB er en embedded database som er skrevet i C#. VistaDB har de fleste features man ønsker sig i en database, blandt andet har den CLR stored procedures. Da den er 100% managed, kræver den bare medium trust for at køre, hvilket betyder at den kan bruges som drag 'n drop database på de fleste webhoteller, hvilket du hverken kan med SQLite, SQL Server CE eller Firebird. Denne kan i mange tilfælde være et interessant alternativ. Der findes en gratis Express version. Den har dog langt fra så god performance som SQLite.

groyk -> Jeg bruger SQLite Administrator som databaseværktøj. Jeg har aldrig haft problemer med æ, ø og å i denne, så jeg tror ikke det er der problemet ligger. Hvis du stadig har problemer med dette, kan du så ikke vise lidt af din kode her?
Avatar billede arne_v Ekspert
28. november 2008 - 22:15 #27
Max. throughput er ikke typisk brug. Men det har ingen relevans fordi X TPM ved 100 %
load betyder også 100/X % load per TPM.
Avatar billede aaberg Nybegynder
28. november 2008 - 22:44 #28
Jeg tror jeg forstår dit regnestykke, men jeg fanger ikke pointen!
Avatar billede groyk Novice
29. november 2008 - 21:37 #29
Hej aaberg cc

Her er den kode jeg bruger til at smide data ind i SQLite med

Public Sub opdater_sanistaal()

        Dim CountErrors As Integer = 0

        Dim SQLconnect As New SQLite.SQLiteConnection()
        Dim SQLcommand As New SQLite.SQLiteCommand
        SQLconnect.ConnectionString = "Data Source=" & Main.DB2 & ";"
        SQLconnect.Open()
        SQLcommand = SQLconnect.CreateCommand
        'Insert Record into Fo
        Using transaction As IDbTransaction = SQLconnect.BeginTransaction()
            SQLcommand.Transaction = transaction

            ' Looper ALLE inserts igennem
            Dim i As Integer
            i = FreeFile()
            Dim ii As Integer
            Dim Vl(19) As String
            Dim SQLstring As String = ""

            If System.IO.File.Exists(Main.DB1) Then
                FileOpen(i, Main.DB1, OpenMode.Input)
                Do While Not EOF(i)
                    Vl = Split(LineInput(i).Replace("""", ""), ";")

                    'Vl(0) identifikation
                    'Vl(1) varenr
                    'Vl(2) saninr
                    'Vl(3) varegruppe
                    'Vl(4) varetekst
                    'Vl(5) subvaretekst
                    Vl(6) = Vl(6).Replace(",", ".") 'Vl(6) listepris
                    'Vl(7) enhedsbetegnelse
                    'Vl(8) enhedsfaktor
                    'Vl(9) minsalg
                    'Vl(10) rabattype
                    'Vl(11) rabatkode
                    Vl(12) = Vl(12).Replace(",", ".") 'Vl(12) meterprlgd
                    Vl(13) = Vl(13).Replace(",", ".") 'Vl(13) kgprmeter
                    'Vl(14) direktesogeord
                    'Vl(15) eankode
                    Vl(16) = Vl(16).Replace(",", ".") 'Vl(16) rabatiprocent
                    Vl(17) = Vl(17).Replace(",", ".") 'Vl(17) rabatikr
                    Vl(18) = Vl(18).Replace(",", ".") 'Vl(18) nettopris
                    'Vl(19) kundensvarenr

                    SQLstring = ""
                    For ii = 0 To Vl.Length - 1
                        SQLstring = SQLstring + "'" + Vl(ii) + "'"
                        If Not ii = Vl.Length - 1 Then SQLstring = SQLstring + ","
                    Next

                    If Not SQLstring = "" Then
                        Try
                            If Vl(0) = "OPR" Then
                                'Insert = Insert + SQLstring + ";"
                                'MsgBox(SQLstring)
                                'SQLcommand.CommandText = "DELETE FROM sanistaal WHERE saninr = " + Vl(2)
                                SQLcommand.CommandText = "INSERT INTO sanistaal (identifikation,varenr,saninr,varegruppe,varetekst,subvaretekst,listepris,enhedsbetegnelse,enhedsfaktor,minsalg,rabattype,rabatkode,meterprlgd,kgprmeter,direktesogeord,eankode,rabatiprocent,rabatikr,nettopris,kundensvarenr) VALUES (" + SQLstring + ")"
                                SQLcommand.ExecuteNonQuery()
                            End If
                            If Vl(0) = "ÆND" Then
                                SQLcommand.CommandText = "DELETE FROM sanistaal WHERE saninr = " + Vl(2)
                                SQLcommand.CommandText = "INSERT INTO sanistaal (identifikation,varenr,saninr,varegruppe,varetekst,subvaretekst,listepris,enhedsbetegnelse,enhedsfaktor,minsalg,rabattype,rabatkode,meterprlgd,kgprmeter,direktesogeord,eankode,rabatiprocent,rabatikr,nettopris,kundensvarenr) VALUES (" + SQLstring + ")"
                                SQLcommand.ExecuteNonQuery()
                            End If
                            If Vl(0) = "SLT" Then
                                SQLcommand.CommandText = "DELETE FROM sanistaal WHERE saninr = " + Vl(2)
                                SQLcommand.ExecuteNonQuery()
                            End If
                        Catch ex As Exception
                            CountErrors += 1
                        End Try
                    End If

                Loop
            End If
            'Catch ex As Exception

            'End Try
            FileClose(i)
            ' Færdig

            transaction.Commit()
        End Using
        SQLcommand.Dispose()
        SQLconnect.Close()

        MsgBox(CountErrors)
    End Sub
Avatar billede groyk Novice
29. november 2008 - 21:39 #30
Try sætningen fanger fejl, de forekommer f.eks hvis der tegnet ' er i en varetekst.

Hvordan escaper jeg dem?

Derudover inporteres æøå stadig ikke rigtigt til SQLite
Avatar billede aaberg Nybegynder
30. november 2008 - 10:56 #31
Som arne_v nævner tidligere, så skal du bruge parametre. Hvis du bruger parametre, slipper du i hvert fald for fejlen som opstår når der er en ' i teksten. Med hensyn til danske tegn, så er problemet enten at du ikke bruger parametre, eller også er det at du bruger en forkert encoding når du læser fra filen.

Parametre bruger du ved først at angive parametre i sql querien med @ forand parameternavnet.

"INSERT INTO sanistaal (identifikation,varenr,saninr, osv...)
values (@identifikation, @varenr, @saninr...)"

og så tilføjer du parametre til SQLiteCommand objektet.
SQLcommand.Parameters.Add("@identifikation", Vl(0))
SQLcommand.Parameters.Add("@varenr", Vl(1))
SQLcommand.Parameters.Add("@saninr", Vl(2))
osv...

Hvis dette ikke hjælper på danske tegn, så er det næsten sikkert i indlæsningen af filen der er noget galt. Jeg kan se at du bruger en gammel VB måde at læse filer på, det skader nok ikke at lære "the .NET way" uanset hvad. Men i hvert fald, så kan der opstå problemer, hvis filen er gemt med et karaktersæt, og indlæsningen foregår med et andet karakterset. Med FileOpen funktionen, har du ikke mulighed for at specificere karaktersæt.

Prøv at læse filen på følgende måde:
dim reader as new StreamReader(Main.DB1, Encoding.GetEncoding(1252))

Do While reader.Peek() > -1
  Vl = reader.ReadLine().Replace("""","").Split(';')

Læg mærke til at jeg tilføjer en Encoding (karaktersæt) i StreamReaderens konstruktør. Karaktersættet med codepage 1252, er det vest-europæiske karaktersæt, som er standard for blandt andet de skandinaviske lande.

Bare spørg hvis du ikke får det til at fungere, eller der er noget jeg skal forklare lidt bedre.
Avatar billede groyk Novice
01. december 2008 - 09:52 #32
Hej Aaberg

Takker mange gange for hjælpen, Har ændret alle mine indput til parameter, samt ændret måden jeg læser filen på.

Har dog stadigvæk problemer med æøå.

Men som jeg ser det fortæller jeg jo også kun hvilket format tekstfilen er i, eller?

Skal jeg ikke konventere de strenge der indeholder VARCHAR.?
Avatar billede aaberg Nybegynder
01. december 2008 - 10:33 #33
Hej groyk.

For at teste, hvad pokker det er der sker for alle æ, ø og å'erne, lavede jeg en lille testbase, og puttede nogle danske tegn ind i den. Og ganske rigtigt... i SQLite Manager ser æ,ø og å helt åndsvage ud. Jeg prøvede at åbne samme sqlite fil fra Sqliteman ( http://sqliteman.com/ ), og her ser de danske tegn helt fine ud. Så, det er åbenbart SQLite Manager som har et problem med danske tegn.
Avatar billede groyk Novice
01. december 2008 - 12:04 #34
Hej aaberg

Tak for alt den hjælp du har givet. bruger du sqliteman som db admin?

Har også lie et spørgsmål mere hvis du har tid.

Kan denne sægning speedes op, synes ikke jeg får den hastighed jeg gerne vil have. (søgetid 2-4 sek.)
Kunne gøres lige så hurtigt i en tekstfil!!

Kan man evt. lave en "prefered tabel" hvor den smider de sidste 1000 søgninger over i, og så kigger der før den kigger i MainDB?

Skal kun bruge et resultat pr. søgning (unik søgning)

Dim SQLconnect As New SQLite.SQLiteConnection()
        Dim SQLcommand As SQLite.SQLiteCommand
        SQLconnect.ConnectionString = "Data Source=" & Main.DB2 & ";"
        SQLconnect.Open()
        SQLcommand = SQLconnect.CreateCommand

        If row = 1 Then SQLcommand.CommandText = "SELECT * FROM sanistaal WHERE saninr='" + UCase(search) + "'"
        If row = 2 Then SQLcommand.CommandText = "SELECT * FROM sanistaal WHERE direktesogeord='" + UCase(search) + "'"

        Dim Vl As SQLite.SQLiteDataReader = SQLcommand.ExecuteReader()
        While Vl.Read() ' Hent nødvendige data her

            DGWS.Item(1, DGWS.CurrentRow.Index).Value = System.Convert.ToString(Vl(2))
            DGWS.Item(2, DGWS.CurrentRow.Index).Value = Vl(14)
            DGWS.Item(5, DGWS.CurrentRow.Index).Value = Vl(7)
            DGWS.Item(6, DGWS.CurrentRow.Index).Value = Vl(4)
            DGWS.Item(7, DGWS.CurrentRow.Index).Value = Vl(5)
            DGWS.Item(8, DGWS.CurrentRow.Index).Value = Vl(12) * 1000
            DGWS.Item(9, DGWS.CurrentRow.Index).Value = Vl(8)
            DGWS.Item(10, DGWS.CurrentRow.Index).Value = Vl(13)
            DGWS.Item(11, DGWS.CurrentRow.Index).Value = Vl(9)

        End While
        SQLcommand.Dispose()
        SQLconnect.Close()
        Return True
Avatar billede aaberg Nybegynder
01. december 2008 - 12:31 #35
Jeg har længe brugt Sqliteman, men er for lidt tid siden gået over til SQLite Administrator, da jeg synes den er lidt mere intuitiv. Jeg har dog aldrig lagt mærke til æ,ø og å problematikken, mærkeligt nok.

prøv at sætte et index på "direktesogeord" kolonnen. Fra SQLite Administrator højreklikker du på kolonnen og trykker "Create Index". Se om det ikke forbedre performance betydeligt.

Hvis det er en slags Fulltext search du er ved at lave, så prøv at tjekke det her link. http://sqlite.phxsoftware.com/forums/p/516/2228.aspx#2228
Avatar billede groyk Novice
01. december 2008 - 12:51 #36
Hej aaberg

Takker mange gange. Nu spiller det max.

Søgetiden er jo mildest taget imponerende!! vi snakker millisekunder på 200.000 rækker

Har jo lidt svært ved at give dig point, da spørgsmålet ikke er oprettet af mig, og samtidigt er lukket.
Avatar billede aaberg Nybegynder
01. december 2008 - 14:34 #37
Ingen problem. Jeg er bare glad for at kunne hjælpe.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester