Autor Beitrag
Schafschaf
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 63
Erhaltene Danke: 2

Windows 10
C# (VS 2015)
BeitragVerfasst: Mi 13.04.16 11:25 
Hallo,

Entity Framework macht mal wieder Probleme.
Wenn ich z.B. eine CSV Datei einlese mit Zwei Spalten, in der einen Steht der Schülername, in der anderen der Name der Klasse, in der er ist,
dann möchte ich beim Durchgehen der CSV den Schüler einer Klasse zuordnen, wenn es die Klasse noch nicht gibt, soll sie angelegt werden.
Das Model sähe dann so aus:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
    public class Schueler
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public Klasse Klasse { get; set; }
    }

    public class Klasse
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public ICollection<Schueler> Schueler { get; set; }
    }


Jetzt lese ich die CSV Zeile für Zeile durch und erzeuge aus den Zeilen ein Schülerobjekt.
Dabei prüfe ich, ob für den Schüler schon eine Klasse gibt, wenn ja weise zu, wenn nein, lege an und weise zu.
Eine Zeile sieht z.B. so aus: Peter Muster;10b, die wird in ein StringArray umgewandelt.
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
 public void Lesen()
        {
            foreach (var zeile in csv)
            {
                var schueler = new Schueler()
                {
                    Name = zeile[0],                                       
                };

                if (cxt.Klasse.Any(x => x.Name == zeile[1]))
                {
                    schueler.Klasse = cxt.Klasse.Where(x => x.Name == zeile[1])
                }
                else
                {
                    schueler.Klasse = new Klasse() { Name = zeile[1] };
                }


                cxt.Schueler.Add(schueler);
                
            }
        }


Leider legt er jetzt für jeden Schüler grundsätzlich eine neue Klasse an, obwohl die Klasse schon vorhanden ist(oder sein sollte?). Warum?
Was mache ich falsch?

(Natürlich geht es nicht um Schüler und Lehrer, ich kann mit einfachen Beispielen mein Problem einfach besser auf den Punkt bringen)

LG Schafschaf
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4263
Erhaltene Danke: 851


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 13.04.16 11:40 
Zitat:
Leider legt er jetzt für jeden Schüler grundsätzlich eine neue Klasse an, obwohl die Klasse schon vorhanden ist(oder sein sollte?). Warum?

Du legst bei jeder Zeile ganz offensichtlich immer ein neues Object an aka
Zitat:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
foreach (var zeile in csv)
{
   var schueler = new Schueler()
   {
       Name = zeile[0],                                       
   };

warum wunderst du dich da das du auch für jede Zeile ein neues Schueler object bekommst :gruebel:

Hol dir dein Schueler Object aus dem Context und lege nur ein neues an wenn keins gefunden wurde. Da in der csv nur denn Namen hast nehme ich das mal zwangsweise als Key an obwohl du ein ID definiert hast.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
foreach (var zeile in csv)
{
    Schueler schueler = cxt.Schueler.FirstOrDefault(x=> x.Name == zeile[0]);
    if (schueler == null)
    {
        var schueler = new Schueler() { Name = zeile[0]};
        cxt.Schueler.Add(schueler);
    }
    // hier jetz schueler bearbeiten


Edit: Den Test auf Gleichheit in FirstOrDefault solltest du dir genau überlegen. Strings vergleiche sind potentiell Kultur und Casing abhängig. Ein simples == oder equals (ao wie hier gezeigt) ist also meist nicht das was man will. Sondern man braucht was gezielteres.
Schafschaf Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 63
Erhaltene Danke: 2

Windows 10
C# (VS 2015)
BeitragVerfasst: Mi 13.04.16 11:50 
Er soll ja auch ein neues Schülerobjekt anlegen, aber nicht für jeden Schüler eine neue Klasse.

Wenn z.B. der Schüler Peter in die 10b geht und es die 10b noch nicht gibt, soll er den Schüler Peter und die Klasse 10b adden.
Jetzt gehe ich weiter in der Datei und komme zu Lisa, die auch in die 10b geht. Jetzt legt er Lisa an, was auch richtig ist, aber er legt auch nochmal 10b an.
Da soll er aber für Lisa.Klasse die vorhandene Klasse, die ja schon bei Peter angelegt wurde zuweisen.

Deshalb schaue ich ja bei jeder Zeile mit Klasse.Any ob es eine Klasse gibt, wenn ja weise die vorhandene zu und nur wenn es diese Klasse noch nicht gibt soll er sie anlegen.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4263
Erhaltene Danke: 851


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 13.04.16 12:09 
Hmh. Hast du mal versucht die Klasse Klasse explizit ctx.Klasse hinzuzufügen und nicht nur auf den impliziten Weg über das hinzufügen von Schueler auch die Klasse zu bekommen?

Edit: Der nächste Stotterthread :roll:
Schafschaf Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 63
Erhaltene Danke: 2

Windows 10
C# (VS 2015)
BeitragVerfasst: Mi 13.04.16 13:25 
Habe ich auch versucht. Kommt das Gleiche 'bei raus :(

Warum Stotterthread?
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4263
Erhaltene Danke: 851


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 13.04.16 13:48 
Zitat:
Warum Stotterthread?

Zitat:
Hast du mal versucht die Klasse Klasse explizit ctx.Klasse

www.entwickler-ecke....tterern+_115342.html
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4263
Erhaltene Danke: 851


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 13.04.16 13:53 
Dann wird EF bei deinem Konstrukt wohl die Klasse Property nicht als Referenz interpretiert.
Ich kenne mich bei Poco/Code First Konstrukten in EF nicht wirklich gut aus aber in dieser Beschreibung sieht der Aubau einer solchen Navigational Property anders aus als bei dir.
Schafschaf Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 63
Erhaltene Danke: 2

Windows 10
C# (VS 2015)
BeitragVerfasst: Mi 13.04.16 15:40 
Ich habe die Lösung selbst gefunden.
Wenn ich ein Klassenobjekt mit cxt.Klassen.Add() hinzufüge, ist es zwar hinzugefügt, aber bevor ich nicht SaveChanges() aufgerufen habe noch nicht in der Datenbank.
Wenn ich dann mit cxt.Klassen.Any() abfrage ob es vorhanden ist, bekomme ich immer false, da die Liste noch leer ist, weil diese Abfrage direkt auf der DB ausgeführt wird.
cxt.Klassen.Local ist hier die Lösung. Darin finde ich die Objekte, die noch nicht von SaveChanges betroffen sind.