Laden...

Graph: Rekursive Methode, Upload OneDrive

Erstellt von Biggi12 vor 3 Jahren Letzter Beitrag vor 3 Jahren 1.121 Views
B
Biggi12 Themenstarter:in
4 Beiträge seit 2020
vor 3 Jahren
Graph: Rekursive Methode, Upload OneDrive

Hallo,

arbeite momentan an einer Consolen-Anwendung zum Migrieren von Daten in OneDrive.

Dazu Verwende ich folgende Technologien:

  • C-Sharp
  • MS Graph
  • Visual Studio
  • .Net 4.7.2

In meiner aktuellen Methode lade ich Rekursiv alle Dateien und Ordner aus dem angegeben Pfad.
Die Methode WriteFolderToOneDrive, schreibt mir die Ordner in mein OneDrive. Als Rückgabewert bekomme ich die ID vom geschriebenen Ordner, diese ID wird von OneDrive generiert und ist einmalig.

Die Methode WriteFileToOneDrive macht im Prinzip das selbe aber mit Files.....

Nun liegt irgendwo in der Rekursion der Hase begraben, hier ist meine Rekursive Methode:

 static async Task Execute(GraphServiceClient graphClien, User user, string sDir, string folderId)
        {
            try
            {
                foreach (string d in System.IO.Directory.GetDirectories(sDir))
                {
                    string folderName = new DirectoryInfo(d).Name;
                    folderId = await WriteFolderToOneDrive(graphClien, user, folderName, folderId);
                    foreach (string f in System.IO.Directory.GetFiles(d))
                    {
                        using (FileStream stream = System.IO.File.Open(f, FileMode.Open))
                        {
                            string fileName = Path.GetFileName(f);
                            await WriteFilesToOneDrive(graphClien, stream, user, fileName, folderId);
                        }
                    }
                    await Execute(graphClien, user, d, folderId);
                }
            }
            catch (Exception excpt)
            {
                Console.WriteLine(excpt.Message);
            }
        }

Um einen Ordner auf meinen Root-Verzeichnis auf OneDrive zu erstellen verwende ich folgenden Befehl:

  var folderToOneDrive = await graphServiceClient.Users[user.Id].Drive.Items.Request().AddAsync(driveFolder);
                return folderToOneDrive.Id;

Um einen Unterordner zu erstellen gebe ich die OrdnerId, die generiert wurde, mittels Items[folderId] an.

  var folderToOneDrive = await graphServiceClient.Users[user.Id].Drive.Items[folderId].Children.Request().AddAsync(driveFolder);
                return folderToOneDrive.Id;

Das Problem an diesem Code ist das er mir die Daten immer im letzten Ordner abspeichert, und nicht wieder zurück ins Root Verzeichnis geht.

In meiner Methode WriteFolderToOneDrive habe ich eine If/Else abfrage ob die Id null ist:


 if (folderId != null)
            {
                var folderToOneDrive = await graphServiceClient.Users[user.Id].Drive.Items[folderId].Children.Request().AddAsync(driveFolder);
                return folderToOneDrive.Id;
            }
            else
            {
                var folderToOneDrive = await graphServiceClient.Users[user.Id].Drive.Items.Request().AddAsync(driveFolder);
                return folderToOneDrive.Id;
            }

Meine Überlegung ist nun das ich in der Methode Execute einen schalter einbaue der den Wert von folderId auf null setzt wenn er wieder im Root Verzeichnis schreiben soll...

Hat jemand ein paar Ideen wie ich das erreichen kann ?

4.939 Beiträge seit 2008
vor 3 Jahren

Du solltest nicht die selbe Variable folderId in der Schleife benutzen, sondern eine neue erstellen.

T
2.224 Beiträge seit 2008
vor 3 Jahren

Dein Code muss auch in der Benennung der Variablen etwas besser werden.
Auch machst du Sachen, die unnötig sind.
Wenn du einen Order Namen von einem Pfad willst, kannst du dies auch mit Path.GetDirectoryName arbeiten.
Dann muss kein unnötiger Zugriff im Dateisystem gemacht werden, bei vielen Ordnern kann dies dann zu einer langen Laufzeit bei langsamen Platten führen.

Anstelle von Rekursion würde ich die Ordner und Dateien möglichst iterativ hochladen.
Wenn du eine heftige Ordner Struktur hast, kann es wegen zu viel Rekursion auch knallen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.833 Beiträge seit 2008
vor 3 Jahren

Wenn du eine heftige Ordner Struktur hast, kann es wegen zu viel Rekursion auch knallen.

Dafür könnte man Stack<T> verwenden, was dann immer noch Rekursiv wäre aber keine entsprechende Exception auslösen würde.

T
2.224 Beiträge seit 2008
vor 3 Jahren

@Abt
Kann man machen, ich würde Rekursion nur vermeiden wenn es auch ohne geht.
Und beim durchlaufen einer Ordner Struktur kann man dies auch über eine LinkedList/Queue lösen um iterativ durch zu laufen.
Dazu muss man nur am Ende einfügen und am Anfang rausnehmen.
Habe ich schon ein paar mal gebaut um größere Ordner Strukturen zu verabreiten.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

B
Biggi12 Themenstarter:in
4 Beiträge seit 2020
vor 3 Jahren

Hallo,

Ja die Variablen muss ich noch ändern..

Ich habe noch einen anderen Ansatz wo ich die Pfade und Dateien quasi liste und abarbeite.
Hätte es aber gerne Rekursiv gelöst, wenn das aber gerade bei größeren Datenmengen zu vielen Fehler führen kann werde ich den anderen Ansatz verwenden.

@T-Virus

Und beim durchlaufen einer Ordner Struktur kann man dies auch über eine LinkedList/Queue lösen um iterativ durch zu laufen.
Dazu muss man nur am Ende einfügen und am Anfang rausnehmen.

Hast du dazu ein beispiel ?

4.939 Beiträge seit 2008
vor 3 Jahren

Hast du meinen Rat nicht verstanden?
Du verwendest bei

folderId = await WriteFolderToOneDrive(graphClien, user, folderName, folderId);

dieselbe Variable und überschreibst damit die Root folderId!
Benutze

string subFolderId = await WriteFolderToOneDrive(graphClien, user, folderName, folderId);

// use subFolderId

PS: Das müßte aber eine Rekursionstiefe von mehr als ein paar Tausend (oder sogar Zehntausend) sein, damit der Stack (Default: 1MB bzw. 4MB bei 64 Bit) überläuft.
Für selbst 10 (Referenz)Werte auf dem Stack je Rekursion wären es bei x64 80 Bytes, d.h Rekursionstiefe von 50.000 möglich (und das Dateisystem wird das wohl auch kaum hinbekommen).
Und zur Not kann man mittels EditBin den Stack bei einer Anwendung (auch .NET) noch nachträglich erhöhen: /STACK.