Laden...
M
Benutzerbeschreibung
Visual Studio 2012 C# !NET Framework 4 - FÜR WINDOWS XP UNTERSTÜTZUNG! WPF, DataBinding (einschichtig) über Entity Framework, SQL-Server 2000-2012

Forenbeiträge von m.grauber Ingesamt 343 Beiträge

21.07.2010 - 16:37 Uhr

Hallo FZelle,

vielen Dank, dass Du mir wieder einmal aus der Patsche geholfen hast! 👍

In der Tat hatte ich bereits verschwommen gelesen (von einem MVP), dass man nur komplette Entitäten auslesen kann, jedoch habe ich das nicht glauben können, da diese Vorgehensweise ja für Joins und Berechnungen etc. oft notwendig ist.

Auf den ExecuteStoreQuery wäre ich sicher nicht gekommen!

Seltsam ist es für mich aber schon, dass MS in das neue EF eine extra-Funktion dafür einbaut, statt die Funktionsweise des CreateQuery zu modifizieren. Noch verwunderter bin ich, dass hier jetzt wieder T-SQL genutzt wird. Mir soll es auf jeden Fall recht sein und ich werde damit arbeiten, da ich mir den Select optimal zusammensetzen kann.

Also nochmals Tausend Dank! 👍

21.07.2010 - 14:26 Uhr

Ich habe sicher Tomaten auf den Augen, aber ich versuche es jetzt schon sehr lange. 🙁

Ich möchte auch nicht über einen DbDataRecord gehen, sondern direkt in mein Objekt hinein selektieren. Unbedingt notwendig ist mir die komplette Abfrage in Hochkommas zu schreiben, damit der String wie gewünscht zusammengesetzt werden kann. (Daher möchte ich auch kein Linq2SQL nutzen):

eine komplette Entität kann ich mir holen:


List<Kunde> myList = Entities.CreateQuery<Kunde>("SELECT VALUE Kunde FROM Kunde").ToList();

Wie kann ich aber nur einzelne Spalten in ein selbst erstelltes Objekt selektieren❔


List<TeilKunde> myTeil = Entities.CreateQuery<TeilKunde>("SELECT K.Kundenname, K.ID FROM Kunde AS K").ToList();

Hier tritt der folgende Fehler auf:

Die angegebene Umwandlung aus einem materialisierten 'System.Data.Objects.MaterializedDataRecord'-Typ in den 'TeilKunde'-Typ ist ungültig.

TeilKunde existiert wiefolgt lokal:


public class TeilKunde
{
  public String Kundenname {get;set}
  public Int ID {get;set}
}

TeilKunde sollte ein lokales Objekt sein, da es nur in dieser Form an genau einer Stelle benötigt wird.

Vielen Dank!!

21.07.2010 - 11:45 Uhr

Hallo Vines,

ich habe leider das gleiche Problem. Scheinbar gibt es noch nicht viele, die mit ObjectQuery arbeiten.

Hast Du es lösen können?

Vielen Dank!

21.07.2010 - 10:15 Uhr

Hallo,

nutzt ihr die Sortierung ganz anders oder warum kann mir dieses Problem wirklich niemand beantworten? Ich habe nun den Beitrag nochmals etwas umformuliert.

Vielen Dank

19.07.2010 - 14:09 Uhr

Hallo,

in einem WPF-Datagrid, welches die automatische Sortierung durch den User per Spaltenklick zulässt (automatisch, damit nicht zu viel programmiert werden muss), möchte ich die Sortierreihenfolge beeinflussen:

Bei einem Klick auf eine Spalte soll das DataGrid die Sortierung nach dieser Spalte vornehmen (Das funktioniert). Was nicht geht: Es soll die Sortierung nach der zuletzt sortierten Spalte als 2. Sortierbedingung beibehalten und nach der vorletzt Sortierten Spalte als 3. Sortierbedingung.

So weit bin ich: "DataGrid.Sortiung += ..." --> Damit kann ich die Sorting-Methode abfangen und kann per "sender" und "e" auf das DataGrid zugreifen.

Mit "DataGrid.Items.SortDescriptions.Add(..." kann ich wie gewünscht die 2. und 3. Sortierbedingung anfügen.

Jedoch sortiert das Datagrid nur dann nach meinen SortDescriptions, wenn ich im DataGrid.Sorted "e.Handeled=true" setze. Dabei wird aber logischerweise nur nach meinen angegebenen "SortDescriptions.Add" sortiert und der Userklick ignoriert. (Scheinbar tritt die Sorting-Methode vor dem Ausführen der Sortierung von .NET auf)

