Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   C# DataGridView füllen zur Laufzeit (https://www.delphipraxis.net/118413-datagridview-fuellen-zur-laufzeit.html)

GuenterS 7. Aug 2008 11:25

Datenbank: Oracle • Version: 10g Express • Zugriff über: Oracle Instant Client (OCI)

DataGridView füllen zur Laufzeit
 
Hallo,

ich verwende die Express Edition des Visual Studios 2008 und habe ein paar Problemchen auf die Oracle Datenbank zuzugreifen.

Ich habe es folgendermaßen probiert:

Code:
       static private string GetConnectionString()
        {
            return "Data Source=127.0.0.1;Persist Security Info=True;User ID=system;Password=oracle;Unicode=True";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string connectionString = GetConnectionString();

            OracleConnection OraConn = new OracleConnection();

            OraConn.ConnectionString = connectionString;
            OraConn.Open();

            label1.Text = OraConn.State.ToString();

            OracleDataAdapter da = new OracleDataAdapter("SELECT * FROM CONTACTTYPE", OraConn);

            OracleCommandBuilder commandBuilder = new OracleCommandBuilder(da);

            DataTable table = new DataTable();
            table.Locale = System.Globalization.CultureInfo.InvariantCulture;

            da.Fill(table);

            dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader);

            bindingSource1.DataSource = table;

            dataGridView1.DataSource = bindingSource1;

            OraConn.Close();
        }
Das DataGridView-Objekt hat den Namen dataGridView1 und die BindingSource "bindingSource1".

Nach einer ganzen Weile wird die Verbindung zur Datenbank scheinbar geöffnet, denn im label1.Text steht danach "Open", das interpretiere ich als Erfolgsmeldung.

Das Gridview bleibt aber ganz leer. Ich habe auch schon versucht, die Spalten im Gridview manuell anzulegen, das hatte allerdings nur den Effekt, dass sich die Anzahl der Zeilen erhöht hat. (Genau um die Anzahl welche in der Tabelle gespeichert waren). Allerdings waren die Inhalte leer.

Ich glaube ich habe irgend eine Kleinigkeit vergessen, ich komme aber nicht darauf. Auch dass der Zugriff so lange dauert ca. 5 Sekunden macht mich etwas stutzig.

GuenterS 11. Aug 2008 09:00

Re: DataGridView füllen zur Laufzeit
 
Ich habe den Fehler gefunden :)

Anscheinend muss man, wenn man auf die Unterstützung vom Studio nicht bauen kann, die Spalten manuell einfügen und auch das Feld für die Datenbindung ausfüllen.


Warum der Verbindungsaufbau aber dermaßen langsam ist, ist mir nach wie vor ein Rätsel. Ich hab die sekunden mal gezählt und komme auf 15-20 ... irgendwie nicht gerade flott.

Elvis 11. Aug 2008 10:58

Re: DataGridView füllen zur Laufzeit
 
Zitat:

Zitat von GuenterS
Anscheinend muss man, wenn man auf die Unterstützung vom Studio nicht bauen kann, die Spalten manuell einfügen und auch das Feld für die Datenbindung ausfüllen.

Neeee! :shock:
Einfach irgendwo die Eigenschaft AutogenerateColumns auf true setzen.
Die ist dafür da, damit deine Design-Time Einstellungen nicht immer überschrieben werden.
Ohne Designtime macht das natürlich wenig Sinn. :-)


Zitat:

Warum der Verbindungsaufbau aber dermaßen langsam ist, ist mir nach wie vor ein Rätsel. Ich hab die sekunden mal gezählt und komme auf 15-20 ... irgendwie nicht gerade flott.
Dein Connectionstring sieht aus als hättest du in deinem Orahome\Network\Admin keine TNSNames.ora mit den Einstellungen für deine DB hinterlegt.
Eine IP anzugeben heißt, dass er durch etliche Mögliche Settings fällt bevor er es irgendwann versucht auf die Default DB der Maschine zuzugreifen.

Eine Möglichkeit ohne TNSNames.ora siehst du in dem abstrakten Bleistift unten.
Da siehst du außerdem wie du eine Conenction kriegen kannst ohne gegen einen speziellen Provider zu kompilieren. Und wie du wo "using" nutzen kannst damit du a) nicht in Finalizer rennst und b) keine Conenction unnötig lange aufgehalten wird.
Und c) ein kleiner Tip, damit der GridView nicht so EXTREEEEM langsaaaaam ist (DoubleDBuffered ist in .Net leider protected :? )

Das da unten geht schneller auf als ein Maikäfer husten kann. Du kannt auch den ODP von Oracle installieren.
Der öffnet Connection signifikant schneller als die Krücke von MSFT, dafür musst du dann deine App.config anpassen um ihn nutzen zu können.


(KEIN Delphi code)
Delphi-Quellcode:
type
  DoubleBufferedDataGridView = class(DataGridView)
   protected
      method CreateHandle; override;
   end;

method DoubleBufferedDataGridView.CreateHandle;
begin
   DoubleBuffered := true;
   inherited;
end;

class method ConsoleApp.Main;
begin
   var dt := new DataTable();
   var factory := DbProviderFactories.GetFactory("System.Data.OracleClient");
   using conn := factory.CreateConnection() do
   begin
      conn.ConnectionString := "Persist Security Info=True;User ID=deinUser;Password=deinPasswort;"+
                               "Data source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)"+
                               "(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=DeineDB)))";
      conn.Open();

      using cmd := conn.CreateCommand() do
      begin
         cmd.CommandText := "select * from all_users";
         using rdr := cmd.ExecuteReader() do
            dt.Load(rdr);
      end;
   end;

   Application.EnableVisualStyles();

   using frm := new Form() do
   begin
      var dgv := new DoubleBufferedDataGridView();
      dgv.Dock := DockStyle.Fill;
      dgv.AutoSizeColumnsMode := DataGridViewAutoSizeColumnsMode.AllCells;
      dgv.AutoGenerateColumns := true;
      dgv.DataSource := dt;
      frm.Controls.Add(dgv);
      frm.ShowDialog();
   end;
