Reputation: 2711
I have three classes
Event, Dog, Result
Each dog can participate in many events and for each event he will get a score related to this specifik event. Thus must mean that my result-class must contain 2 foreign keys. 1 that specifies the event and 1 that specifies the dog. I am very confused about how to set this up. I´ve been getting som help with this earlier and I hope someonen can help me again:
Here are my classes now:
public class Dog {
public int DogId { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public bool Checked { get; set; }
public string DogImage { get; set; }
[ForeignKey("Event")]
public int EventID { get; set; }
public virtual ICollection<Result> Results { get; set; }
public virtual Event Event { get; set; }
}
public class Event
{
public int EventId { get; set; }
public string EventName { get; set; }
public string EventLocation { get; set; }
public string EventType { get; set; }
public string EventDate { get; set; }
public virtual ICollection<Dog> Dogs { get; set; }
}
public class Result
{
public int ResultId { get; set; }
public int Track { get; set; }
public int Obedience { get; set; }
public int Protection { get; set; }
[ForeignKey("Dog")]
public int DogId { get; set; }
public virtual Dog Dog { get; set; }
}
Help appreciated, thanks!
EDIT:
Ok, this is how it looks now. I should tellyou that when i tried to do a mgration with these updates I received an error ending with: may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
I added this method in my dbcontext and it took care of that provblem(I Think...)
public class EfdbContext : DbContext
{
public DbSet<Event> Events { get; set; }
public DbSet<Dog> Dogs { get; set; }
public DbSet<Result> Results { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Event>()
.HasRequired(c => c.Results)
.WithMany()
.WillCascadeOnDelete(false);
}
Now when I try to migrate I get this error:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_dbo.Events_dbo.Results_Results_ResultId". The conflict occurred in database "CloudDog.EFDB.EfdbContext", table "dbo.Results", column 'ResultId'. And this is how my classes look now:
public class Event
{
public int EventId { get; set; }
public string EventName { get; set; }
public string EventLocation { get; set; }
public string EventType { get; set; } //Dropdown med tävlingar
public string EventDate { get; set; } //Picker
public virtual ICollection<Dog> Dogs { get; set; }
public virtual ICollection<Result> Results { get; set; }
}
public class Dog
{
public int DogId { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public bool Checked { get; set; }
public string DogImage { get; set; }
[ForeignKey("Event")]
public int EventId { get; set; }
public virtual ICollection<Merit> Merits { get; set; }
public virtual ICollection<Result> Results { get; set; }
public virtual Event Event { get; set; }
}
public class Result
{
public int ResultId { get; set; }
public int Track { get; set; }
public int Obedience { get; set; }
public int Protection { get; set; }
[ForeignKey("Dog")]
public int DogId { get; set; }
public virtual Dog Dog { get; set; }
[ForeignKey("Event")]
public int EventId { get; set; }
public virtual Event Event { get; set; }
}
Upvotes: 1
Views: 321
Reputation: 109255
In your previous question you didn't tell the whole story. In itself the solution was correct. When there is nothing but a many-to-many association between two classes then EF can model this by a junction table that remains invisible in the class model.
But now you add more information to this junction table. This means that the table must be represented as a class in the class model, otherwise you'll never be able to access this information. Now your model should look like this (reduced to the essentials):
public class Dog
{
public int DogId { get; set; }
public virtual ICollection<Result> Results { get; set; }
}
public class Event
{
public int EventId { get; set; }
public virtual ICollection<Result> Results { get; set; }
}
public class Result
{
public int ResultId { get; set; }
[ForeignKey("Dog")]
public int DogId { get; set; }
public virtual Dog Dog { get; set; }
[ForeignKey("Event")]
public int EventId { get; set; }
public virtual Dog Event { get; set; }
}
Logically, there's still a many-to-many association between Dog
and Event
, but technically it is implemented as a 1-n-1 association. So by adding information you sacrifice the shortcut access from Dog
s to Event
s and back. This is very common though. I don't often see pure many-to-many associations. Sooner or later people start storing information about the association.
Now if you want to fetch a Dog
's Event
s, you'll have to write a somewhat more complicated query:
from d in Dogs
from r in d.Results
select r.Event
Upvotes: 2
Reputation: 16131
The ‘Result‘ class is the junction table that embodies the many to many relation between dogs and events. So the Dogs property on Event and the Events property on Dog should be An ICollection of Result. The Result class is really a DogInEvent class.
Upvotes: 1