Einzelnen Beitrag anzeigen

Morphie

Registriert seit: 27. Apr 2008
Ort: Rahden
630 Beiträge
 
#1

Vergleich Firebird: C# vs. Delphi Win32

  Alt 22. Sep 2011, 14:00
Datenbank: Firebird • Version: 2.5 • Zugriff über: ADO.NET / IBDAC
Hi, ich lerne gerade C# und wollte einen Datenimport für Firebird programmieren.
Leider musste ich feststellen, dass meine C#-Lösung ca. 8x langsamer ist als meine Delphi-Lösung.

Habt ihr eine Idee, was ich hier falsch mache?

Habe mal ein Beispielprojekt gemacht.

Delphi-Code:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  Con: TIBCConnection;
  Qry: TIBCQuery;
  i: integer;
const
  max = 10000;
begin
  Con := TIBCConnection.Create(nil);
  try

    Con.Server := 'localhost';
    Con.Username := 'SYSDBA';
    Con.Password := 'masterkey';
    Con.Database := 'F:\Test.fdb';
    Con.Open;

    Qry := TIBCQuery.Create(nil);
    try
      Qry.Connection := Con;
      Qry.Params.CreateParam(ftInteger,'Par1',ptInput);
      Qry.Params.CreateParam(ftFloat,'Par2',ptInput);
      Qry.Params.CreateParam(ftString,'Par3',ptInput);
      Qry.Params.CreateParam(ftDateTime,'Par4',ptInput);
      Qry.SQL.Text := 'UPDATE OR INSERT INTO TEST (FELD1, FELD2, FELD3, FELD4) VALUES (:Par1, :Par2, :Par3, :Par4);';
      Qry.Prepare;

      ProgressBar1.Max := max;
      ProgressBar1.Position := 0;

      for i := 0 to max do
      begin
        Qry.ParamByName('Par1').Value := i;
        Qry.ParamByName('Par2').Value := i;
        Qry.ParamByName('Par3').Value := 'Test';
        Qry.ParamByName('Par4').Value := Now;
        Qry.Execute;

        ProgressBar1.Position := i;
        Label1.Caption := inttostr(i) + ' / ' + inttostr(max);
        Application.ProcessMessages;
      end;

    finally
      qry.Free;
    end;

  finally
    Con.Free;
  end;
end;
C#-Code:
Code:
private void button2_Click(object sender, EventArgs e)
{
    FbConnection Con = new FbConnection();
    FbConnectionStringBuilder ConStrBuilder = new FbConnectionStringBuilder();

    // ConnectionString bauen
    ConStrBuilder.DataSource = "localhost";
    ConStrBuilder.UserID = "SYSDBA";
    ConStrBuilder.Password = "masterkey";
    ConStrBuilder.Database = "F:\\Test.fdb";
               
    // ConnectionString zuweisen
    Con.ConnectionString = ConStrBuilder.ConnectionString;
    Con.Open();

    FbCommand Cmd = new FbCommand();
    Cmd.Connection = Con;
    Cmd.Parameters.Add("Par1", FbDbType.Integer);
    Cmd.Parameters.Add("Par2", FbDbType.Decimal);
    Cmd.Parameters.Add("Par3", FbDbType.VarChar);
    Cmd.Parameters.Add("Par4", FbDbType.TimeStamp);
    Cmd.CommandText = "UPDATE OR INSERT INTO TEST (FELD1, FELD2, FELD3, FELD4) VALUES (@Par1, @Par2, @Par3, @Par4);";
    Cmd.Prepare();

    const int max = 10000;

    progressBar1.Maximum = max;
    progressBar1.Value = 0;

    for (int i = 0; i < max; i++)
    {
        Cmd.Parameters["Par1"].Value = i;
        Cmd.Parameters["Par2"].Value = i;
        Cmd.Parameters["Par3"].Value = "Test";
        Cmd.Parameters["Par4"].Value = DateTime.Now;
        Cmd.ExecuteNonQuery();

        progressBar1.Value = i;
        label2.Text = i.ToString() + " / " + max.ToString();
        Application.DoEvents();
    }
}
Ich habe auch schon Transaktionen eingebaut, das hat allerdings auch nichts gebracht.

Die Tabellendefinition sieht so aus:
Code:
CREATE TABLE TEST (
  FELD1  INTEGER NOT NULL,
  FELD2  DECIMAL,
  FELD3  VARCHAR(20),
  FELD4  TIMESTAMP,
  /* Schlüssel */
  PRIMARY KEY (FELD1)
);
Folgende Werte konnt ich mittels GetTickCount (sind das eig. Millisekunden?) ermitteln:
Code:
Versuch   Delphi   C#
1          8515      68312
2          8297      55312
3          8703      54969
4          9984      53969
5          8671      54218

Geändert von Morphie (22. Sep 2011 um 14:02 Uhr)
  Mit Zitat antworten Zitat