Laden...

Warum ist beim Auslesen der ForeignKey immer null (SqLite)?

Erstellt von Steven85 vor 3 Jahren Letzter Beitrag vor 3 Jahren 602 Views
Steven85 Themenstarter:in
99 Beiträge seit 2011
vor 3 Jahren
Warum ist beim Auslesen der ForeignKey immer null (SqLite)?

Hallo zusammen,

ich bin gerade dabei mir EF Core anzueignen. Hier mein Beispiel mit Sqlite:


public class DataContext : DbContext
    {
        // Für die zu erzeugende Tabelle nach dem Code first Prinzip
        public DbSet<Person> Personen { get; set; }
        public DbSet<Geschlecht> Geschlechter { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite(@"Data Source=D:\Daten\Steven IT\Daten\C# Entity Framework Core\Beispielanwendung Einfach\Beispielanwendung Einfach\Data\EntityFrameworkTutorial.db");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Geschlecht>()
                .HasMany(g => g.Personen)
                .WithOne(p => p.Geschlecht);
        }
    }


public class Person
    {
        public int Id { get; set; }
        public string Vorname { get; set; }
        public string Nachname { get; set; }
        public Geschlecht Geschlecht { get; set; }
    }


public class Geschlecht
    {
        public int Id { get; set; }
        public string Bezeichnung { get; set; }
        public List<Person> Personen { get; set; }
    }


class Program
    {
        static void Main(string[] args)
        {
            using (var db = new DataContext())
            {
                var maennlich = new Geschlecht();
                maennlich.Bezeichnung = "Männlich";
                db.Geschlechter.Add(maennlich);

                var weiblich = new Geschlecht();
                weiblich.Bezeichnung = "Weiblich";
                db.Geschlechter.Add(weiblich);
                db.Personen.Add(person);

                person = new Person();
                person.Vorname = "Steven";
                person.Nachname = "S.";
                person.Geschlecht = maennlich;
                db.Personen.Add(person);

                person = new Person();
                person.Vorname = "Lisa";
                person.Nachname = "S.";
                person.Geschlecht = weiblich;
                db.Personen.Add(person);

                db.SaveChanges();
            }
            using (var db = new DataContext())
            {
                foreach (var person in db.Personen)
                {
                    Console.WriteLine($"{person.Id}. {person.Vorname} {person.Nachname} ({person.Geschlecht.Bezeichnung})");
                }
            }

            Console.ReadKey();
        }
    }

Das speichern klappt wunderbar, hier wird die Id des Geschlechts autom. hinzugefügt.
Jedoch ist beim Anzeigen der Daten in der Console person.Geschlecht = null. In der Datenbank sieht alles gut aus.
Könnt ihr mir sagen was hier noch fehlt?

Gruß Steven

2.078 Beiträge seit 2012
vor 3 Jahren

Schau mal da: Laden zugehöriger Daten - EF Core

Generell solltest Du deren Doku durcharbeiten, die ist wirklich gut.

Steven85 Themenstarter:in
99 Beiträge seit 2011
vor 3 Jahren

Danke dir, das hat schon geholfen 😃

16.806 Beiträge seit 2008
vor 3 Jahren

Beginner Tipps, die einem das Lernen vereinfachen:
Verwende direkt .NET 5 und Nullable Reference Types; das spart einem viel Validierungsarbeit

public string Vorname { get; set; } = null!;

Wird zudem von Haus aus von EF5 unterstützt (wird auch im Schema beachtet)
EF arbeitet intern mit ICollection und dem HashSet

public ICollection<Person> Personen { get; set; } = new HashSet<Person>();

Ja, die Doku verwendet an manchen Stellen List - aber das ist eigentlich totaler Quatsch.

Verwende immer die async-Methoden, immer. Immer immer.

Verwende Explizite FK-Properties; vermeide die Attribute


 public Geschlecht Geschlecht { get; set; }
 public int GeschlechtId { get; set; }

 modelBuilder.Entity<Geschlecht>()
                .HasMany(g => g.Personen)
                .WithOne(p => p.Geschlecht)
                .HasForeignKey(p => p.GeschlechtId);

Besonders bei der Fehlersuche versteht man seinen eigenen Aufbau viel einfacher als wenn das ganze Magic Zeug da reinspielt.

Palladin007 hat aber absolut recht, dass die Doku sehr mächtig und insgesamt - bis auf eine Hand voll Dinge - qualitativ extrem gut ist.
90% aller Durchschnitts-Themen zu EF lassen sich von der Doku beantworten.