Darum habe ich die aktuelle angeklickte Spalte per SortDescriptions.Add manuell sortiert. (Sortierung auslesen und per SortDescriptions.Add menuell setzen.

Wenn also e.Handeled=true ist, wird mir aber im Header des DataGrids kein kleiner Pfeil (für auf/absteigend) mehr angezeigt, auch wenn ich manuell folgendes Eingebe:


DataGrid.Items.SortDescriptions.Add(...)
e.Column.SortDirection = System.ComponentModel.ListSortDirection.Descending

Was muss ich dafür noch zusätzlich umstellen?

Vielen Dank

16.07.2010 - 13:16 Uhr

Hallo Talla,

"komplett neue Werte" klingt für mich als wenn du nen neues ObservableCollection Objekt erstellst oder? Das darfst du natürlich nicht machen.

Exakt - das war mein Fehler! Vielen Dank für die superschnelle Hilfe! 👍 Ich kürze nun meine Eingangsfrage, damit es für alle anderen transparenter wird.

Grüße

16.07.2010 - 12:28 Uhr

Hallo,

Ein WPF-DataGrid ist gebunden und zeigt per ItemsSource=myObservableCollection Daten an.

Nach dem erneuten Zuweisen der ItemsSource ist die vom User per Klick auf die Spalte eingestellte Sortierung entfernt.

Wie bleibt die Sortierung bestehen?

Vielen Dank!

15.07.2010 - 15:15 Uhr

Hallo Erfinder des Rads,

ok, d. h. ich hatte bisher immer versucht so wenig Daten wie möglich zu laden aber merke, dass es dadurch beim späteren Update problematischer würde. Wenn die Performance an dieser Stelle trotzdem i. O. ist, werde ich sicher auch einen solchen Weg gehen.

Schöne Grüße!

15.07.2010 - 15:04 Uhr

Hallo TomLeech,

Danke für Deine Geduld!

Nein, ich meinte, dass du die Schichten erst in deiner Viewschicht generierst, also die Daten, die du zur Darstellung brauchst, und die echten Daten, wie Erfinder des Rades geschrieben hat verwendest.

Ok, jetzt habe ich es verstanden!

Wie du das mit dem Refresh() meinst ist mir ned ganz klar, dass lädt halt die Daten neu, je nach angegebener Quelle. Die dort aktuellen Daten werden geladen, welche auch immer das sind. Wieso das nicht funktionieren sollte ist mir nicht ganz klar.

Ich hatte anfangs gedacht, wenn ich einen Refresh() mache, würde er mir die Werte der Collection automatisch auch dann aktualisieren, wenn ich die Werte vom Server direkt im SELECT z.B. als Berechnung einlese: Spalte 1 + Spalte 2 AS Kalkspalte. Nun ist mir klar, das .NET nicht soweit geht und den einstmals gemachten SELECT speichert und analysiert. Und das ich mir in diesem Fall die Spalte 1 und Spalte 2 in meiner Viewschicht umsetze (obgleich nur das Ergebnis benötigt wird) und die "Kalkspalte" intern in der Viewschicht berechne!

Ich habs nun endlich verstanden.

Tausend Dank!

15.07.2010 - 14:46 Uhr

Hallo Erfinder des Rads,

es ist schön, wenn man sieht, wie verschiedene Entwickler verschiedene Möglichkeiten nutzen.

Man lädt die Tabellen bzw. Auszüge davon ins Dataset, und wenn man gejointe Views haben will bastelt man die im Gui zusammen, zb mit ComboBoxcolumns im DataGridView.

Das mit den "Auszügen" ist eine sehr gute Idee, da die "restlichen vielen Felder", die nicht momentan genutzt werden, dann zwar lokal leer sind - und noch etwas Speicher benötigen - , aber schon sehr viel weniger Daten per Select vom Server gelesen werden müssen. Auch das die Speicherroutine trotz nicht vollständiger Daten klappt, ist optimal.

Die Variante, Joins direkt in der Guid zu realisieren, ist auch eine gute Idee.

Ich sehe nun, eine allgemeine Variante gibt es nicht und ich werde wohl je nach Anwendungsfall mischen müssen oder wirklich die Daten erneut selektieren müssen.

Dein Artikel ObjectBindingSource ist beeindruckend! Ich werde mir das noch genau ansehen.

Vielen Dank!

15.07.2010 - 14:18 Uhr

Hallo Lector,

vielen Dank, das war´s! Klappt prima! 👍 👍

@CSL

Entschuldige dir wirklich einfache Frage. Ich versuche immer zuerst im Forum zu suchen, in externen Quellen und in Büchern nachzuschlagen.

Im Forum findet man bei StackPanel unzählige Einträge, da im gesamten Text gesucht wird. Nach längerer Zeit dort und in externen Quellen hatte ich wirklich nichts passendes gefunden. In Büchern stehen zwar alle Panels einfach beschrieben, aber nicht solche "Spezialdinge" - Zumindest nicht in meinen. Allein das der Button vor der Textbox eingefügt werden muss - darauf wäre ich nicht gekommen.

Also nochmals Entschuldigung. Ich hoffe, der Beitrag hilft zumindest auch Anderen.

Viele Grüße!

14.07.2010 - 16:45 Uhr

Hallo Lector,

vielen Dank für den Tipp! In der Tat klappt das:


<DockPanel HorizontalAlignment="Stretch">
  <Button HorizontalAlignment="Right" Width="Auto">Edit</Button>
  <TextBox Width="Auto" Text="{Binding Path=Kundenname, UpdateSourceTrigger=PropertyChanged}"></TextBox>
</DockPanel>

Jedoch möchte ich den Button rechts neben dem Textfeld positionieren. Wenn ich den Button als letztes einfüge, klappt es aber nicht mehr und die Textbox wird nicht mehr verbreitert.

HorizontalAlignment="Right" beim Button funktioniert leider auch nicht um den Button rechts neben dem Textfeld anzuordnen.

Was mache ich da nur falsch?

14.07.2010 - 16:29 Uhr

Hallo TomLeech,

vielen Dank!! Das hat mir bei der Entscheidung sehr geholfen 👍 :

Wenn du den Datensatz im Propertychanged von einer Liste in die andere Liste schreibst, dann schon, sonst wissen 2 unabhängige Elemente natürlich nichts voneinander.

Jetzt habe ich es endlich verstanden: Die automatische Änderung klappt also nur dann, wenn ein Objekt B direkt aus einem Objekt A erzeugt wird und nicht "parallel" direkt vom Server abgerufen wird.

Möglich:
Server > Objekt A > Objekt B (dann führen Änderungen an Objekt B auch zu Änderungen an Objekt A)

Nicht möglich:
Server > Objekt A
Server > Objekt B (dann führen Änderungen an Objekt B nicht zu Änderungen an Objekt A und Objekt A kann auch nicht mit einem einfachen Refresh() aktualisiert werden.)

Wenn ich den Datensatz also manuell "per Hand" sowieso in der 1. Liste "Objekt A" (oder weiteren Listen) ändern muss und bei zusammengesetzten und berechneten Listen diese Vorgehensweise ohnehin problematisch ist, ist für mich eine manuelle Aktualisierung, also das Neuselektieren der Liste besser und einfacher. Es werden dann zwar mehr Daten über das Netzwerk gejagt, aber diese Einschränkungen sind einfach zu groß für mich.

Eine Möglichkeit hier wäre, das ganze intern zu machen und dadurch hast du alle Möglichkeiten offen.

Sicherlich könnte man evtl. die Daten per Sicht auf dem SQL-Server erzeugen lassen, jedoch ist dies unflexibler (und nicht immer möglich) und führt bei großen Programmen zu sehr vielen Sichten.

Ich hatte gehofft, dass zumindest ein explizit aufgerufener Refresh() die geänderten Listenwerte berücksichtigt.

Vielleicht können auch noch andere User schreiben, ob sie zukünftig eher Entities2LINQ oder die CreateQuery-Methode vom EF bevorzugen?

Grüße!

14.07.2010 - 15:02 Uhr

Ich sitze gerade auf dem Schlauch:

In einem Stackpanel sollen nebeneinander eine Textbox und ein Button angeordnet werden.

Die Textbox-Breite soll auf die maximal mögliche Breite im Stackpanel abzüglich der Breite des Buttons gesetzt werden:


<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
  <TextBox Width="Auto" HorizontalContentAlignment="Stretch"></TextBox>
  <Button HorizontalContentAlignment="Right">Edit</LrsButton>
</StackPanel>

Die Textbox hat nur die Möglichkeit Width="Auto". Dies ist aber abhängig von der Länge des Textes und nicht von der Breite des Stackpanels.

Wie wird die Textbox auf die Restbreite des Stackpanels gesetzt? (Width="*" geht nicht)

Danke!

14.07.2010 - 12:54 Uhr

Hallo TomLeech,

Danke für Deine Hilfe: Also nochmals im Klartext:

1 SQL-Server-Tabelle "Kunde" mit den Spalten "ID" und "Kundenname" und vielen weiteren Spalten
1 SQL-Server-Tabelle "Bestellungen" 1:n Verknüpft mit der Tabelle "Kunde"

WPF-Form mit DataGrid. Zugriff auf den SQL-Server über das EntityFramework.

Im DataGrid soll z.B. der Kundenname dargestellt werden. (und später noch wenige weitere Spalten)

Ich erstelle dazu manuell ein Objekt "DisplayKunde" (siehe Code oben) das später nur die Elemente, die im DataGrid als Spalten dargestellt werden sollen, enthalten wird (da ich ja die vielen weiteren Felder aus der SQL-Tabelle für die Anzeige nicht benötige).

Ich selektiere alle gewünschten Kundennamen. Die Selektion erfolgt per:


var query = from K in Kunden where (.......) select new DisplayKunde() { Kundenname = K.Kundenname, ID=K.ID };

Ich erstelle dann eine ObservableCollection "KundeCollection" bestehend aus "DisplayKunde"-Objekten und füge alle selektierten Werte in diese "KundeCollection". (Die Observable Collection ist ja scheinbar notwendig, wenn die Daten bei Änderung automatisch refresht werden sollen)

Das DataGrid wird dann an die "KundeCollection" gebunden und damit wird bereits der gewünschte Kundenname angezeigt.

Wenn ich nun einen Datensatz bearbeiten möchte, selektiere ich mir die Daten des zu bearbeitenden Kunden (hier mit ID 11) mit:


_thisKunde = (from o in Entities.Kunde where o.ID == 11 select o).First();

In _thisKunde kann ich dann die Werte im Bearbeiten-Fenster ändern und mit .SaveChanges() speichern.

Wird z. B. der Kundenname geändert und mit SaveChanges() gespeichert, wird er aber nicht in der "KundeCollection" (also im DataGrid automatisch refresht)

**

Ich erstelle mir also eine Liste (Collection) für das DataGrid, damit ich nicht immer alle Felder selektieren muss.

Zudem werden in dieser oftmals nicht nur Daten aus 1 simplen Tabelle dargestellt, sondern auch durch Joins Spalten aus anderen Tabellen angezeigt und z. B. Berechnungen (z.B. Anzahl der Bestellungen für jeden Kunde) in der Liste vorgenommen etc.

5.) D.h. also, das die automatische Refresh-Möglichkeit bei Listen mit aus weiteren anderen Tabellen gejointen Spalten und berechneten Spalten nicht funktioniert?

