Announcement

Collapse
No announcement yet.

Datensätze von MS Access => MS SQL kopieren

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Datensätze von MS Access => MS SQL kopieren

    Hallo,

    ich mache zur Zeit mein Praxissemester. Meine Aufgabe ist es ein C# Programm zu schreiben mit dem ich in regelmäßigen Abständen die neuen Datensätze aus einer Access Datenbank in eine SQL Datenbank kopiere.
    Ich will die Datensätze einzeln kopieren, da ich manche Felder noch ändern muss.

    Ich habe es schon mit typisierten Datensätzen versucht, aber es klappt leider immer noch nicht richtig.

    Über den Commandbuilder habe ich Kommandos für Update und Insert generieren lassen.

    Einen neuen Datensatz kann ich aus der Access DB in meine SQL Testdatenbank einfügen:
    [highlight=c#]
    (sDS=SQL-Dataset, aDS = AccessDS)
    DataRow newrow = sDS.Tables[0].NewRow();
    newrow[0] = aDS.Tables[0].Rows[0][0];
    newrow[1] = aDS.Tables[0].Rows[0][1];
    newrow[2] = aDS.Tables[0].Rows[0][2];
    newrow[3] = aDS.Tables[0].Rows[0][3];
    newrow[4] = aDS.Tables[0].Rows[0][4];
    sDS.Tables[0].Rows.Add(newrow);

    SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(sqlDA);
    sqlDA.InsertCommand = cmdBuilder.GetInsertCommand();
    sqlDA.UpdateCommand = cmdBuilder.GetUpdateCommand();
    [/highlight]

    Leider habe ich es nicht geschafft eine Schleife für 2 oder mehrere Datensätze zu schreiben, weil "newrow" nicht mehrfach verwendet werden kann.
    Mit der foreach Schleife schreibt er mir immer den ersten Datensatz x mal in die SQL DB und mit der For-Schleife kommt immer der Fehler, dass newrow schon verwendet wird.

    Ausserdem habe ich das Problem, das bei manchen Versuchen die Fehlermeldung kommt, dass die Spalte in die ich schreiben will noch nicht auf der SQL DB existiert.

    Über den Befehl "ImportRow" habe ich es auch nicht geschafft.

    Ich suche seit Tagen in Google und Foren und habe leider nichts passenden gefunden.
    Für Lösungsansätze wäre ich sehr dankbar.
    mfg Mark
    Zuletzt editiert von gfoidl; 12.05.2009, 09:53. Reason: Code-Formatierung! (hinzugefügt)

  • #2
    Hallo Mark und willkommen,

    die "mehrfache" Verwendung der Variablen newrow dürfte kein Problem sein. Du musst nur den Geltungsbereich richtig beachten:
    Code:
    foreach(DataRow row in SourceTable.Rows) {
       DataRow newrow = DestTable.NewRow();
       newrow[0] = row[0];
       newrow[1] = row[1];
       newrow[2] = row[2];
       newrow[3] = row[3];
       newrow[4] = row[4];
       DestTable.Rows.Add(newrow);
    }
    Solange du bei der SourceTable immer Rows[0] verwendest, ist doch klar, dass nur die erste Zeile übertragen wird.

    ImportRow könnte aus folgendem Grund nicht funktionieren:
    Beim Aufruf von ImportRow werden der vorhandene DataRowState sowie andere Werte in der Zeile beibehalten.
    RowState.Unchanged bleibt also erhalten, also wird diese Zeile auch in der DestTable als "unverändert" markiert und beim Update übergangen.

    Gruß Jürgen

    PS. Bitte markiere deinen Code als solchen, entweder als highlight (siehe den Hinweis im obersten Beitrag des NET-Forums von gfoidl) oder wenigstens allgemein mit dem #-Button.

    PS2. Nur der Vollständigkeit halber möchte ich auf BulkCopy bzw. BulkInsert hinweisen: Damit ist der Import von Access nach MS-SQL einfach möglich. Das geht bei dir natürlich nicht, wenn du einzelne Felder überarbeiten willst.

    PS3. Das Problem mit der fehlenden Spalte kann ich mangels Informationen über die Datenstruktur natürlich nicht nachvollziehen.
    Zuletzt editiert von Jürgen Thomas; 12.05.2009, 09:42. Reason: PS2 + PS3 eingefügt

    Comment


    • #3
      Danke für deine schnelle Antwort Jürgen :-)

      Wenn ich folgenden Code schreibe wird die erste Zeile meiner Access DB korrekt kopiert. In allen weiteren Zeilen steht in jedem Feld leider nur "null"

      Code:
       foreach (AccessDS.AccessdbStrecke1Row zeile in aDS.AccessdbStrecke1)
              {
                  int x = 0;
                  DataRow newrow = sDS.Tables[0].NewRow();
                  sDS.Tables[0].Rows.Add(newrow);
                  sDS.Tables[0].Rows[x][0] = aDS.Tables[0].Rows[x][0];
                  sDS.Tables[0].Rows[x][1] = aDS.Tables[0].Rows[x][1];
                  sDS.Tables[0].Rows[x][2] = aDS.Tables[0].Rows[x][2];
                  sDS.Tables[0].Rows[x][3] = aDS.Tables[0].Rows[x][3];
                  sDS.Tables[0].Rows[x][4] = aDS.Tables[0].Rows[x][4];
                  x++;
              }
      Das Problem mit der fehlenden Spalte kommt, wenn ich z.B. folgenden Code verwende und die Zeile 6, in die ich schreiben möchte, noch nicht auf der SQL DB exisitert.

      Code:
      sDS.Tables[0].Rows[5][4] = aDS.Tables[0].Rows[1][4];

      Comment


      • #4
        Hallo Mark,

        entschuldige, aber dein jetziger Code ist zumindest reichlich umständlich und wird dadurch fehlerhaft.

        Die foreach-Schleife muss über eine Collection gehen, also über SourceTable.Rows. Dann hast du jede dieser Zeilen direkt im Zugriff; es gibt keinen Grund, auf der Quelle mit Rows[x] zu arbeiten. Es gibt auch überhaupt keinen Grund, die Variable x zusätzlich mitzuschleppen.

        Diese Variable wird außerdem (größter Mist in dieser Situation!) in jedem Schleifendurchlauf neu erstellt und zuerst auf 0 gesetzt. Also werden immer nur die Werte der ersten Zeile übernommen und sonst nur Standardwerte eingetragen (i.d.R. null). Am Ende der Schleife wird ihr Wert um 1 erhöht, danach wird sie ungültig und an den GC übergeben. Ihr Geltungsbereich ist nur der einzelne Schleifendurchgang!

        Die neue Zeile muss zuerst mit Werten gefüllt werden, erst danach wird sie der Rows-Auflistung der DestinationTable hinzugefügt. Warum willst du nicht meinen obigen Code übernehmen? Das ist wirklich das einfachste Verfahren!

        Das Problem mit der fehlenden Spalte kommt, wenn ich z.B. folgenden Code verwende und die Zeile 6, in die ich schreiben möchte, noch nicht auf der SQL DB exisitert.
        Das verstehe ich nicht. Was hat eine fehlende Spalte mit einer fehlenden Zeile zu tun?

        Bei diesem Vorgehen setze ich natürlich voraus, dass die Spalten beider Tabellen einander entsprechen; sonst wäre eine Übergabe von Werten per Index sowieso sinnlos. Ob Zeilen beim Update-Befehl per InsertCommand oder per UpdateCommand übertragen werden, hängt nur vom DataRowState ab; die DataTable kann an dieser Stelle nichts davon wissen, was in der SQL-DB gespeichert ist. Entweder du musst vorher bei jeder Zeile, die aus der Access-DataTable übernommen wird, prüfen, ob sie in der SQL-DB schon vorhanden ist; oder du musst beide Update-SqlBefehle ändern auf (wobei ich hoffe, dass MS-SQL diese Konstruktion kennt):
        Code:
        string sql = "INSERT OR UPDATE ..."
        Gruß Jürgen

        Comment


        • #5
          Ich habe das Problem mit folgendem Code gelöst hoffe ich:

          Code:
          int count = accessDT.Rows.Count;
          DataRow newrow2 = sDS.Tables[0].NewRow();
          for (int y = 0; y < count; y++)
            {
            newrow2[0] = aDS.Tables[0].Rows[y][0];
            newrow2[1] = aDS.Tables[0].Rows[y][1];
            newrow2[2] = aDS.Tables[0].Rows[y][2];
            newrow2[3] = aDS.Tables[0].Rows[y][3];
            newrow2[4] = aDS.Tables[0].Rows[y][4];
            sDS.Tables[0].Rows.Add(newrow2);
            SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(sqlDA);
            sqlDA.InsertCommand = cmdBuilder.GetInsertCommand();
            sqlDA.UpdateCommand = cmdBuilder.GetUpdateCommand();
            sqlDA.Update(sDS.SqldbStrecke1);
            sDS.Tables[0].Rows.Clear();
            }
          Der Code ist jedoch sehr wahrscheinlich viel zu aufwendig. Falls jemand eine bessere Idee hat würde ich mich sehr freuen.

          mfg Mark

          Comment


          • #6
            Sorry ich hatte deine letzte Antwort noch nicht gelesen weil ich gerade selbst einen Eintrag am schreiben war. Ich versuche es jetzt mit deiner Foreach Schleife.
            Vielen Dank für deine Hilfe!

            Comment


            • #7
              Vielen vielen Dank Jürgen. Ein Glück gibt es noch so hilfsbereite Menschen wie Dich.
              Folgender Code funktioniert super:

              Code:
              foreach (DataRow row in accessDT.Rows)
                      {
                          DataRow newrow = sqlDT.NewRow();
                          newrow[0] = row[0];
                          newrow[1] = row[1];
                          newrow[2] = row[2];
                          newrow[3] = row[3];
                          newrow[4] = row[4];
                          sqlDT.Rows.Add(newrow);
                      }
              SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(sqlDA);
              sqlDA.InsertCommand = cmdBuilder.GetInsertCommand();
              sqlDA.UpdateCommand = cmdBuilder.GetUpdateCommand();
              sqlDA.Update(sqlDT);
              mfg Mark

              Comment

              Working...
              X