Domanda

I have problems defining an entity that has two one-to-many relations (two lists)

public class Calendar
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public Guid ID { get; set; }


    public virtual IList<Appointment> FreeSlots { get; set; }
    public virtual IList<Appointment> AppointmentsList { get; set; }
    ...
}

public class Appointment
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int AppointmentID { get; set; }
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
    public String Type { get; set; }       
    public String Info { get; set; }
    public Guid CalendarID { get; set; }       
    public virtual Calendar Calendar { get; set; }
 }

And code-first code:

modelBuilder.Entity<Appointment>().HasKey(u => new {u.AppointmentID, u.CalendarID });
        modelBuilder.Entity<Appointment>().HasRequired(u => u.Calendar).WithMany(c => c.FreeSlots).HasForeignKey(f => f.CalendarID).WillCascadeOnDelete(true);
        modelBuilder.Entity<Appointment>().HasRequired(u => u.Calendar).WithMany(c => c.AppointmentsList).HasForeignKey(f => f.CalendarID).WillCascadeOnDelete(true);

Appointment has two PK because I want the appointment to be deleted if the calendar is deleted.

When I try to add a new appointment to the FreeSlot, I get the following error: An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception.

I have tried with this mapping too with no luck:error 0040: Type Calendar_FreeSlots is not defined in the namespace Project.DAL (Alias=Self).

modelBuilder.Entity<Appointment>().HasKey(u => new {u.AppointmentID, u.CalendarID });           
        modelBuilder.Entity<Calendar>().HasMany(c => c.FreeSlots).WithRequired(c => c.Calendar).HasForeignKey(c => c.CalendarID).WillCascadeOnDelete();
        modelBuilder.Entity<Calendar>().HasMany(c => c.AppointmentsList).WithRequired(c => c.Calendar).HasForeignKey(c => c.CalendarID).WillCascadeOnDelete();

I guess the problem is that I have two one-to-many relations to the same type of entity but I do not know the way to make it correctly.

È stato utile?

Soluzione

The mistake in your mapping is that you use Appointment.Calendar twice for two different relationships. That's not possible. You would need a second pair of FK and navigation properties in Appointment (or map one relationship without inverse properties):

modelBuilder.Entity<Calendar>()
    .HasMany(c => c.FreeSlots)
    .WithRequired(c => c.Calendar1)
    .HasForeignKey(c => c.Calendar1ID)
    .WillCascadeOnDelete(false);

modelBuilder.Entity<Calendar>()
    .HasMany(c => c.AppointmentsList)
    .WithRequired(c => c.Calendar2)
    .HasForeignKey(c => c.Calendar2ID)
    .WillCascadeOnDelete(true);

(For at least one relationship you must disable cascading delete. Otherwise you'll end up with a multiple cascading delete exception.)

However, I have the feeling that you actually should have only one relationship and collection Calendar.Appointments and a kind of status in Appointment, like a bool IsFree property. You could then always extract the free slots of a calendar entry with calendar.Appointments.Where(a => a.IsFree).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top