Announcement

Collapse
No announcement yet.

Datenbank ADO.NET zu langsam??

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

  • Datenbank ADO.NET zu langsam??

    Hallo,

    ich habe festgestellt, das wenn meine Anwendung startet und die Daten aus der Datenbank geladen werden (Speziell geht es um Rohstoffe, bei denen auch Bilder hinterlegt sind. Die Tabelle Rohstoffe hat ca. 8 MB. Mein Programm lädt diese Daten in eine ObservableCollection. Dies dauert ca. 30-60 sekunden!
    Ich kann gerne Code posten, aber es ist ja nur ein paar zeilen Code die das machen. Kann das sein, oder gibt es andere Dinge die ich vielleicht nicht beachtet habe?

    Habe jetz mal einige Bilder gelöscht, dann gehts schneller. Meine zweite Frage darum: Falls das die Lösung ist, wo verwalte ich dann meine Bilder, wenn nicht in der Datenbank?

    MfG und Danke!
    Die Taschenlampe!

    Die perfekte Taschenlampe für Ihr Windows Phone!

    - Die APP steuert die echte Blitz-LED an und versorgt Sie mit 100% Leistung!
    - Zudem zeigt die Live-Kachel den aktuellen Akkustand des Telefons an!


    Hier gehts zu APP!

  • #2
    Hallo,

    ADO.net ist keine Datenbank, sondern eine Zugriffstechnologie für Datenbanken.

    wo verwalte ich dann meine Bilder, wenn nicht in der Datenbank?
    Das passt schon so. Wenn allerdings die Bilder riesig sind, so dauert es halt lange, v.a. wenn dazwischen noch ein Netzwerk, ect. ist. Daher wäre es möglich zusätzlich zu den Bilder noch Thumbnails zu speichern und erstmal nur diese zu laden. Wenn dann z.B. in einer Detailansicht das große Bild benötigt wird, so wird dieses geladen (und lokal vorgehalten - z.B. in den %Temp%-Ordner speichern, siehe Environemtn.Specialfolders) und dann angezeigt.

    Das Laden sollte auch immer asynchron erfolgen, also nicht im GUI-Thread.

    mfG Gü
    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

    Comment


    • #3
      Hi!

      Danke erstmal. Ich habe gleich versucht dies so umzusetzen, und lasse nun einen Backgroundworker die jeweiligen Daten im Hintergrund laden. "jedes" Usercontrol hat einen eigenen Backgroundworker. Momentan 4 Usercontrols.
      Nun bekomme ich aber immer Fehlermeldungen, wie z.B. die hier: Ein Element mit dem gleichen Schlüssel wurde bereits hinzugefügt.
      Klar, die BGW's greifen auf die gleiche void zu um eine "ObservableCollection" zu füllen. Aber jedes UserControl hat definitiv seine eigene Observablecollection welche auch nur es selbst nutzt. Wie kommen solche überschneidungen??

      Zur Ergänzung, in der Window_Loaded meines Hauptfensters, werden alle Usercontrols nacheinander geladen, wobei jedes Usercontrol selbst dann seinen BGW startet.

      Liegt es evtl. an meinen einzigen langlebigen DBContext?? Arbeite wie oben angesprochen mit Ado.NET.

      MfG und Vielen Dank!!!
      Zuletzt editiert von Flo_Plus; 24.07.2012, 17:24.
      Die Taschenlampe!

      Die perfekte Taschenlampe für Ihr Windows Phone!

      - Die APP steuert die echte Blitz-LED an und versorgt Sie mit 100% Leistung!
      - Zudem zeigt die Live-Kachel den aktuellen Akkustand des Telefons an!


      Hier gehts zu APP!

      Comment


      • #4
        Hallo,

        Liegt es evtl. an meinen einzigen langlebigen DBContext??
        Ja genau das ist das Problem. Der DbContext ist nicht threadsicher und somit liegt eine Race-Bedingung beim gemeinsamen Zugriff auf die geteilte Ressource, den DbContext, vor.

        Verwende besser nur einen Backgroundworker um die Daten zu laden, dann kommt es zu keinem Race. Persönlich würde ich ganz auf den BGW verzichten und lieber mit Tasks und deren Continuations arbeiten.

        Hast du den Vorschlag mit den Thumbnails und dem lokalen Cache aufgegriffen? Dann sollte es schon ziemlich schnell gehen. Zusätzlich könntest du mit einem weiteren Task und einem extra DbContext die großen Bilder nebenläufig in den lokalen Cache laden, so dass diese bei Bedarf bereits vorhanden sind.
        Werden mehrere DbContexte verwendet, so wird der gleichzeitige Zugriff auf eine Ressoruce in die Datenbank verlegt und jede vernüftige Datenbank kann damit problemlos umgehen.

        mfG Gü
        "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

        Comment


        • #5
          Hallo,

          den Vorschlag habe ich angenommen. Aber ich denke ich sollte den ganzen Startprozess überdenken... Ich lade wie gesagt alle UserControls in der Window_Loaded meines Hauptfensters. Und das Usercontrol Rohstoffe lädt eben alle Rohstoffe, Lieferanten alle Lieferanten usw...
          Ist das so sinnvoll alle Daten der Datenbank bereits beim Programmstart zu holen?
          Wenn ich jedes Usercontrol erst wenn es gebraucht wird (also angezeigt werden soll), seine Daten holen lasse entstehen natürlich hier immer kurze Wartezeiten.

          Vielleicht hat jemand Erfahrungswerte?

          MfG!
          Die Taschenlampe!

          Die perfekte Taschenlampe für Ihr Windows Phone!

          - Die APP steuert die echte Blitz-LED an und versorgt Sie mit 100% Leistung!
          - Zudem zeigt die Live-Kachel den aktuellen Akkustand des Telefons an!


          Hier gehts zu APP!

          Comment


          • #6
            Originally posted by Flo_Plus View Post
            Vielleicht hat jemand Erfahrungswerte?
            Der Erfahrungswert ist:
            Ein einzelnes System (DB & Client) muss schon ziemlich brutal aufgesetzt werden, damit es zu negativen, spürbaren Effekten für den Anwender kommt.
            Im Multiuserbetrieb zeigen sich mit wachsender Anzahl der Nutzer alle "Schwächen" oder nennen wir es Resourcen intensive Momente einer Anwendung.

            Ein Beispiel in Deinem Fall: Die "Initialisierung" aller Componenten mit allen Daten zum Programmstart stellt sich schon in der Entwicklungsphase (1 Mann Betrieb) als zeitkritisch dar. Im Echtbetrieb wäre der worst case morgens 8:30 im Büro, wenn alle(10, 20, 100, 1000 ?) Mitarbeiter die Anwendung starten und ihre GUI Componenten mit Daten befüllen.

            Man muss nicht groß rechnen, um das Problem zu sehen!
            Das Beispiel trifft natürlich nicht zu, wenn "klar" ist, dass es nie 10, 20 oder 1000 Anwender gleichzeitig geben wird. Solche Annahmen haben sich erfahrungsgemäß aber schon oftmals als falsch entpuppt.
            Gruß, defo

            Comment


            • #7
              Das heißt? Wie genau würdest du die Daten holen? Jedes UserControl "erst" sobald es geöffnet wird, dann im speicher halten, oder immer neu laden?
              Wäre für ein paar Erfahrungswerte sehr dankbar.
              Ich habe mich durch das Internet und dieses Forum schon sehr stark entwickelt, da ich das Programmieren nie gelernt habe, und dieser Produktmanager entstand/entsteht daher, da man in der firma in der ich beschäftigt bin alles noch per Excel usw machte, also ziemlich Aufwändig.
              Ich gebe zu, genau solche "Fehler" passieren mir weil ich es noch nie gemacht habe.

              Wäre echt dankbar für eine kleine Beschreibung einer guten Strategie die zu ADO.NET passt. Den Anwender werden es später ca. 60 sein, also ein ganzer haufen...

              EDIT: Momentan löse ich das so: Das Programm initialisiert ALLE UserControls direkt beim start. Somit ist die Anwendung 100% geladen. Die Daten der Datenbank allerdings werden erst geholt wenn das dementsprechende UserControl sichtbar wird (ChildWindow Verfahren). Wenn das UC seine Daten dann geholt hat, speichert es diese natürlich, dass es nicht jedesmal alles neu holen muss. Finde es läuft jetz doch recht schön. Gute Lösung?

              Vielen Dank im Voraus für eure wie immer tolle Hilfe!!
              Zuletzt editiert von Flo_Plus; 25.07.2012, 10:30.
              Die Taschenlampe!

              Die perfekte Taschenlampe für Ihr Windows Phone!

              - Die APP steuert die echte Blitz-LED an und versorgt Sie mit 100% Leistung!
              - Zudem zeigt die Live-Kachel den aktuellen Akkustand des Telefons an!


              Hier gehts zu APP!

              Comment


              • #8
                Hallo,

                genau solche "Fehler" passieren mir weil ich es noch nie gemacht habe.
                Siehe es positiv. Das ist genau die richtige Chance aus den "Fehlern" zu lernen. Du hattest keine Erfahrung und nun bist du um diese Erfahrung reicher. Du lernst ständig dazu, mir ging und geht es nicht anders.

                Wie genau würdest du die Daten holen?
                Meist ist es besser "lazy" zu agieren. D.h. die Objekte, UserControls, Daten, etc. erst dann zu erstellen bzw. zu laden, wenn diese tatsächlich das erste mal benötigt werden.
                Während der Programmausführung können diese Daten dann ruhig im Arbeitsspeicher verweilen, vorausgesetzt es werden nicht Unmengen an RAM belegt, damit sonst keine andere Anwendung mehr arbeiten kann. Sollte es damit zu Problemen kommen, so können die Objekte, Daten, etc. verwerfen werden und bei Bedarf neu erstellt bzw. neu geladen werden.
                Daten die sich mit ziemlicher Wahrscheinlichkeit nie ändern werden, können auch lokal auf die Festplatte gespeichert werden in Environment.SpecialFolder.ApplicationData od. Environment.SpecialFolder.CommonApplicationData, wie in diesem Fall eben die Bilder.

                einer guten Strategie die zu ADO.NET passt
                Da du oben auch DbContext erwähnt hast: mit ADO.NET meinst du eh das Entity Framework? Wenn dem so ist, dann ist eine gute Strategie mit Repositories und UnitOfWork zu arbeiten. Siehe hierzu Using Repository and Unit of Work patterns with Entity Framework. Die UnitOfWork, zu deutsch Arbeitseinheit, sollte auch so behandelt werden, wie es der Name suggeriert. D.h. genau so lange leben wie eine Arbeitseinheit vorhanden ist bzw. für die Dauer eines Use Cases.

                Angenommen es soll einem Lieferanten ein Rohstoff hinzugefügt werden: UnitOfWork erstellen, Daten bearbeiten bzw. hinzufügen, UnitOfWork.Save(), UnitOfWork.Dispose()
                So ist auch mit gewisser Wahrscheinlichkeit sichergestellt, dass die Daten im DbContext nicht schal werden und immer ziemlich aktuell sind.

                Und dass lange Operationen (in Bezug auf das GUI alles das länger als 1/10s dauert) in einen eigenen Thread ausgeführt werden sollen habe ich oben schon erwähnt.

                mfG Gü
                "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

                Comment


                • #9
                  Vielen Dank euch allen! Jetz läuft das Ding schon schöner!

                  Eine "Schönheitsfrage" bezgl. C# hätte ich aber noch: Wenn man einiges in der Window_Loaded zu erledigen hat, neigt das Fenster beim Starten dazu den Rahmen anzuzeigen und anstatt den Fensterelementen nimmt der Hintergrund das gerade Sichtbare auf dem Monitor an.

                  Wenn ich in der App.xaml.cs allerdings die UserControls, Datenbank usw. initialisiere startet die Anwendung insgesamt noch schneller... Ist es richtig Fenster usw. zu laden, dem Hauptfenster zuzuweisen und DANACH erst das Hauptfenster anzuzeigen?
                  Ich meine es funktioniert, überrascht mich aber :-)


                  MfG!
                  Zuletzt editiert von Flo_Plus; 26.07.2012, 09:56.
                  Die Taschenlampe!

                  Die perfekte Taschenlampe für Ihr Windows Phone!

                  - Die APP steuert die echte Blitz-LED an und versorgt Sie mit 100% Leistung!
                  - Zudem zeigt die Live-Kachel den aktuellen Akkustand des Telefons an!


                  Hier gehts zu APP!

                  Comment


                  • #10
                    Hallo,

                    du kannst alle Views ganz normal laden und anzeigen - so wie oben erwähnt. Nur das laden der Daten sollte unbedingt asynchron erfolgen und dann wenn die Daten da sind, an die Views gebunden werden. Z.B. in einem Completed-Ereignis od. bei Task mittels Continuations. Kurz: es geht darum, dass die GUI nicht blockiert, auch nicht beim Laden.

                    mfG Gü
                    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

                    Comment


                    • #11
                      Hey. Nene, die Daten usw. laufen asynchron. Ich sollte mich deutlicher Ausdrücken: Die Datenbank-VERBINDUNG sowie das laden von zusätzlichen Fenstern, kann ich dies in der initialisierung des Hauptfensters machen, quasi nach InitializeComponents?
                      Hier läuft die Anwendung insgesamt schneller, oder müssen solche Dinge in der Window_Loaded stattfinden?

                      MfG
                      Die Taschenlampe!

                      Die perfekte Taschenlampe für Ihr Windows Phone!

                      - Die APP steuert die echte Blitz-LED an und versorgt Sie mit 100% Leistung!
                      - Zudem zeigt die Live-Kachel den aktuellen Akkustand des Telefons an!


                      Hier gehts zu APP!

                      Comment


                      • #12
                        Hallo,

                        Die Datenbank-VERBINDUNG
                        erstell die DB-Verbindung erst dann wenn sie das erste mal wirklich benötigt wird, also "lazy". Das geht mit der Lazy<T>-Klasse ab .net ganz einfach. Sonst ist es auch nicht schwer, indem eine (private) Eigenschaft verwendet mit if (_db == null) _db = new ... im Getter.

                        Bei den Fenstern analog. Sollte dies aber - aus welchen Gründen auch immer nicht möglich sein - machs es so wie du geschrieben hast nach Init-Components.
                        Schau aber, dass nach Möglichkeit beim Anwendungsstart so wenige Objekte (auch Fenster sind Objekte) wie möglich und nur so viele wie nötig sofort erstellt werden. Der Rest sollte lazy sein.

                        mfG Gü
                        "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

                        Comment

                        Working...
                        X