6.) D.h. also, das die automatische Refresh-Möglichkeit ohnehin nicht funktioniert, wenn nicht vorher für das Datagrid alle Spalten selektiert werden, obwohl sie überhaupt nicht benötigt werden? (Gerade in einer Kundenliste werden oft sehr viele Datensätze dargestellt, sehr viele Felder aber erst tatsächlich beim Bearbeiten benötigt)

7.) Daher scheint es in diesen Fällen besser zu sein, die Liste nochmals neu per Code zu aktualisieren? (In diesem Fall würde ich auch dann lieber in einfachen Fällen so verfahren, da ich gerne Code ähnlich schreibe.) Wie macht ihr das?

3.) Und nochmals: Sollte ich lieber kein LINQ (var query = from...) für die Abfragen verwenden, sondern stattdessen lieber gleich mit der CreateQuery-Methode vom Entity Framework? LINQ soll ja angeblich nicht mehr so richtig weiterentwickelt werden und das Entity Framework umso mehr?

Ich hoffe, das ist nun etwas klarer.

Tausend Dank!

14.07.2010 - 11:14 Uhr

Hallo TomLeech,

danke für Deine Antwort! Leider habe ich auf codeproject.com trotz intensiver Suche nichts richtig passendes gefunden und bin nun etwas irritiert. Ich hoffe, Du hast etwas Geduld mit mir. 🙁

Wenn ich eine Liste für ein Datagrid erstelle, werden in dieser oftmals nicht nur aus 1 simplen Tabelle Daten dargestellt, sondern auch durch Joins Spalten aus anderen Tabellen angezeigt und z. B. Berechnungen in der Liste vorgenommen etc.

5.) D.h. also, das die automatische Refresh-Möglichkeit bei Listen mit aus weiteren anderen Tabellen gejointen Spalten und berechneten Spalten nicht funktioniert?

6.) D.h. also, das die automatische Refresh-Möglichkeit ohnehin nicht funktioniert, wenn nicht vorher für das Datagrid alle Spalten selektiert werden, obwohl sie überhaupt nicht benötigt werden? (Gerade in einer Kundenliste werden oft sehr viele Datensätze dargestellt, sehr viele Felder aber erst tatsächlich beim Bearbeiten benötigt)

7.) Daher scheint es in diesen Fällen besser zu sein, die Liste nochmals neu per Code zu aktualisieren? (In diesem Fall würde ich auch dann lieber in einfachen Fällen so verfahren, da ich gerne Code ähnlich schreibe.) Wie macht ihr das?

3.) Und nochmals: Sollte ich lieber kein LINQ (var query = from...) für die Abfragen verwenden, sondern stattdessen lieber gleich mit der CreateQuery-Methode vom Entity Framework? LINQ soll ja angeblich nicht mehr so richtig weiterentwickelt werden und das Entity Framework umso mehr?

Tausend Dank!

13.07.2010 - 14:04 Uhr

SQL-Server+Entity Framework+WPF

Ich weiß, das Thema wurde schon oft besprochen. Trotz Umsetzung aller Punkte klappt es aber nicht. 🙁

**Ich möchte Daten in eine Collection selektieren + im DataGrid anzeigen und
anschließend einen Datensatz aus dem Grid auswählen und verändern.

Wichtig: Beim Speichern der Veränderung soll sich der Eintrag in der Liste automatisch aktualisieren!**

Es klappt alles, nur NICHT die Aktualisierung. Trotz ausführlicher Suche hier im Forum und Internet klappt es einfach nicht!

Es existiert eine SQL-Server-Tabelle "Kunde", auf die per Entity-Framework zugegriffen wird.

Im Code wurde eine Klasse "DisplayKunde" mit den Feldern, die im Datagrid angezeigt werden sollen erstellt. Ich habe eine eigene Klasse erstellt, da ich im Grid nur sehr wenig Felder darstellen will und viele Felder nicht benötigt werden. Zudem können einzelne Felder noch umgerechnet (manipuliert) dargestellt werden oder aus verknüpften Tabellen genommen werden.

Das INotifyPropertyChanged wurde nur eingefügt, damit die Aktualisierung klappen soll - die geht aber trotzdem leider nicht:


