I’m building a Blazor Wasm Webap with Asp net EF 8.
I have the following setup:
public class EventRole
{
//Composite Key
public long EventId { get; set; }
public string Name { get; set; }
//Backwards Reference
[ForeignKey(nameof(EventId))]
public Event? Event { get; set; }
}
public class EventParticipant
{
//Composite Key
public long EventId { get; set; }
public long UserId { get; set; }
//Content
public ICollection<EventRole> Roles { get; set; } = new HashSet<EventRole>();
[ForeignKey(nameof(EventId))]
public Event? Event { get; set; }
[ForeignKey(nameof(UserId))]
public User? User { get; set; }
}
public class Event
{
public long Id { get; set; }
public ICollection<EventParticipant> Participants { get; set; } = new HashSet<EventParticipant>();
public ICollection<EventRole> Roles { get; set; } = new HashSet<EventRole>();
}
So in my Context I setup the following Keys:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//Primary Keys
modelBuilder.Entity<EventParticipant>().HasKey(p => new { p.EventId, p.UserId });
modelBuilder.Entity<EventRole>().HasKey(r => new { r.EventId, r.Name });
//modelBuilder.Entity<EventParticipantRole>().HasKey(pr => new { pr.EventId, pr.UserId, pr.RoleName });
//AutoInclude Properties
modelBuilder.Entity<Event>().Navigation(e => e.Participants).AutoInclude();
modelBuilder.Entity<Event>().Navigation(e => e.Roles).AutoInclude();
modelBuilder.Entity<EventParticipant>().Navigation(p => p.User).AutoInclude();
modelBuilder.Entity<EventParticipant>().Navigation(p => p.Roles).AutoInclude();
}
In my Blazor App (client Side) I wrote the following Post:
Event ev = new Event();
EventParticipant participant = new EventParticipant()
{
User = user;
}
EventRole role = new EventRole
{
Name = "Organisation"
}
EventRole role2 = new EventRole
{
Name = "BudgetControl"
}
participant.Roles.Add(role);
participant.Roles.Add(role2);
ev.Roles.Add(role);
ev.Roles.Add(role2);
ev.Participants.Add(participant);
await Http.PostAsJsonAsync<Event>("api/Events", ev);
The EventsController has the default scaffolded PostEvent method with:
_context.Events.Add(@event);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetEvent), new { id = @event.Id }, @event);
Now when running the above code I get the following Error:
System.InvalidOperationException: The value of 'EventRole.EventId' is unknown when attempting to save changes. This is because the property is also part of a foreign key for which the principal entity in the relationship is not known.
Especially due to the last part of the error I have the feeling that my relations are just not well chosen. However I see that this error happens due to the deserialization of the json. After deserializing, EF does not know wether the Roles within the Participants are new Roles or the same Roles as within the Event.
So my question is: How can I tell EF, that the deserialized Objects of Roles within the Participants, are the same as the ones in the Event and so assigns the same Entity-Reference (And EventId) to the Participant-Roles? Do I need to change my DataModel for this?
In case it is important: For testing purposes I’m currently using In Memory Database.