Domanda EF Code first Relazione Required/Optional

  • lunedì 31 ottobre 2011 11:22
     
      Contiene codice

    salve a tutti,
    Sto facendo i primi passi con EF code first e sono in questa situazione :

     

    public class City   
    {       
           private Guid m_ID;
           private string m_CityName = string.Empty;
           public string CityName
           {
               get { return m_CityName; }
               set { m_CityName = value; }
           }
           public Guid ID
           {
               get { return m_ID; }
               set { m_ID = value; }
           }
        }
        public class TicketGroup
        {
            private Guid m_ID;
            private City m_From;
            public City From
            {
                get { return m_From; }
                set { m_From = value; }
            }
            public Guid ID
            {
                get { return m_ID; }
                set { m_ID = value; }
            }
        }
    

    Una City può vivere di vita propria(senza che alcun TicketGroup le faccia riferimento) ma una TicketGroup deve avere una CityFrom. Queste le tabelle


    TicketGroups
     ID [uniqueidentifier] NOT NULL,
     FromCity [uniqueidentifier] NOT NULL

    Cities
     ID [uniqueidentifier] NOT NULL,
     CityName [varchar](50) NOT NULL

     

    In OnmodelCreating ho definito la relazione cosi

     

    modelBuilder.Entity<TicketGroup>().HasRequired(TG => TG.From).WithOptional().Map(map => { map.MapKey("FromCity"); }).WillCascadeOnDelete(false);
    

    Perchè da quanto ho capito HasRequired indica che per TicketGroup é obbligatorio e WithOptional indica che per City è opzionale e sembra funzionare tranne che in questo caso :


                    City C = new City();

                    C.ID = Guid.NewGuid();
                    C.CityName="TestCity";

                    TicketGroup TG = new TicketGroup();
                    TG.ID = Guid.NewGuid();
                    TG.From = C;

                    TicketGroup TG1 = new TicketGroup();
                    TG1.ID = Guid.NewGuid();
                    TG1.From = C;

                    DB.TicketGroups.Add(TG);
                    DB.TicketGroups.Add(TG1);

                    DB.SaveChanges();

    al SaveChanges ottengo l'eccezione
    Le entità in 'FlightContext.TicketGroups' fanno parte della relazione 'TicketGroup_From'. Trovati 'TicketGroup_From_Target' correlati a 0. Previsto 1 'TicketGroup_From_Target'.


    Mentre se aggiungo un solo TG, non mi da problemi. Ho Provato a sostituire WithOptional con WithMany e funziona anche con due inserimenti, ma questo cambia la natura della relazione.
    Potreste aiutarmi a trovare cosa non ho capito?

    Grazie

     

Tutte le risposte

  • lunedì 31 ottobre 2011 18:50
    Postatore
     
      Contiene codice
    Il problema per EF è che in City non hai mappato la navigation property ICollection<TicketGroups> Tickets { get; set; }.

    Se intanto vuoi farlo funzionare devi aggiungere la navigation property e mapparla nella entity City:
    modelBuilder
        .Entity<TicketGroup>()
        .HasRequired(x => x.From)
        .WithMany(x => x.Tickets)
        .Map(map => map.MapKey("FromCityId"))
        .WillCascadeOnDelete(false);
    


    Sto verificando se è possibile evitarla.


    Matteo Migliore

    Bloghttp://blogs.ugidotnet.org/matteomigliore
    Twitterhttp://twitter.com/matteomigliore
    CodePlex
  • martedì 1 novembre 2011 08:31
     
      Contiene codice
    Il problema per EF è che in City non hai mappato la navigation property ICollection<TicketGroups> Tickets { get; set; }.

    Se intanto vuoi farlo funzionare devi aggiungere la navigation property e mapparla nella entity City:
    modelBuilder
        .Entity<TicketGroup>()
        .HasRequired(x => x.From)
        .WithMany(x => x.Tickets)
        .Map(map => map.MapKey("FromCityId"))
        .WillCascadeOnDelete(false);
    


    Sto verificando se è possibile evitarla.


    Matteo Migliore

    Bloghttp://blogs.ugidotnet.org/matteomigliore
    Twitterhttp://twitter.com/matteomigliore
    CodePlex


    Ciao Matteo, grazie per la tua consueta disponibilità.

    Come ho scritto nel post precedente, usando .WithMany() funziona, indipendentemente dal fatto che in City ci sia la navigation property sui ticket oppure no. Daltronde, guardando su MSDN WithMany ha due firme, una per quando dall'altra parte non c'è la Navigazion Property WithMany() e l'altra per quando dall'altra parte c'è la navigation Property WitMany(Expression<Func<TTargetEntityType, ICollection<TEntityType>>> navigationPropertyExpression). Entrambe funzionano.

    Il punto è che io sto cercando di usare WithOptional e qui mi sta venendo il dubbio, visto che dall'altra parte(in City) posso anche non avere Ticket che fanno riferimento ad una City, devo usare WithOptional, oppure WithOptional indica che dall'altra parte, City può avere solo un Ticket(Relazione 1..0-1) Mentre io voglio specificare che una City può avere più Ticket?

    Spero di non essermi incartato troppo

     

     

  • martedì 1 novembre 2011 20:13
     
      Contiene codice
    Il problema per EF è che in City non hai mappato la navigation property ICollection<TicketGroups> Tickets { get; set; }.

    Se intanto vuoi farlo funzionare devi aggiungere la navigation property e mapparla nella entity City:
    modelBuilder
        .Entity<TicketGroup>()
        .HasRequired(x => x.From)
        .WithMany(x => x.Tickets)
        .Map(map => map.MapKey("FromCityId"))
        .WillCascadeOnDelete(false);
    


    Sto verificando se è possibile evitarla.


    Matteo Migliore

    Bloghttp://blogs.ugidotnet.org/matteomigliore
    Twitterhttp://twitter.com/matteomigliore
    CodePlex


    Ciao Matteo, grazie per la tua consueta disponibilità.

    Come ho scritto nel post precedente, usando .WithMany() funziona, indipendentemente dal fatto che in City ci sia la navigation property sui ticket oppure no. Daltronde, guardando su MSDN WithMany ha due firme, una per quando dall'altra parte non c'è la Navigazion Property WithMany() e l'altra per quando dall'altra parte c'è la navigation Property WitMany(Expression<Func<TTargetEntityType, ICollection<TEntityType>>> navigationPropertyExpression). Entrambe funzionano.

    Il punto è che io sto cercando di usare WithOptional e qui mi sta venendo il dubbio, visto che dall'altra parte(in City) posso anche non avere Ticket che fanno riferimento ad una City, devo usare WithOptional, oppure WithOptional indica che dall'altra parte, City può avere solo un Ticket(Relazione 1..0-1) Mentre io voglio specificare che una City può avere più Ticket?

    Spero di non essermi incartato troppo

     

     


    Ciao,
    rileggendo un po, forse avevo capito male.

    Se guardo la firma di WithOptional

            public ForeignKeyNavigationPropertyConfiguration WithOptional(Expression<Func<TTargetEntityType, TEntityType>> navigationPropertyExpression);
    


    Vuole una TEntityType non una ICollection<TEntityType>

    Quindi WithOptinals indica che dall'altra parte, una City può avere una relazione con un solo Ticket mentre WithMany riceve una ICollection<TEntityType> che è quello che devo fare io.