public class DisplayKunde : System.ComponentModel.INotifyPropertyChanged
{
        private string _kundenname = String.Empty;
        public String Kundenname
            {
                get
                {
                        return this._kundenname;
                }

                set
                {
                    if (value != this._kundenname)
                    {
                        this._kundenname = value;
                        NotifyPropertyChanged("_kundenname");
                    }
                }
            }
            public int ID { get; set; }
}

Die Werte für das DataGrid werden dann per Query


var query = from K in Kunden where (.......) select new DisplayKunde() { Kundenname = K.Kundenname, ID=K.ID };

selektiert und dann mit foreach und Add() in Observable Collection "KundeCollection" gespeichert.

Im XAML-Code der DataGridTextColumn vom DataGrid steht folgendes:

...Binding="{Binding Path=Kundenname, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

Im Bearbeiten-Fenster selektiere ich mir den jeweiligen Kunden - nicht aus dieser KundeCollection - sondern wieder aus der Datenbank heraus:


_thisKunde = (from o in Entities.Kunde where o.ID == 11 select o).First();

1.) Warum klappt die Aktualisierung trotz INotifyPropertyChanged und ObservableCollection nicht? Liegt es daran, das ich den Kunden beim Bearbeiten nicht aus der KundeCollection herausselektiere, sondern direkt nochmals aus der Datenbank? (Selbst DataGrid.Items.Refresh(); und DataGrid.DataContext = DataGrid.DataContext; funktioniert nicht)

2.) Geht es auch ohne die INotifyPropertyChanged-Schnittstelle? Mir würde ein Code reichen, in dem ich z. B. eine Methode _thisKunde.Refresh() aufrufen würde und der dann erkennt, dass z. B. das Feld "Kunde.Kundenname" geändert wurde und diesen Eintrag in allen Collections im Programm aktualisieren könnte, in dem dieser Kundenname vorkommt.

Zudem würde ich gerne auf den langen Code für den "kundenname" in Klasse Kunde verzichten und stattdessen nur "public string kundenname {get;set;}" schreiben.

3.) Sollte ich lieber kein LINQ (var query = from...) für die Abfragen verwenden, sondern stattdessen lieber gleich mit der CreateQuery-Methode vom Entity Framework? LINQ soll ja angeblich nicht mehr so richtig weiterentwickelt werden und das Entity Framework umso mehr?

4.) Klappt die Aktualisierung auch dann noch, wenn ich
a) in meiner Query für das Datagrid Daten aus mehreren Tabellen verbinde?
b) Felder bei der Selektion manipuliere (z. B. "Kundenname+" "+Kundenort) und bei der anschließenden Bearbeitung z. B. den Kundenort ändere. Merkt sich .NET, wie die Daten im Select zusammengesetzt wurden?

Vielen Dank und Grüße!

23.06.2010 - 09:28 Uhr

Hallo Lector und SeboStone,

ja, in der Tat stehe ich - natürlich wie alle unter Zeitdruck. Ich weiß auch, dass Ihr mit der Umsetzung per ViewModel recht habt!

Ich habe es vorerst (unsauber) so gelöst:

In PreviewKeyDown wird "Textbox_TextChanged-Event" mit += an meine gewünschte Methode gebunden. (Dieser Code wird nur 1x ausgeführt)

Danach klappt es.

Trotzdem werde ich es mir ansehen und eine ViewModel-Schicht "einzuziehen" versuchen. Ihr habt mich hier wirklich in die richtige Richtung angestoßen. 😃

Vielen Dank für Eure tolle Unterstützung!

22.06.2010 - 17:08 Uhr

Hallo Lector,

der Timer könnte dennoch sehr einfach ausgelöst werden:

Z.B. Im Window_Loaded() Timer starten:
50 ms nach dem Loaded wird der Timer nur einmal ausgeführt
Im Timer wird nur einmalig das "Textbox_TextChanged-Event" mit += an meine gewünschte Methode gebunden (die die Fallnummer berechnet).

Danach läuft alles schon so, wie bereits gewünscht, da das {Binding} vom Laden bereits abgeschlossen ist, ändert sich das TextChanged wirklich nur dadurch, wenn der Benutzer etwas eingibt.

Der Timer verzögert den Code im Timer nur etwas. Wenn es eine Methode Window_AfterBinding oder Window_AfterLoading gäbe, könnte man den Code auch dort hineinschreiben, und würde keinen Timer benötigen.

Das separate ViewModel kommt mir ziemlich aufwändig vor. Ich hoffe halt immer noch, mich darum zu "drücken". 🙁

22.06.2010 - 16:57 Uhr

Hallo SeboStone,

ich habe mich etwas verkehrt ausgedrückt: Die Funktion zur Berechnung steht natürlich nicht in der CodeBehind-Datei, sondern ist von allen Programmteilen zentral aufrufbar.

Nur arbeite ich leider nicht mehrschichtig über ein ViewModel, sondern mit dem EF.

Wegen dieser Änderung möchte ich auch (noch) nicht komplett alles umschreiben müssen.

Irgendwie muss so etwas ansich relativ einfaches doch möglich sein?

Danke vielmals!

22.06.2010 - 16:31 Uhr

Hallo Lector,

vielen Dank für die sehr gute und auch richtige Schilderung! Bitte mich jetzt nicht umbringen:

Ich weiß, wie Sie die Änderung machen möchten und umgehen dies geschickt, indem Sie die Berechnung in das Viewmodel verlagern - dahin, wo es auch eigentlich hingehört.

Leider arbeite ich (noch) nicht mehrschichtig und zudem über das Entity Framework, bei denen ich direkt an die Daten gebunden habe. Außerdem sollen die Änderungen direkt beim Tippen neu berechnet werden (Wunsch vom Kunden).

Gibt es noch einen nicht "so sauberen" Weg, um die Angaben im Formular zu berechnen?

Wenn ich auf der Form einen Button einfüge, und in dessen Click-Event das Textbox_TextChanged-Event mit += an meine Neuberechnung "kopple", funktioniert die Aktualisierung nach dem Drücken des Buttons wie gewünscht. Nur ich muss manuell vorher 1x nachdem die Form offen ist auf den Button klicken. Ich möchte auch nicht zu sehr "pfuschen" und einen Timer verwenden.

Gibt es vielleicht noch eine Lösung?

Ich hoffe auf dein Verständnis!

22.06.2010 - 15:54 Uhr

Hallo Lector,

danke für die schnelle Antwort!

In einem Feld gibt es eine Fallnummer (z.B. ID01AD3FG42010)

diese Nummer soll standardmäßig aus den Eingaben verschiedener Textboxen zusammengesetzt werden. (z. B. 1. Buchstabe des Falls, Jahr etc.)

Nur wenn der Benutzer manuell in die Textbox mit der Fallnummer geht, soll er sie überschreiben und ändern können. Wenn sich später etwas an den Angaben ändert, soll die Fallnummer sofort neu "berechnet" werden.

Hat ein Benutzer also eine Fallnummer manuell geändert und ich öffne die Maske mit dem Fall, wird dummerweise jedesmal die Berechnung durchgeführt, obwohl die Änderung nur auf dem Binding beruht.

22.06.2010 - 14:55 Uhr

Hallo Experten,

in einer WPF-Form sitzen gebundene Textboxen ({Binding}).

In einem "Textbox_TextChanged-Event" wird ein bestimmter Code ausgeführt. Dieser Code soll aber nur dann ausgeführt werden, wenn der Benutzer Werte ändert (tippen per Tastatur, StrgX, StrgV, Copy&Paste per Rechtsklick, Drag&Drop von Text usw.)

Momentan wird das "TextChanged"-Event auch beim Laden der Form ausgeführt, da die Textbox ja gebunden {Binding} ist.

Nichts gebracht hat:

  • TextChanged-Event mit += erst am Ende des Window_Loaded zuweisen
  • oder dasselbe im Init-Event machen (wird ja noch früher aufgerufen)

Wo könnte ich das Event mit += zuweisen (gibt es noch etwas nach dem Window_Loaded-Event?) oder, wie könnte ich im TextChanged abfragen, ob die Änderung vom User oder per Binding vorgenommen wurde (in "sender" und "e" finde ich nichts passendes)

Die Lösung sollte natürlich nicht nur mit Textboxen, sondern auch anderen WPF-Controls funktionieren.

Vielen Dank!

17.06.2010 - 16:10 Uhr

Hallo Erfinder des Rades und Tom Leech!

das ist ja sehr eigentümlich. weil weiter oben sagtest du,
KundeListe = query.ToList();
täte nicht klappen (die Angabe des generischen typen <oDisp> ist übrigens entbehrlich)

Ja du hast Recht. Ich hatte inzwischen den gesamten Programmcode noch weiter geändert. Sicher hast du auch mit den Grundlagen Recht - ich habe schon in einigen Büchern gelesen aber durch die hohe Seitenzahl vergisst man wieder viel und einiges wird und kann auch nicht so gut erklärt werden und ist nur durch die Praxis vermittelbar.

Vielen Dank auch für den Code, die Daten in eine ObservableCollection zu bringen. Momentan benötige ich die ObservableCollection noch nicht zwingend. Da die zusätzlichen Schritte Zeit kosten, werde ich nun das Ergebnis vorerst in der Liste belassen.

Nochmals vielen Dank an Euch 👍 =) 👍 - damit kann ich das Thema schließen.

