Zum Inhalt springen

Argbeil

Mitglieder
  • Gesamte Inhalte

    433
  • Benutzer seit

  • Letzter Besuch

Alle Inhalte von Argbeil

  1. Argbeil

    Eigene Events

    Dann ist es auch gute Praxis in der Klasse nicht direkt das Event zu Feuern, sondern eine protected virtual Methode zu erstellen in der dann nicht anderes gemacht wird als das Event auszulösen. Damit kannst du in abgeleiteten Klassen vor dem Feuern des Events noch andere Dinge einschieben oder die Methode überschreiben um das Event gar nicht mehr auszulösen. Diese Variante ist Thread-Safe: protected virtual OnMyEvent(MyEventArgs e) { EventHandler<MyEventArgs> handler = MyEvent; if (handler != null) { MyEvent(this, e ); } } In dem setter aus dem vorherigen Beispiel könnte man also direkt OnMyEvent( e ) aufrufen und so die null Prüfung sparen, wenn man mehr als einen Aufruf des Events hat spart man Code.
  2. Argbeil

    TreeNode Tooltip

    Ah, das mit den festen Werten ist interessant. Sieht nach einem Bug aus, kann ich mir aber andererseits auch schlecht vorstellen bei so einer Standard-Komponente. Hast du mal gegoogelt ob jemand ähnliche Probleme hat?
  3. Argbeil

    TreeNode Tooltip

    Die gelieferten Maus-Koordinaten - beziehen die sich auf ein Koordinatensystem innerhalb des Treeviews oder innerhalb des Forms? Und die Koordinaten innerhalb der Show Methode, Form oder TreeView? Da wird der Fehler liegen.
  4. Dann bau doch mal um dein Application Objekt ein try catch und gib eine detaillierte Fehlermeldung aus, inkl. aller InnerExceptions, kann man z.B. so machen: try { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } catch (Exception ex) { StringBuilder sb = new StringBuilder(); while (ex != null) { sb.Append("-->"); sb.Append(ex.Message); ex = ex.InnerException; } MessageBox.Show( sb.ToString(), "Unhandeled Exception", MessageBoxButtons.OK, MessageBoxIcon.Stop); throw; } Trotz allem - eine Windows Anwendung sollte niemals eigene Daten in oder unter ihrem Programmverzeichnis ablegen, dafür sind die genannten Special Folders da. Auch bei nur einem Benutzer funktioniert sonst das Roaming nicht.
  5. Ne, das Problem bleibt ja das gleiche. Wenn auf dem Rechner z.B. Terminal Services laufen können zwei User beim zeitgleichen Zugriff Probleme bekommen. Aber das wird auch nicht das generelle Problem sein, hier sollte eigentlich eine SecurityException oder sowas geworfen werden. Kann es sein das deine Anwendung ein WPF Frontend hat und du keinen globalen Exception Handler geschrieben hast?
  6. Ich weiß nicht ob es daran liegt ohne das Programm zu kennen, aber: In diesen Ordner darf eine Applikation "niemals-nie" Daten schreiben, das ist schon seit Windows 2000 eine Microsoft Guideline für Windows Entwicklung. Damit macht man sehr viele Funktionen unmöglich (User-Roaming, Terminal Services, Clusterfähigkeit, generelle Multi-User Nutzung, ..). Ich hab die genaue Entwicklung nicht im Kopf, aber ich glaube seit Vista braucht man Admin Rechte dafür und seit 7 geht es gar nicht mehr, am besten mal selber nachsehen, für jeden Windows Version gibt es da Regeln. Das "Problem" ist, das Microsoft zwar gesagt hat "macht es nicht" aber das OS es nicht direkt verboten hat. Für Applikationsdaten gibt es den ApplicationData Folder, den bekommst du über: Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) Für User-Spezifische Daten gibt es den UserData Folder.
  7. Ah so. Den Forms-Designer verwende ich nicht, der Fehler ist mir auch nicht bekannt.
  8. Ein Subfolder unter dem Programme-Ordner? Teste mal ohne Admin Rechte.
  9. Klar kann man alles von Hand machen, der Designer generiert ja auch nur Code über den Schema Generator, das der Aufwand "etwas" größer ist finde ich untertrieben. Mit performanter arbeiten meinst du dann vermutlich die Runtime-Performance? Wenn wir über das reine, erzeugte typisierte Dataset bzw. die DataTables reden glaube ich nicht das du messbare Performance Verbesserungen sehen wirst. Methoden für asynchrones laden stellen komischerweise weder der TableAdapter noch ein DataAdapter zur Verfügung, ist aber relativ leicht zu implementieren, da für lohnt selbstschreiben auch nicht. Der erzeugte TableAdapter ist eine partial class. Du kannst dir z.b. eine AsyncGet Methode hinzufügen, stellst den GetData() Job in einen ThreadPool und feuerst beim beenden ein Event mit der befüllten Table als EventArgs, ist ein 2 Zeiler. Die partielle Klasse bleibt auch bei Änderungen im Designer erhalten. Könnte z.B. so aussehen: public partial class AddressTableAdapter { public void AsyncGet() { ThreadPool.QueueUserWorkItem(new WaitCallback(this.ThreadWorker)); } public void ThreadWorker(object state) { AdventureWorksDataSet.AddressDataTable table = this.GetData(); // Event auslösen mit Table als EventArgs... } } Den beschriebenen Fehler hab ich noch nie geseheh, klingt aber nach einem Problem mit dem Background-Compiler, bei mir (VS2008SP1) tritt das nicht auf. Reden wir von dem Forms Designer oder vom Dataset Designer? Durch die Returns wird vermutlich der Schema-Generator neu gestartet, dann müsste aber auch ein Rebuild helfen, möglicherweise ist auch beim Dataset nicht der MSDataSetGenerator als Build-Tool eingestellt.
  10. Dem Ratschlag den Designer generell nicht zu verwenden kann ich nicht zustimmen, generell ist das schon ein gutes Werkzeug. Wir haben hier eine mehrschichtige, komplexe Client/Server Anwendung, die Datenbank hat ca. 200 Tabellen und produktiv ca. 1TB Datenvolumen. Solange man sich an gewisse Regeln hält funktioniert der Designer eigentlich ganz gut, das befüllen der Tabellen realisieren wir über einen eigenen SQL-Generator in Kombination mit einem DataAdapter. Sicher kann man das auch über untypisierte Datasets lösen, die bringen aber viele Nachteile mit sich (Keine Typsicherheit, Performance Nachteile durch Boxing/Unboxing, schlechte Validierungsmöglichkeiten, keine benannten Spaltenproperties, etc...) Man sollte generell versuchen nicht mehr als 10 Tabellen in ein Dataset zu packen. Wenn man die Datasets logisch trennt (CustomersDS, OrdersDS, ...) läuft das eigentlich ganz gut und hat eine bessere Übersicht. Für das nächste Projekt würde ich O/R Mapper wie NHibernate oder Entity Framework in Kombination mit Views und Insert-Triggern verwenden sofern es noch kein Datenbankmodell gibt, aber die Variante mit typisierten Datasets haben sich bei uns sehr gut bewährt und funktionieren auch für komplexere Anfroderungen sehr gut (Master/Detail Forms, Paging, nachladen beim scrolling, etc.), zudem ist die Performance gut. Schneller geht es unter .net nur mit DataReadern, die machen aber auch wieder die Entwicklungsproduktivität kaputt.
  11. Stehen im Windows Eventlog Details? Hast du mal .net 3.5 sp1 getestet? War die Entwicklungsumgebung XP? Schreibst du Daten in den Programme Ordner? Ist der ausführende User Administrator?
  12. Ich lese hier immer wieder von SQL-Statements die von Hand über String-Concatenation zusammengebaut werden. Achtung: Das hat mehrere gravierende Nachteile und ist unnötig. Bevor man mit so was loslegt sollte man sich mit ADO.NET, also der Datenbankschnittstelle im .NET Framework beschäftigen, empfehlenswert ist hier z.B. das Buch ADO.NET Core Reference von MS-Press. Zu den Nachteilen der Statement-Selbstbau-Version: Der Compiler kann syntaktische Fehler in eurem SQL-Code nicht validieren. Das Resultset kann evtl. nicht automatisch an ein Formular bzw. eine WebPage gebunden werden Es findet keine Typ-Validierung statt Es gibt keine Validierung falls bei einer DELETE/UPDATE Anwendung die Daten bereits von einem anderen User geändert wurden Für jede CRUD Operation muss viel Code geschrieben werden Sicherheitslücke: Wenn jemand sowas wie DELETE FROM Tabelle where + txtboxDaten.Text schreibt, kann man in der Textbox jedes beliebige SQL Kommando gegen die Datenbank absetzen! Wenn ich in die Box ein ; DELETE FROM Tabelle; eingebe wird daraus folgendes SQL Kommando: DELETE FROM Tabelle where; DELETE FROM Tabelle; Je nach Datenbank wird das erste Statement mit einem Fehler quittiert, das zweite aber wird trotzdem ausgeführt und löscht die komplette Tabelle!! An der Stelle MUSS man mit SqlParameter Objekten arbeiten, alles andere wäre grob Fahrlässig! Es folgt ein grober Crash-Kurs wie man in VS2008 mit einem SQL Server viel leichter an die Daten kommt (geht auch mit anderen DBs, für Oracle müssen dafür z.B. die kostenlosen ODP.NET Tools installiert werden, auch MySQL und so gut wie jeder andere Hersteller bietet solche Provider an). Der Crash Kurs macht das lesen einer guten ADO.NET Einführung auf keinen Fall überflüssig. Es gibt auch noch andere Möglichkeiten, ich zeige hier nur eine. 1. VS starten, neues Windows Forms Projekt erstellen (Projekttyp ist eigentlich egal, es geht mit jedem Projekt) 2. Auf Ansicht->Serverexplorer gehen, Rechtsklick auf Datenverbindungen, neue Verbindung erstellen. 3. Verbindungsdaten eintragen (Achtung, SQL-Server Authentifizierung ist unsicher, besser Windows-Authentifizierung, wenn das nicht geht euren Admin ansprechen!) 4. Mit Klick auf Testverbindung prüfen ob es geht, wenn nicht anpassen. Dann auf OK klicken. 5. Im VS-Menü oben auf Daten->Neue Datenquelle hinzufügen klicken, Datenbank wählen. 6. Eure gerade erstelle Verbindung wählen, unten auf JA klicken (hierdurch wird in die app.config der Datenbank-Connection String hinzugefügt, aufpassen wenn Passwörter hinterlegt sind, bei Windows-Authentifizierung steht hier praktischerweise kein Passwort) 7. Im nächsten Schritt kann man dem ConnectionString in der app.config einen Namen geben, in meinem Falle z.B. AdventureWorksConnectionString 8. Jetzt die benötigten Tabellen, Views und StoredProcs wählen, in meinem Fall der AdventureWorks DB z.B. die Tabellen Adress und AdressType. Im unteren Bereich des Fensters kann man dem Dataset einen Namen geben, bei mir z.b. AdventureWorksDataSet. Dann auf "fertig stellen" klicken. 9. Dem Projekt wurde jetzt eine app.config mit den Connection-Infos hinzugefügt und ein AdventureWorksDataSet (kann man per Doppelklick im Projektmappen-Explorer öffnen) 10. Wenn ihr das Dataset öffnet, erscheint ein (schicker) Designer. Hier seht ihr eure Datenstruktur. Diese Struktur kann jetzt auch vom Compiler validert werden, in den Eigentschaften der Spalten finden sich z.B. auch Informationen zum Datentyp. Zu jeder Tabelle wurde ein TableAdapter generiert, dieser verbindet die erzeugten Strukturen mit der echten Datenbank aus der app.config. Per Default werden Fill & GetData Methoden erzeugt. 11. Per Rechtsklick auf die Methoden kann man Datenvorschau zum testen wählen. Auch per Rechtsklick kann man Abfragen hinzufügen. Es macht z.B. nicht immer Sinn ALLE Adressen zu laden, um eine Methode zu erstellen die Alle Adressen aus einer bestimmten City lädt macht man folgendes: 11a) Rechtsklick auf die Fill, GetData() Methode des AdressTableAdapter, Abfrage hinzufügen wählen. 11b) SQL-Anweisungen verwenden, weiter, Select Anweisung die Zeilen zurückgibt, weiter. 11c) Der Wizard erzeugt ein: SELECT AddressID, AddressLine1, AddressLine2, City, StateProvinceID, PostalCode, rowguid, ModifiedDate FROM Person.Address wir machen daraus ein: SELECT AddressID, AddressLine1, AddressLine2, City, StateProvinceID, PostalCode, rowguid, ModifiedDate FROM Person.Address WHERE City = @City Über den Button Abfrage-Generator kann die Abfrage getestet werden, eine gültige Stadt ist z.B. Berlin 11d) Weiter klicken, als Namen vergebe ich FillByCity und GetDataByCity, fertig stellen anklicken. 12. Jetzt können wir mit Code loslegen, laden aller Adressen geht so: (zuerst using einfügen, normalerweise using projektname.AdventureWorksDataSetTableAdapters;) // Unser Datenlieferant mit Verbindung zur Datenbank: AddressTableAdapter adressAdapter = new AddressTableAdapter(); // Leere Adressen Tabelle im Speicher anlegen: AdventureWorksDataSet.AddressDataTable adressesTable; // Laden aller Daten... adressesTable = adressAdapter.GetData(); // oder laden aller Adressen aus Berlin adressesTable = adressAdapter.GetDataByCity("Berlin"); // durchlaufen der Adressen foreach (AdventureWorksDataSet.AddressRow row in adressesTable) { // Jede Stadt anzeigen... MessageBox.Show(row.City); } // Alle mit PLZ 141111 nach Ratingen verschieben.... foreach (AdventureWorksDataSet.AddressRow row in adressesTable.Select("PostalCode = 14111")) { row.City = "Ratingen"; } // Es wurden jetzt nur die geladenen Datensätze im Speicher geändert, um die Änderungen // in die Datenbank zu schreiben: adressAdapter.Update(adressesTable); // Weil wir auf der CeBit keinen Parkplatz bekommen haben löschen wir jetzt alle Einträge aus Hannover... // Laden... adressesTable = adressAdapter.GetData(); // Zum löschen markieren... foreach (AdventureWorksDataSet.AddressRow row in adressesTable.Select("City = 'Hannover'")) { row.Delete(); } // In der Datenbank löschen... adressAdapter.Update(adressesTable); 13. Einfach oder? Um alle Daten in einem Grid anzuzeigen zieht man einfach ein DataGridView auf das Form und lässt, z.b. im Konstruktor folgenden Code ausführen: AddressTableAdapter myAdapter = new AddressTableAdapter(); this.dataGridView1.DataSource = myAdapter.GetData(); 14. Wurden Daten im Grid geändert kann man z.B. so wieder speichern: myAdapter.Update((AdventureWorksDataSet.AddressDataTable)this.dataGridView1.DataSource);
  13. Mach es doch direkt über den Table Adapter. Du kannst deine Row aus der DataTable direkt im Code über myTable.Select("Eintrag = XY") oder per Linq über "from row in table.Rows where row.Eintrag == XY select row;" auswählen. Auf die selektierte Row machst du ein row.Delete(); Danach kannst du auf deinen TableAdapter oder auf den DataAdapter Update aufrufen um die Daten mit der Datenbank zu synchronisieren. Vorteil: weniger Code, kein SQL. Die Variante in der du die Einschränkung aus dem Textfeld nimmst ist eine potentielle Sicherheitslücke für SQL-Injection. Wenn jemand in die Textbox nichts tippt löscht er ansonsten ALLE Datensätze, wenn jemand "; DELETE FROM tab_spot; eingibt ist die komplette Tabelle weg, du solltest also mindestens mit Parametern arbeiten.
  14. Das Problem hatte ich noch nicht, allerdings klingt 100 Tabellen in einem Dataset extrem gefährlich. Wenn du das Dataset mal serialisieren willst hast du sofort extrem viel Overhead, Xml ist ein geschwätziges Protokoll. Kannst du die Tabellen nicht logisch auf mehrere Datasets verteilen? Vermutlich kommt der Xml/C# Generator mit der Menge nicht klar.
  15. :uli Let me google that for you :bimei
  16. Die WF4 hat sich tatsächlich wesentlich geändert, wenn es geht warte noch bis März und besorge dir dann ein gutes WF4 Buch. Die bestehenden Lösungen auf Basis der WF Engine zeichnen sich meistens durch schlechte Performance aus. Du kannst auch schon jetzt die WF4 in der Beta2 von VS2010 verwenden, läuft ganz stabil, aber die Doku ist noch Mau.
  17. Sehr schönes Beispiel für SQL-Injection Angriffe, kann ich das in einer Schulung verwenden?
  18. Ich kann dir nicht folgen. Du möchstest eine dynamische Navigation? Du programmierst in ASP.NET? Welche Version? ASP.NET MVC oder Classic? Das mit dem Grid kannst du ohne Click nur über Javascript/AJAX prüfen, was hast du denn mit der Information vor?
  19. Du kannst das Script aus dem Codebehind heraus natürlich nur dann ausführen wenn auch gerade ein Request/Response stattfindet. Ich frag ja gerne: was hast du eigentlich vor?
  20. Hi .NETter, bist der Thomas von BeCon ?

  21. Da gibts ziemlich viele Berechtigungen auf eine Tabelle, nicht vergessen darf man auch noch Server-Berechtigungen wie: Darf der User sich überhaupt einloggen und welches Login wird mit welchem Owner verknüpft. Managing Users Permissions on SQL Server — DatabaseJournal.com GRANT (Transact-SQL)
  22. Naja, es gibt kleine Variationen, du kannst du auch erst die komplette Datei in ein Array einlesen, dann über die gesamte Datei In-Memory laufen, die entsprechenden Einträge entfernen und dann die komplette Datei wieder speichern, aber das ist Speicherintensiv und nicht unbedingt schneller.
  23. Du hast mehrere Möglichkeiten. Schreib die Daten in ein Objekt und packe diese in deine Session Variable, auf der zweiten Seite kannst du sie wieder auslesen. 2. Auf der 2. Seite auf die Controls der ersten zugreifen (ich glaube das ging irgendwie mit PreviousPage und FindControl) oder die Request-Parameter auslesen (davon würde ich aus Sicherheitsgründen abraten, obwohl es die Ressourcensparende Variante ist.
  24. Erstelle ein typisiertes Dataset deiner Tabelle, befülle die entprechenden Rows der DataTable und rufe die UpdateMethode des Table Adapters auf, der erzeugt den SQL Code automatisch. Was extrem hilft ist erstmal das Konzept von DataSets und DataAdaptern kennen zulernen.
  25. Aus dem dbo. schließe ich das du einen SQL Server verwendest? Welche Version? Gehen wir mal davon aus das du keinen Index hast und die Abfrage nicht optimiert ist (hier gibts natürlich sehr viel Optimierungspotentzial) - der SQL Server darf im Normalfall trotzdem nur wenige Sekunden dafür brauchen, mit deinem Server stimmt also vermutlich auch etwas nicht. mach mal ein select * auf die Tabelle und führe dann die gleiche Abfrage nochmal aus. Wenn der Server genügend RAM hat muss er durch das select * from table die komplette Tabelle in Memory gecached haben und es ist kein Plattenzugriff mehr nötig, die Abfrage sollte auf einem halbwegs aktuellen Rechner dann vielleicht noch 2 Sekunden benötigen. Wenn das nicht der Fall ist: Wie viel RAM hat der Server? Wie viel Speicher ist frei? Wie groß ist die Datenbank? Auf welchen Speicherverbrauch ist der SQL Server konfiguriert? Passiert auf dem Server während deiner Abfrage noch was anderes?

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...