Steven85 Themenstarter:in
99 Beiträge seit 2011
vor 3 Jahren

Hi Abt,

das Thema mit await und async wollte ich mir separat ansehen, habe erstmal darauf verzichtet da ich noch nicht wirklich verstehe was da passiert, bzw. was es genau bringt. Könntest du es evtl. kurz beschreiben anhand eines kleinen Beispiels, oder mir evtl. ein gutes Tutorial dazu emphelen?

Und kannst du mir auch noch erklären wozu genau das dient? brauch man das Ausrufungszeichen hinter dem null?


public string Vorname { get; set; } = null!;

Gruß Steven

16.806 Beiträge seit 2008
vor 3 Jahren

Wenn Du etwas nicht kennst, dann werf doch erstmal ein Blick in die Doku 😉

Asynchrone Programmierung mit async und await
Nullable-Werttypen (C#-Referenz)

Macht ja wenig sinn 1:1 zu wiederholen, was auch in der Doku so steht 😃

Steven85 Themenstarter:in
99 Beiträge seit 2011
vor 3 Jahren

Schaue ich mir an, danke dir.

Steven85 Themenstarter:in
99 Beiträge seit 2011
vor 3 Jahren

Hi Abt,

habe mir die Doku zu async und await angesehen und auch bereits angewendet bzw. nachvollzogen.
Habe hierzu noch eine Frage. Du sagst ja ich soll immer die async Methoden verwenden, als z.b. so:


private static async void UseCase_QueryTypesAsync(DataContext dbContext)
        {
            // nur zur Demonstration ein kleines View, hier brauch man keine Migration
            var result = await dbContext.VW_Test.ToListAsync();
            Console.WriteLine(string.Join("\n", result));
        }

Aber was bringt es in diesem Fall? Hier wird doch sowieso nur der eine Aufruf gemacht? Oder ist dann die Methode ToListAsync an sich schon schneller?

Edit: Habe es gerade mal mit der Klasse Stopwatch gemessen (jeweils 5-6 mal). Ich brauche mit async und await im Schnitt 0,2 Sekunden länger.

T
2.219 Beiträge seit 2008
vor 3 Jahren

Da deine Methode async void "liefert", hat dein Code hier keinen Vorteil.
Dadurch läufst du auch Gefahr, dass dein Code nicht auf das Ende der Methode wartet bzw. warten kann.

Der Sinn und Zweck von async/await ist gerade der asynchrone Ablauf von Methode in Verbindung mit Tasks um diese auch steuern zu können bzw. korrekt auf diese warten zu können.
Schau dir am besten nochmal die Doku an und liefere dann Task anstelle von void zurück.

Wenn du mit asynchronen Methoden z.B. bei IO Aufgaben arbeitest, merkst du die Vorteile.
In Verbindung mit einer UI (WPF/Windows Forms), kann man dann durch asynchrone Programmierung mit asnyc/await das bekannte einfrieren der Anwendungung sauber lösen.

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.806 Beiträge seit 2008
vor 3 Jahren

async/await hat große Vorteile die Ressourcen eines Systems effizient zu nutzen und blockierenden Code - wie er aktuell bei Dir ist - zu vermeiden.
Mit async/await kann man aber auch viel falsch machen, wenn man grundlegende Dinge nicht beachtet, wozu zB. der Pitfall async void gehört.
Avoid Async Void

Beachtet man die Grundzüge von async/await nicht, dann wirds Race Condition in Massen hageln und der Code wird ganz komisch Dinge machen.
Daher ist das ein super Thema mit dem Du beginnen kannst wirklich die Doku mal durchzuarbeiten, da dies wirklich notwendig ist.
Dann kann auch Dein Code davon profitieren.

2.078 Beiträge seit 2012
vor 3 Jahren

Ergänzend dazu:

Await, SynchronizationContext, and Console Apps

Mir hatte das sehr geholfen, die Hintergründe zu verstehen (- allerdings weiß ich nicht mehr, welchen Wissensstand ich da hatte 😄

Generell halte ich es beim Thema async/await für sehr wichtig, die Hintergründe wirklich verstanden zu haben, da hier viel "Magie" passiert, die man sonst kaum verstehen kann.
Aber überstürze es nicht, merk's dir bloß für später, wenn Du halbwegs damit umgehen kannst.

Einmal verstanden, stellt sich aber heraus, dass es doch gar nicht so viel Magie ist 😉