end;

GuenterS 11. Aug 2008 13:39

Re: DataGridView füllen zur Laufzeit
 
Hallo vielen Dank für die Anregungen.

Ich habe versucht den Connection String so aufzubauen, wie du es vorgeschlagen hast, allerdings hat das nichts genutzt (abgesehn davon, dass ichs nach ner halben Minute abschießen musste).

Dein code Fraqument war so leider nicht nutzbar. Gewisse Objekte kennt er einfach nicht. Ich bin noch kein C#-Experte. Ich nehme an, man muss irgendwas einbinen um an diese DbProviderFactories Klasse zu kommen. Nur was???

Abgesehn davon kann ich mir nicht vorstellen, dass die OracleConnection so aufgebaut ist, dass diese Wartezeiten normal sind.

Mein Connection String sieht jetzt so aus:
Code:
Persist Security Info=True;User ID=test;Password=test;Data source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=XE)))
Vielleicht eine ganz dumme Frage ... Ich nehme an, dass das "XE" richtig ist, aber wo sieht man denn bei Oracle den Datenbanknamen? (Bei MSSQL Server wüßt ichs...)

Elvis 11. Aug 2008 14:38

Re: DataGridView füllen zur Laufzeit
 
Bevor wir weitermachen, 2 ganz kurze Sachen.
Wenn du die beantwortest hastm können wir dann weitermachen.
  • Schaue mal in die Serviceliste deines Rechners.
    Du suchst nach einem Dienst Namens "OracleService%", wobei % der Name der Datenbank ist.
  • Du solltest unter "DbProviderFactories" ein gelbes Bälkchen sehen.
    Wenn du nun ctrl+"." drückt oder drauf klickst, siehst du ein Menü mit dem du den Namespace in die usings werfen kannst.
    Die 2 interessanten Namespaces sind:
    • System.Data
    • System.Data.Common

Hier ist die C# verison:
Code:
class Program
{
  static void Main(string[] args)
  {
    DataTable dt = new DataTable();
    DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.OracleClient");
    using (IDbConnection conn = factory.CreateConnection())
    {
      conn.ConnectionString = "Persist Security Info=True;User ID=deinUser;Password=deinPasswort;" +
                               "Data source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)" +
                               "(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=DeineDB)))";
      conn.Open();

      using (IDbCommand cmd = conn.CreateCommand())
      {
        cmd.CommandText = "select * from all_users";
        using (IDataReader rdr = cmd.ExecuteReader())
          dt.Load(rdr);

      }
    }

    System.Windows.Forms.Application.EnableVisualStyles();

    using (System.Windows.Forms.Form frm = new System.Windows.Forms.Form())
    {
      DoubleBufferedDataGridView dgv = new DoubleBufferedDataGridView();
      dgv.Dock = System.Windows.Forms.DockStyle.Fill;
      dgv.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells;
      dgv.AutoGenerateColumns = true;
      dgv.DataSource = dt;
      frm.Controls.Add(dgv);
      frm.ShowDialog();
    }
  }
}

class DoubleBufferedDataGridView : System.Windows.Forms.DataGridView
{
  protected override void CreateHandle()
  {
    DoubleBuffered = true;
    base.CreateHandle();
  }
}

GuenterS 11. Aug 2008 14:55

Re: DataGridView füllen zur Laufzeit
 
Hallo,

also der Dienst OracleServiceXE ist gestartet, somit denke ich habe den Namen der Datenbank richtig gehabt.

Ich habe Dein Code Stück genommen nur um zu testen wie schnell die connection aufgeht... Ich schreibe währenddessen gerade diesen Beitrag... Leider auch nicht wirklich schneller, sieht eher danach aus, dass sie gar nicht aufgeht.

Das ist der code der ausgeführt werden soll...

Code:
           
        static private string GetConnectionString()
        {
            //return "Data Source=XE;Persist Security Info=True;User ID=test;Password=test;Unicode=True";
            //return "User Id=test;Password=test;Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))(CONNECT_DATA=(SID=XE)))";
            //return "Driver=(Oracle in XEClient);dbq=192.168.252.161:1521/XE;Uid=system;Pwd=oracle;";
            //return "Driver={Microsoft ODBC for Oracle};Server=192.168.252.161;Uid=test;Pwd=test;";
            //return "Provider=msdaora;Data Source=XE;User Id=test;Password=test;";
            return "Persist Security Info=True;User ID=test;Password=test;"
                        + "Data source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)"
                        + "(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=XE)))";
        }

        private void button1_Click(object sender, EventArgs e)
        {

            DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.OracleClient");

            using (IDbConnection conn = factory.CreateConnection())
            {
                conn.ConnectionString = GetConnectionString();
                conn.Open();

                label1.Text = conn.State.ToString();




            }
}

Elvis 11. Aug 2008 16:20

Re: DataGridView füllen zur Laufzeit
 
Sorry, bin mit der XE nicht wirklich vertraut. :oops:
Das hätte eigentlich gehen sollen... :zwinker:
Dein originaler Connectionstring wird auch mit den Factories weiterhin gehen, nur anscheinend langsam... :wall:


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:43 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz