I'm working with an entity framework project where I'm struggling to remove an Item out of one of my collections. I have firstly a "One to Many" relation created between my object "Resto" and "OpeningTimes" the following way:
In my model:
[Table("Resto")]
public class Resto
{
public int Id { get; set; }
public string Name { get; set; }
public string PhoneNumber { get; set; }
public string Address { get; set; } //TODO Ajouter adresse détaillées
public virtual ICollection<SlotTime> OpeningTimes {get; set;}
public virtual ICollection<ApplicationUser> Administrators { get; set; }
public virtual ICollection<ApplicationUser> Chefs { get; set; }
public virtual Menu Menu {get; set;}
}
[Table("RestoSlotTimes")]
public class SlotTime
{
public int SlotTimeId { get; set; }
public DayOfWeek DayOfWeek { get; set; }
public TimeSpan OpenTime { get; set; }
public TimeSpan CloseTime { get; set; }
public int RestoId { get; set; }
public virtual Resto Resto { get; set; }
}
Since I have other relation from that object (see the one from Applications User) I'm also using Fluent language to remove ambiguities.
The following way:
modelBuilder.Entity<Resto>()
.HasMany<ApplicationUser>(s => s.Administrators)
.WithMany(c => c.Resto_Admin)
.Map(cs =>
{
cs.MapLeftKey("Resto_Admin");
cs.MapRightKey("Admin");
cs.ToTable("RestosAdmins");
});
modelBuilder.Entity<Resto>()
.HasMany<ApplicationUser>(s => s.Chefs)
.WithMany(c => c.Resto_Chefs)
.Map(cs =>
{
cs.MapLeftKey("Resto_Chefs");
cs.MapRightKey("Chef");
cs.ToTable("RestosChefs");
});
modelBuilder.Entity<Resto>()
.HasOptional(s => s.Menu)
.WithRequired(ad => ad.resto)
.WillCascadeOnDelete(true);
But those relations are working fine.
Today I do basic operations on my "OpeningTimes" in my controller as adding a item in the DB with the following:
[HttpPost]
public async Task<ActionResult> AddSlotTimeToRestaurant(AddSlotTimeToRestaurantView model)
{
var resto = await DbManager.Restos.FirstAsync(r => r.Id == model.RestoId);
if(resto != null)
{
if(model.OpenTimeId < model.CloseTimeId)
{
SlotTime slotTime = new SlotTime()
{
DayOfWeek = model.Day,
OpenTime = model.SlotTimeList.timeSpanViews.FirstOrDefault(m => m.Id == model.OpenTimeId).TimeSpan,
CloseTime = model.SlotTimeList.timeSpanViews.FirstOrDefault(m => m.Id == model.CloseTimeId).TimeSpan
};
resto.OpeningTimes.Add(slotTime);
await DbManager.SaveChangesAsync();
return RedirectToAction("edit", new { id = model.RestoId });
}
else
{
ModelState.AddModelError("SelectedSlotTimeId_1_Stop", "L'heure de fermeture doit être après l'heure d'ouverture");
return View();
}
}
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
This code is working as expected. But now one I try to do another function for removing the object with he following code:
public async Task<ActionResult> RemoveSlotTimeToRestaurant(int RestoId, int SlotId)
{
var resto = await DbManager.Restos.FirstAsync(r => r.Id == RestoId);
if (resto != null)
{
SlotTime slotTime = resto.OpeningTimes.FirstOrDefault(m => m.SlotTimeId == SlotId);
if(slotTime != null)
{
resto.OpeningTimes.Remove(slotTime);
await DbManager.SaveChangesAsync();
return RedirectToAction("edit", new { id = RestoId });
}
}
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
I have an error on the DbSave line... Where it looks like EF try not to remove my object but just to keep it and set its ID to Null... Which is not what I expect
The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted
I have the feeling my relation is well configured for EF. I feel like doing the add and removing relation properly... Do you think this can come from the fluent configuration?
BTW once I remove the "Resto" I have the cascade deleting working well where all my items "OpeningTimes" are well deleted out of the DB without error.