Grüße

16.06.2010 - 16:35 Uhr

Hallo Erfinder des Rades und Tom Leech!

Vielen Dank für die super Hilfe! Es klappt nun tatsächlich mit:


MeineVorherSchonGenerierteLeereListe = query.ToList<oDisp>();  :thumbsup:

Aber nur wenn "MeineVorherSchonGenerierteLeereListe" vom Typ List<oDisp> ist. Mit "MeineVorherSchonGenerierteLeereListe" als ObservableCollection klappt es ersteinmal nicht, auch nicht mit einem Casting (ObservableCollection<oDisp>) vor der Zuweisung.

Ich hatte die ganze Zeit versucht zu casten und bin daran verzweifelt.

Vielleicht wisst ihr noch einige Hintergrundinfos dazu:

* query.Dispose(); gibt es nicht. Wie kann man diese Query dann wieder entfernen, ohne auf die automatische Garbage Collection zu warten?

* Was macht .NET bei der Zeile "MeineVorherSchonGenerierteLeereListe = query.ToList<oDisp>();" wirklich? Kopiert er die Liste (wg. ToList) oder reicht er das "Originalmaterial" nur konvertiert weiter.

Vielen Dank nochmals!

Grüße

16.06.2010 - 11:30 Uhr

Hallo Erfinder des Rads,

ich weiß, du hast geschrieben:


var oDisps=query.ToList();

Mein Problem ist nur, dass

Ich erstelle bereits direkt (im Konstruktor) in der Klasse des WPF-Windows eine Liste (und natürlich oDisp) List<oDisp> KundeListe = new List<oDisp>();

Wenn die Form geöffnet wird, existiert bereits ohne die anonyme Abfrage meine Liste. Daher muss ich vorher den Datentyp definieren. (Egal ob List, ObservableCollection oder irgend etwas anderes)

Erst wenn der Anwender ein Filterkriterium auswählt (z. B. alle Kunden mit "A"), kann ich mir die Daten vom Server holen. Da dies dann in einen anonymen Typen (mit var x =) passiert, muss ich diesen anonymen Typen in meine Liste übernehmen (und konvertieren), die bereits seit dem Öffnen der Form vorhanden ist. Evtl. kann ich ja gleich in diese Liste selektieren? - Das habe ich jedoch noch nicht hinbekommen.

Diese umständliche Vorgehensweise benötige ich, weil ich die "KundeListe" an meine WPF-Controls binde, evtl. für weitere Aktionen, Änderungen oder für einen Valueconverter bereits fixieren möchte. Auch bei späteren Umsortierungen etc. möchte ich dann mit dieser Liste arbeiten.

* Nur wie kann ich entweder direkt in eine vorhandene Liste selektieren oder die anonyme Liste in meine Liste konvertieren?

* Welcher Listentyp ist der beste dafür (IList, ObservableCollection, etc.?)

Vielen Dank!

16.06.2010 - 10:42 Uhr

Hallo dN!3L und gfoidl,

ich bedanke mich sehr für Eure große Geduld! Ja es funktioniert nun tatsächlich. Zuerst hatte er aus irgendeinem Grund die "Felder" in der manuell erzeugten Partial-Klasse immer unterstrichen und nicht erkannt. Nun klappt es!

Und hier könnte man auch den Code anbringen, die Standardwerte vom SQL-Server zu lesen.

Vielen Dank nochmals an Euch beide!

Grüße

15.06.2010 - 17:58 Uhr

Hallo dN!3L!

Verstehe ich dich richtig: ID ist im Model ein Nullable<int>, darf aber nicht null sein?
Du kannst doch das Property im Model auf "Nullable=false" setzen - dann ist es ein "normales" int und kann nie null werden.

* In der Datenbank sind die Felder not null und ein Standardwert ist hinterlegt
* In der edmx-Datei kann man bei den Entinitätstypen für alle einzelnen "Felder" den Standardwert von "(Keine)" manuell auf einen Standardwert ändern. Da dort auch "Null zulassen" auf False steht, wäre es wie von mir gewünscht. Jedoch muss ich bei Tabellenänderungen die edmx-Datei neu aufbauen lassen und müsste jedes Mal hunderte von Feldern wieder manuell mit Standardwerten beglücken. Das will ich vermeiden. Der Typ im Modell ist nicht nullable, sondern z.B. Int32 oder String.


