简体   繁体   中英

EF Core relations between tables

I'm quite new to EF Core. I don't undestand the logic of relations betweek table.

In my DataContext:

modelBuilder.Entity<CorsoStepLezioneSessione>()
                .HasKey(x => new { x.codCorso, x.codStep, x.codLezione, x.codSessione });
            modelBuilder.Entity<CorsoStepLezioneSessione>()
                .HasOne(sessione => sessione.Lezione)
                .WithMany(lezione => lezione.Sessioni)
                .HasForeignKey(sessione => new { sessione.codCorso, sessione.codStep, sessione.codLezione });

modelBuilder.Entity<CorsoStepLezione>()
                .HasMany(lez => lez.Sessioni)
                .WithOne(sess => sess.Lezione)
                .HasForeignKey(sess => new { sess.codCorso, sess.codStep, sess.codLezione });

Entities:

public class CorsoStepLezione
    {
        public int codCorso { get; set; }
        public int codStep { get; set; }
        public int codLezione { get; set; }
        public string nome { get; set; }


        public CorsoStepS CorsoStep { get; set; }
        public List<CorsoStepLezioneSessione> Sessioni { get; set; }
    }

public class CorsoStepLezioneSessione
    {
        public int codCorso { get; set; }
        public int codStep { get; set; }
        public int codLezione { get; set; }
        public int codSessione { get; set; }
        public DateTime? data { get; set; }
        public string ora { get; set; }
        
        public CorsoStepLezione Lezione { get; set; }
        public List<CorsoStepLezioniSessioniIscrizione> Iscrizioni { get; set; }

    }

In a service when I call

var x = _clienteContext.CorsoStepLezioneSessioni.Include(x => x.Lezione)
                    .Where(x => x.codCorso == codCorso && x.codStep == codStep && x.codLezione == codLezione && x.codSessione == codSessione).ToList();

it gives me: "The expression 'x.Lezione' is invalid inside an 'Include' operation, since it does not represent a property access: 't => t.MyProperty'. To target navigations declared on derived types, use casting ('t => ((Derived)t).MyProperty') or the 'as' operator ('t => (t as Derived).MyProperty'). Collection navigation access can be filtered by composing Where, OrderBy(Descending), ThenBy(Descending), Skip or Take operations. For more information on including related data, see http://go.microsoft.com/fwlink/?LinkID=746393."

Can you give me some advice?

The composite keys and property naming are going to make things a bit difficult to pick apart, but one thing you should avoid with EF is declaring relationships from both ends. Is seems rather unusual to have several levels of entity relationships using composite keys. Do you have tables and entities for each of the following?

  • Corso
  • Step
  • Lezione
  • Sessione
  • CorsoStepLezione
  • CorsoStepLezioneSessione

Given a Class A references a collection of Class B, and Class B contains a reference back to A, you should map the relationship from one side or the other, not both:

Ie (My EF Core mapping syntax might not be 100% accurate)

modelBuilder.Entity<A>()
    .HasMany(a => a.Bs)
    .WithOne(b => b.A)
    .Required()
    .HasForeignKey(b => b.AId);

or

modelBuilder.Entity<B>()
    .HasOne(B => b.A)
    .Required()
    .WithMany(a => a.Bs)
    .HasForeignKey(b => b.AId);

Not both of the above.

When it comes to 1-to-many relationships I configure from the "1" side, so in this case I would remove:

modelBuilder.Entity<CorsoStepLezioneSessione>()
    .HasOne(sessione => sessione.Lezione)
    .WithMany(lezione => lezione.Sessioni)
    .HasForeignKey(sessione => new { sessione.codCorso, sessione.codStep, sessione.codLezione });

... just leaving the relationship declared on the CorsoStepLezione side.

What you do need is to define the PK on CorsoStepLezioneSessione:

modelBuilder.Entity<CorsoStepLezioneSessione>()
    .HasKey(s => new s.codCorso, s.codStep, s.codLezione, s.codSessone });

One other recommendation:

Declare navigation properties as virtual and for collections, declare them as virtual ICollection<T> rather than List<T> . This helps ensure that EF proxies for lazy loading and change tracking can work with these navigation properties effectively.

I'm not sure that the double-mapping would explain the error, it seems more like EF does not consider the CorsoStepLezione as a valid entity type. If you are using any inheritance or other mapping configuration for this class that might help explain the behaviour.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM