2

I am trying to delete some data (how hard can it be, anyway?) but whenever I remove a complex-type prop from my model object, the contents of an ICollection prop are also mixed. Here's the code:

    [HttpPost, ActionName("Delete")]
    public ActionResult DeleteConfirmed(string name)
    {
        using (var db = new HoursDb())
        {
            db.Configuration.ProxyCreationEnabled = false;

            var schedule = db.Schedules.Where(s => s.ScheduleId == name)
                .Include(s => s.WeekSpec)
                .Include(s => s.WeekSpec.DaySpecs)
                .Include(s => s.ExceptionHoursSets)
                .Include(s => s.ExceptionHoursSets.Select(e => e.WeekSpec))
                .Include(s => s.ExceptionHoursSets.Select(e => e.WeekSpec.DaySpecs))
                .FirstOrDefault();
            if (schedule == null)
            {
                return View("404");
            }


            var daySpecs = new List<DaySpec>(schedule.WeekSpec.DaySpecs);
            foreach (var daySpec in daySpecs)
            {
                db.DaySpecs.Remove(daySpec);
            }
            db.WeekSpecs.Remove(schedule.WeekSpec);

            var exceptionHoursSets = new List<ExceptionHoursSet>(schedule.ExceptionHoursSets);
            foreach (var exceptionHoursSet in exceptionHoursSets)
            {
                daySpecs = new List<DaySpec>(exceptionHoursSet.WeekSpec.DaySpecs);
                foreach (var daySpec in daySpecs)
                {
                    db.DaySpecs.Remove(daySpec);
                    db.SaveChanges();
                }
                db.WeekSpecs.Remove(exceptionHoursSet.WeekSpec);
                db.SaveChanges();
                db.ExceptionHoursSets.Remove(exceptionHoursSet);
            }

            db.Schedules.Remove(schedule);
            db.SaveChanges();

            return RedirectToAction("Index");
        }
    }

Before I fire off the line with

db.WeekSpecs.Remove(schedule.WeekSpec);

ExceptionHoursSets has, say, three items. After removing the WeekSpec, it has zero. Eh. Any ideas?

Update

Here's the code for the HoursDb class:

using System.Data.Entity;
using LibraryAdmin.Models;
using System.Data.Entity.ModelConfiguration.Conventions;

namespace ####.DAL
{
    public class HoursDb : DbContext
    {
        public DbSet<DaySpec> DaySpecs { get; set; }
        public DbSet<WeekSpec> WeekSpecs { get; set; }
        public DbSet<ExceptionHoursSet> ExceptionHoursSets { get; set; }
        public DbSet<Schedule> Schedules { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }
    }
}

Also, should it help, DaySpecs contain open and close hours for a generic building; they are contained in WeekSpecs.
The Schedule contains a WeekSpec to describe the general open hours, as well as a set of ExceptionHoursSets.
These have WeekSpecs describing exceptions to the aforementioned general hours.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Bondolin
  • 2,793
  • 7
  • 34
  • 62
  • What's HoursDb? is that EF db context? or just a home made repository pattern? I'm thinking the relational db is deleting it based on foreign keys – Rikon Aug 15 '12 at 13:31
  • @Rikon -- it is a Code First DbContext. I will add the code. – Bondolin Aug 15 '12 at 13:34

2 Answers2

0

My guess that in Database for relationship between WeekSpec and ExceptionHoursSet you have the cascade delete option enabled. So when you delete WeekSpec - you delete the same WeekSpec that you have in ExceptionHoursSet, and because you have cascade delete - EF deletes ExceptionHoursSet objects as well.

More than I think that this will be the right solution to use Cascade Delete option for relationship and do not use foreach to delete all child objects. Of course - you should use it only if you 100% sure that it is impossible to have WeekSpecs/ExceptionHoursSet/DaySpecs without Schedules.

outcoldman
  • 11,584
  • 2
  • 26
  • 30
  • Cascade deleting may have something to do with it. I do not see why it would cause a problem when deleting the WeekSpec in my question, as it is a prop of the schedule, not the schedule's exception sets (see my updated structure overview), which of course is why I also do not want it to cascade delete. How can I be sure that doesn't happen? – Bondolin Aug 15 '12 at 13:58
  • You should try to use SQL Profiler to take a look which SQL queries .NET trying to execute on each line of your code. This can give you some answers. – outcoldman Aug 15 '12 at 14:02
  • Don't know if I'll be able to use it or not, but thanks for the help. – Bondolin Aug 15 '12 at 14:12
0

Moving the foreach that deletes the ExceptionHoursSets to the front after the var schedule is initialized, as well as removing all but the last db.SaveChanges, seems to work. I still do not know why it does and what I had doesn't, though, so any additional information is appreciated.

Bondolin
  • 2,793
  • 7
  • 34
  • 62