public partial class  MyEntities
{
    public MyEntities()
    {
         // Initialisierung hier machen
    }
}

Ich möchte doch nicht MyEntities, sondern z. B. die einzelnen Felder der Kunden-Entities, der Lager-Entities etc. beim Initialisieren automatisch mit Standardwerten belegen, die ich 1x irgendwo im Code (nicht aber in der edmx-Datei) definiere. Ich müsste daher meiner Ansicht nach etwas folgendes schreiben:


public partial class Kunde
{
    public Kunde()
    {
         ID=0;
         Name="";
    }
}

Nur das geht leider nicht.

15.06.2010 - 17:46 Uhr

Hallo gfoidl,

ja, Du hast recht, jetzt hab ichs gefunden:


    [EdmEntityTypeAttribute(NamespaceName="MyModel", Name="Kunde")]
    [Serializable()]
    [DataContractAttribute(IsReference=true)]
    public partial class Kunde : EntityObject
    {
       public static Kunde CreateKunde(...)
       {
          ...
       }
    ...
    }
  

sonst sind partielle Methoden nur noch direkt bei den einzelnen Feldern auffindbar:


        private global::System.String _Name;
        partial void OnName1Changing(global::System.String value);
        partial void OnName1Changed();

sonst leider nichts "partiales".

Grüße

15.06.2010 - 17:14 Uhr

Hallo Erfinder des Rads!

vielen Dank für Deine Unterstützung! Das hat mir bereits gut weitergeholfen! Der Konstruktor in oDisp ist nun draußen. (Der Name wurde nur schnellschnell gewählt und wird später geändert)

und die Query ist nun auch korrigiert:
var query = from A in Kunden select new oDisp(){Name=A.Name, ID=A.ID };

Ich erstelle bereits direkt in der Klasse des WPF-Windows eine Liste (und natürlich oDisp):
List<oDisp> KundeListe = new List<oDisp>();

Wenn ich nach der Query die Werte in die Liste KundeListe übernehmen will:


KundeListe = (List<oDisp>)query;

erhalte ich jedoch folgenden Fehler:

Das Objekt des Typs "System.Data.Objects.ObjectQuery1[MyN.KundeForm+oDisp]&quot; kann nicht in Typ &quot;System.Collections.Generic.List1[MyN.Kunde]" umgewandelt werden.

(Inner Exception ist null)

* Warum klappt hier nicht die Konvertierung?
* Ist es besser statt der List<Kunde> eine ObservableList<Kunde> oder etwas passenderes zu nehmen?

Tausend Dank!

15.06.2010 - 16:16 Uhr

Hallo dN!3L und Gfoidl,

Trotz Eurer beiden ausführlichen Postings und langem Versuchens verstehe es einfach nicht:

Ich möchte inzwischen nun den für mich leichtesten Ansatz verfolgen und dafür sorgen, sobald eine Entität erstellt wird, diese mit leeren Werten vorzubelegen:

In Model.Designer.cs ist im EF folgendes definiert:


public partial class MyEntities : ObjectContext
{
    public MyEntities() : base("name=MyEntities", "MyEntities")
    {
        this.ContextOptions.LazyLoadingEnabled = true;
        OnContextCreated();
    }
...

"partial", also wäre die OnContextCreated() auch von außen erweiterbar. Nur bringt es mir nichts, beim ObjectContext etwas auszuführen, da ich hier nicht weiß, um welche Entität (z. B. Tabelle Kunde, Lager o. ä.) es sich handelt. Kann man das hier irgendwie abfragen?

Sonst steht in der Model.Designer.cs zwar das ObjectSet noch aufgeführt, aber das ist nicht partial und beschreibt auch nicht das Kunde-Objekt, sondern die entsprechende Kollektion.

Daher habe ich es folgendermaßen versucht:


   public partial class MyEntities
    {
        partial void OnContextCreated()
        {
            if (this.DefaultContainerName=="Kunde")  // klappt so leider nicht
            {
                this.Kunde.ID = 0;	// alle Werte setzen, um NULL zu vermeiden
	this.Kunde.Name = "";
                ...
            }
        }
    }

Sobald ich im Code:

Kunde _kunde = new Kunde();

aufrufe, soll der Teil, der in meiner "public partial class MyEntities" steht, dafür sorgen, dass z. B. ID=0 ist und Name="". In anderen Entitäten können die Felder anders heißen.

Vielen Dank!

14.06.2010 - 17:58 Uhr

Hallo dN!3L,

auch Dir vielen Dank! Da muss ich aber erst einmal durchsteigen: 8o

Dieser Ansatz, die Defaultwerte direkt aus dem SQL-Server auszulesen gefällt mir auch und ist zudem sehr bequem. Allerdings speichert er die Werte nicht im Modell, sondern muss sie im Programmablauf vorher abfragen.

Diese Funktion könnte man evtl. auch dazu benutzen, um die Standardwerte direkt in die EDMX-Datei einzutragen, nachdem man das EF-Modell neu aufgebaut hat. Funktionen (z.B. newid()) müssten manuell noch angepasst werden.

Ich werde mir beide Ansätze ansehen!

Grüße

14.06.2010 - 17:45 Uhr

Hallo Gü!

Danke für die Antwort! Ich habe es mit einer Extension Methode versucht zu lösen:


    public static class MyExtender
    {
        public static Kunde GetDefaultValues(this Kunde currentKunde)
        {
            currentKunde.ID=0;
            currentKunde.Name = "";
            // hier folgen alle weiteren Felder....
            return currentKunde;
        }
    }

