Home > Software design >  Entity Framework Linq 1 to many query
Entity Framework Linq 1 to many query

Time:03-11

I know there are similar questions, but I can't seem to transfer the answers to my situation.

This is my database tables: Library - sorry for the Danish

I have CPR for a Låner. And I want to get objects for each Udlån with UdlånsDato, Afleveringsfrist from Udlån and the related Bog.Navn. Since There are a table, Kopi, between Udlån and Bog, I get confused. Each Bog has several Kopi. I am Spanning over 4 tables.

var udlånsliste = context.Udlån.Where(u => u.Låner.Cpr==cpr).Join(context.Kopier, udlån => udlån.Kopi.KopiID, kopi => kopi.KopiID,
                    (udlån, kopi) => new
                    {
                        KopiID=kopi.KopiID,
                        UdlånDato = udlån.Udlånsdato.ToString("MMMM dd, yyyy"),
                        UdlånsFrist = udlån.Afleveringsfrist.ToString("MMMM dd, yyyy"),
                    }
                    ).Join(context.Bøger, kopi=> kopi.KopiID, bog=> bog.Kopier.Any(k=>k.KopiID),
                    (kopi, bog) => new
                    {
                        BogNavn = bog.Navn,
                        UdlånDato = kopi.UdlånDato,
                        UdlånsFrist = kopi.UdlånsFrist,
                    }

                    ).ToList();
public class Bog
{
    public int BogID { get; set; }
    public string Navn { get; set; }
    public Forlag Forlag { get; set; }
    public Forfatter Forfatter { get; set; }
    public virtual List<Genre> Genrer { get; } = new List<Genre>();

    //Dobbeltrettet relation mellem bog og kopi. 
    //Vil gerne have det simpelt at finde hvilke bøger en låner har lånt
    //samt kunne danne nemt overblik over, hvor mange kopier af en bestemt bog er udlånt.
    //Det skulle gerne være den eneste dobbeltrettede relation i min model.
    //Jeg forventer databasen opretter foreignkey for bogen i databasen for kopi.
    public virtual List<Kopi> Kopier { get; } = new List<Kopi>();

    public Bog(string navn, Forfatter forfatter, Forlag forlag) : this() 
    { 
        Navn = navn;
        Forfatter = forfatter;
        Forlag = forlag;
    }
    
    public Bog()
    {
        Genrer = new List<Genre>();
        Kopier = new List<Kopi>();
    }

    //Sikrer tovejskobling
    public Genre AddGenre(Genre genre)
    {
        if (!Genrer.Contains(genre))
        {
            Genrer.Add(genre);
            genre.AddBog(this);
        }
        return genre;
    }

    //Komposition hvor Bog opretter nye kopiobjekter.
    //Det bliver eks. aldrig relevant at ændre relationen i en kop fra en bog til en anden
    public Kopi AddKopi(DateTime anskaffelsesdato)
    {
        var kopi = new Kopi(anskaffelsesdato,this);
        Kopier.Add(kopi);
        return kopi;
    }

    public override string ToString()
    {
        return Navn;
    }
}
public class Kopi
{
    public int KopiID { get; set; }
    public DateTime Erhvervelsesdato { get; set; }
    //Ingen set i komposition, hvor bog er helhedsobjektet.
    public Bog Bog { get; }

    public Kopi(DateTime erhvervelsesdato, Bog bog): this()
    {
        Erhvervelsesdato = erhvervelsesdato;
        Bog = bog;
    }

    public Kopi()
    {

    }
}
public class Udlån
{
    public int UdlånID { get; set; }
    public DateTime Udlånsdato { get; set; }
    public DateTime Afleveringsfrist { get; set; }

    [Column("Afleveret")]
    public int _Afleveret { get; set; }


    //Da databasen bool egentlig blot er en 0 eller 1 værdi i stedet for true og false,
    //så skal vi mappe denne property, så Databasen og Appen kan tale sammen. 
    [NotMapped]
    public bool Afleveret
    {
        get
        {
            return _Afleveret != 0;
        }
        set
        {
            _Afleveret = value ? 1 : 0;
        }
    }
    public Kopi Kopi { get; set; }
    public Låner Låner { get; set; }

    //Tænkte først at lave udlånsdato til nu, men da jeg gerne ville have testdata med overskreden frist,
    //duer det ikke.
    public Udlån(DateTime udlånsdato,Kopi kopi, Låner låner): this()
    {
        Udlånsdato= udlånsdato;
        Afleveringsfrist = udlånsdato.AddDays(14);
        Afleveret = false;
        Kopi = kopi;
        Låner = låner;
    }

    public Udlån()
    {

    }


    public Boolean toggleAfleveret()
    {
        if (Afleveret == true) {
            Afleveret = false;
            return false;
            }
        else
        {
            Afleveret = true;
            return true;
        }
    }

    public override string ToString()
    {
        return "Udlånsdato: " Udlånsdato.ToString("MMMM dd, yyyy")   " Afleveringsdato: " Afleveringsfrist.ToString("MMMM dd, yyyy");
    }

}
public class Låner
{
    //CPR er allerede unik, derfor bruges det som key
    [Key]
    public string Cpr { get; set; }    
    public string Navn { get; set; }
    public int Tlf { get; set; }

    public Låner(string cpr, string navn, int tlf): this()
    {
        Cpr = cpr;
        Navn = navn;
        Tlf = tlf;
    }

    public Låner()
    {

    }

    public override string ToString()
    {
        return "CPR: "  Cpr " Navn: "  Navn " Tlf: " Tlf;
    }
}

CodePudding user response:

If I understand your question and your Model correctly, you do not need explicit joins at all, just use navigation properties.

var query = context.Udlån
    .Where(u => u.Låner.Cpr == cpr)
    .Select(udlah => new 
    {
        BogNavn = udlah.Kopi.Bog.Navn,
        UdlånDato = udlah.UdlånDato.ToString("MMMM dd, yyyy"),
        UdlånsFrist = udlån.Afleveringsfrist.ToString("MMMM dd, yyyy"),
    });

CodePudding user response:

Svyatoslav said I could just navigate the properties through the model and did not have to use the table connections. I feel folish. Sadly I deleted my Kopy class just before the answer.

  • Related