   // Später auslösen:
  Kunde _kunde = new Kunde();
  Kunde.GetDefaultValues()       // .GetDefaultValues() wird leider nicht von Intellisense angeboten!?


Leider zeigt mir Intellisense später nicht Kunde.GetDefaultValues() als Möglichkeit an. Bei "partial void OnCreated()" weiß ich nicht, wie und wo ich es aufrufen sollte: Partial würde ich ja als "partial class Kunde" anlegen und dann mit "public override OnCreated()" überschreiben. Oder kann man mit Kunde.OnCreated()+= Code anhängen? Nur wo muss man das einbauen?

"oder man findet sich eben damit ab 😉" --> Wie verfahrt ihr, wenn nicht alle Felder gesetzt werden sollen? - In diesem Fall immer alle leeren Felder manuell setzen und bei Felderweiterungen in der Datenbank die neuen Felder ergänzen?

Vielen Dank!

14.06.2010 - 17:13 Uhr

Hallo,

ich nutze SQL-Server 2000-2008, C#, VS 2010 und arbeite über das Entity Framework.

Ich möchte eine Abfrage in einer Collection speichern, die ich selbst erstellt habe.


ObjectQuery<Kunden> Kunden = EModell.Kunden;
var query =  from A in Kunden  select new { A.Name, A.ID };

public class oDisp    // Fehlt hier noch ein Interface?
{
  public string Name {get;set;}
  public int ID {get;set;}
  public oDisp  // Konstruktor ist doch da!
    {
       Name="";
       ID=0;
    }
}

// Hier tritt der Fehler auf: 
ObjectSet<oDisp> query2 = new ObjectSet<oDisp>(); // Fehler: "Für den Typ "System.Data.Objects.ObjectSet<TEntity>" sind keine Konstruktoren definiert."

query2=query  // Hier soll query in query2 abgelegt werden, weil ich zukünftig mit query2 weiterarbeiten will
oder:
query2 = (ObjectSet<oDisp>)query; // ist das notwendig?


DataGrid.ItemsSource=query   // Funktioniert Problemlos: Werte werden angezeigt
query.Dispose();                     // gibt es nicht - warum nur?

DataGrid.ItemsSource=query2  // Das möchte ich! - Wenn obiger Fehler weg ist

Ist ObjectSet<> überhaupt die richtige Wahl? Und was habe ich falsch gemacht?

Vielen Dank für Eure Hilfe!

14.06.2010 - 15:31 Uhr

Hallo dN!3L,

vielen Dank für die Antwort!

Die Felder sollen an anderen Programmstellen schon befüllt werden. (Kann man vielleicht mitteilen: Alles andere, was nicht explizit übergeben wurde = computed? oder gibt es in der Entität eine Möglichkeit wie "Entity.LoadDefaultValuesIfNull=true;" um die Defaultwerte zu laden?)

Im Konstruktor kann ich leider nicht die Standardwerte einsetzen, da ich ja den Desinger vom Entity Model genutzt habe, um die SQL-Tabellen als Entitäten darzustellen. Dort kann ich zwar sicher irgendwo in den Code gehen und die Standardwerte im Konstruktor manuell setzen. Das geht sogar im Designer:

Im Entitätsmodel kann ich die einzelnen Felder (Entitätstypen) mit einem Standardwert auch befüllen. Aber auch diese Änderungen gehen verloren, wenn ich das Entitätsmodell neu erzeuge.

Ich möchte aber bei Tabellenänderungen das Entity Model schnell neu aufbauen können: Alles markieren, löschen und dann neu erzeugen. Damit wären meine Änderungen überschrieben.

Vielleicht weiß jemand noch eine Lösung?

Danke

14.06.2010 - 13:53 Uhr

Hallo,

hat denn wirklich niemand eine Idee wie das geht?

Ich bin wirklich dankbar für jeden Tipp!

10.06.2010 - 13:42 Uhr

Liebe Experten,

Ich komme nicht mehr weiter: Per Entity Framework soll ein Datensatz auf den SQL-Server eingefügt werden, was nur dann fehlerfrei klappt, wenn alle Felder tatsächlich mit Werten belegt werden. (In der Datenbank sind alle Felder "Not Null" und haben einen Standardwert hinterlegt)

Im Entitätsmodell kann auch für jedes Feld unter Standardwert jeweils ein Standardwert hinterlegt werden. Damit würde das Problem nicht mehr auftreten.

Im Entitätsmodell sind bei den Feldern die Eigenschaften "NULL zulassen" "=False" und "Standardwert" "=(Keine"). Ändert man "Standardwert" auf den Standardwert, klappts wie gesagt. - Wie kann man das automatisiert für alle Tabellen und alle Felder tun?

Leider möchte ich diese Information nicht manuell im Entitätsmodell eintragen, da ich das Entity-Modell nach Änderungen an den SQL-Server-Tabellen lösche und immer neu erzeuge. Nach jeder Erzeugung müsste ich somit hunderte von Standardwerte eintragen. 😜

Gibt es eine Einstellung beim Erstellen vom Entitätsmodell, die automatisch die Standardwerte vom SQL-Server übernimmt? Oder gibt es vielleicht eine Einstellung "Beim Speichern statt Null-Werten Standardwerte vom Server verwenden"?

SQL-Server 2000-2008
VS2010 C#, .NET 4

Danke!

08.06.2010 - 17:03 Uhr

Hallo Gü,

danke für Deine schnelle Antwort! Ich hatte bereits gegoogled, aber das "versus" hats wirklich gebracht!

Somit habe ich mich nun mit EF beschäftigt und hoffe zukünftig nicht gleich wieder umsatteln zu müssen.

Ich versuche nun den Connection String nicht über die app.config (dort ausdokumentiert), sondern direkt im Code vor jeder Lese- oder Schreibaktion einzusetzen.

Ich hoffe, das es dann möglich ist, die Verbindung zu öffnen > Daten auszulesen + Verbindung sofort danach zu schließen (Werte sollen im WPF-Fenster weiterhin angezeigt werden aber Datenbank könnte jetzt theoretisch offline geschalten werden) > Verbindung wieder zu öffnen und die geänderten Daten z. B. per SaveChanges() in die Datenbank zu übernehmen + Verbindung sofort danach zu schließen.

Ich weiß nicht, ob es möglich ist, die Werte überhaupt nach dem "Verbindungsabbruch" zu ändern oder ob dann ein Fehler kommt? - Ich möchte die Verbindung trotzdem nicht offen lassen. Geht das?

Falls ja habe ich schon hier Probleme:

Leider klappt das nicht ganz - was ist daran falsch?:
EntityConnection conn = new EntityConnection("name=XYModel")
// hier gibt es umfangreiche Möglichkeiten mit using(EntityConnection XYModel = new EntityConnection(entityBuilder.ToString())) und einem anschließendem Block die aber bei mir auch nicht funktionieren

Hier möchte ich hin und folgende Zeilen klappen auch (bei Weg über app.config):
XYEntities dataEntities = new XYEntities();
ObjectQuery<Kunde> Adresse = dataEntities.Kunde;

Danach Verbindung schließen:
XYEntities.Connection.Close();
XYEntities.Connection.Dispose();

Nochmals tausend Dank!

07.06.2010 - 16:15 Uhr

Liebe Experten,

ich habe mich soeben mit den LINQ to SQL - Klassen angefreundet (DBML-Dateien und grafischer Designer). Nun habe ich entdeckt, dass ein Zugriff über das ADO.NET Entity Data Model in ähnlicher Weise möglich ist. Beide arbeiten ja mit Entitäten.

  • Wo ist denn der Unterschied zwischen beiden? (ich habe dazu nichts gefunden)
  • Was ist zukunftssicherer?
  • Was ist schneller?
  • Was ist einfacher zu "handeln" (z. B. bei Änderungen der SQL-Datenbanken (z.B. Feldänderungen)
  • Mit welchen der beiden Möglichkeiten arbeitet die Mehrheit der C# Entwickler (die eine der beiden Methoden einsetzen)?
  • Am liebsten würde ich immer nur für den Abfragezeitraum die Verbindung aufbauen, abfragen und dann schließen. Auch bei Änderungen direkt vorher Verbindung öffnen, ändern und schließen. Die bei der letzten Verbindung eingelesenen Daten müssen auch nach dem Trennen der Verbindung und dem neuen Aufbauen der Verbindung z.B. per SubmitChanges geändert werden können.
  • Die Verbindung (Connection) sollte auch optional per IP-Adresse (und notfalls übers Internet) möglich sein.

Genutzt werden soll alles mit:

  • SQL-Server 2000-2008 bzw. SQL-Server Compact
  • Netzwerkbetrieb mit bis zu 20 Arbeitsplätzen
  • Programmierung unter VS 2010, C#, WPF, Nutzung von DataGrid und DataBinding

Danke vielmals!

16.04.2010 - 16:39 Uhr

Hallo FZelle und Kenchu,

in der Tat habt ihr beide Recht und ich finde es toll, das ich durch diese Antworten nun auf dem (hoffentlich) richtigen Weg bin!

Ich habe mir Linq2Sql angesehen und stelle fest, das es wirklich ein sehr brauchbarer und einfacher OR-Mapper ist, der mir auch sehr(!) viel Arbeit abnimmt. (NIH-Syndrom damit hoffentlich kuriert)

Ich weiß, ich setze mich nun bestimmt viel Kritik aus, aber ich möchte vorerst kein "echtes" Schichtenmodell und erst Recht kein MVVM-Modell nutzen. Ich möchte in einem Projekt die "Schichten" vorerst als einzelne Klassen modellieren, aber den Zugriff der Schichten untereinander nicht verweigern, um die Anwendung einfach zu halten. (KISS) So komme ich am Anfang vorerst am Weitesten.

Die Anwendung soll entweder auf einem Rechner oder von mehreren Clients in einem Netzwerk aus genutzt werden.

Linq2Sql wird in der untersten "Schicht" eingesetzt.

Noch eine letzte Frage zu Linq2Sql: Empfehlt ihr über "LINQ to SQL-Klassen" den "grafischen Designer" (mit .designer.cs-Datei) zu nutzen oder die Entity-Klassen selbst schreiben? (Habe ich auch bereits erfolgreich gemacht und ist für mich zur Zeit etwas übersichtlicher)

Vielen Dank

15.04.2010 - 16:37 Uhr

Hallo FZelle,

entschuldige bitte: ja, ich meinte die DataTable.

Ich möchte dass die Anwendung später auch noch dann erweiterbar und übersichtlich ist, wenn sie einmal sehr groß wird, ohne etwas umzuschreiben.

Folgendes mag ich an den vorhandenen OR-Mappern nicht:

  • Es gibt eine Vielzahl davon und man weiß nicht, ob die Entwicklung daran später einmal eingestellt wird.

  • Es können scheinbar nicht alle Sachen damit gemacht werden. Ich suche aber eine Möglichkeit, die mir später einmal alles erlaubt.

  • Ich könnte später beim eigenen OR-Mapper meine eigenen Zugriffsmethoden wie gewünscht optimieren

Trotzdem sehe ich mir gerade auch Linq2Sql an, was scheinbar sehr viel einfacher ist. Wäre dies evtl. doch für mich sinnvollste Weg, den Du mir empfehlen würdest? (Auch wenn meine Anwendung später sehr wächst, ich evtl. einmal außer SQL-Server auch MySQL und Oracle einsetzen müsste?) Ich möchte dann gerne in der Datenzugriffsschicht einen Switch einbauen, der mir dann auch mit Linq2Sql je nach Datenbanksystem die richtigen Daten liefert.

Vielen Dank!

14.04.2010 - 16:00 Uhr

Hallo,

Danke vielmals für Deine Antwort! Inzwischen habe ich mich intensiv zu anderen ORMappern eingelesen und bin weiterhin in meinem Fall der Auffassung, den ORMapper selbst zu schreiben. Es gibt sicher viele unterschiedliche Meinungen dazu.

Nur ist es in diesem Fall angebracht, im Programm nicht mit RecordSets zu arbeiten und stattdessen besser eine ObservableCollection zu nutzen - oder gibt es eine "bessere" (einfacher/schnellere) Collection dafür?

Entscheide ich mich für Collections muss ich also scheinbar tatsächlich den Umweg über den Recordset gehen und von dort aus alle Daten in die Collection kopieren. (Das kostet auch Zeit).

Ich habe gehofft, es gibt einen direkte Methode, die Daten - ohne über den Recordset - direkt in die Collection zu kopieren.

Die Daten sollen in WPF dargestellt/editiert werden.

Vielen Dank!

09.04.2010 - 16:12 Uhr

verwendetes Datenbanksystem: <MS-SQL-Server 2000 - 2008>

Hallo,

ich bin ein Anfänger und habe bereits viel gesucht aber noch keine übergreifende Antwort auf meine Fragen gefunden:

Daten vom SQL-Server, SQL-Server-Compact und später vielleicht einmal MySQL oder eine andere Datenbank soll im WPF-Programm in eine Observable Collection gespeichert werden. (Lesen und zurückspeichern und an WPF binden)

  1. Ist die Observable Collection zum aktuellen Zeitpunkt VS2008/2010 tatsächlich die empfehlenswerteste Collection (Performance, Möglichkeiten) und sollte man besser nicht mehr mit DataTables arbeiten? Gibt es evtl. eine bessere Collection? Ich möchte später so wenig wie möglich unterschiedliche Collections nutzen und es sollte eine sehr schnelle und einfache Möglichkeit sein.

  2. Beim Füllen einer ObservableCollection stelle ich mich noch schlecht an: Ich hole mir die Daten zuerst mit einem SQLDataReader (und ExecuteReader und dann mit Read()) und füge dann die einzelnen Daten mit einer Schleife ein. Das ist bei großen Datenmengen sicher zu langsam. Gibt es hier eine Möglichkeit, die Werte direkt und auf einen Schlag in eine ObservableCollection einzufügen?

  3. Ist es sinnvoll von allen auf dem SQL-Server existierenden SQL-Tabellen einzelne Klassen mit allen Feldern zu erstellen, die es auf dem SQL-Server gibt um diese Klasse dann für die ObservableCollection zu nehmen? Kann man sich diese Klassen nicht komfortabel und dynamisch beim Lesen vom SQL-Server selber erstellen lassen?

Vielen Dank!