views:

92

answers:

5

Hello

I have this code:

Schedule s = _entities.Schedules.Where(x => x.ScheduleID == schedule.ScheduleID && x.BookingObject.BookingObjectID == bookingObjectID).FirstOrDefault();

if(s == null)
    s = new Schedule();

s.ScheduleStart = schedule.ScheduleStart;
s.ScheduleEnd = schedule.ScheduleEnd;

foreach (var t in schedule.Timetables)
{   
    s.Timetables.Add(t);
}

_entities.AddToSchedules(s);

_entities.SaveChanges();

Exception: System.InvalidOperationException

the object schedule gets passed in as a parameter

EDIT:

changed to:

  Schedule sh = new Schedule();


  sh.ScheduleStart = schedule.ScheduleStart;
  sh.ScheduleEnd = schedule.ScheduleEnd;

  foreach (var t in schedule.Timetables)
  {
       //sh.Timetables.Add(t);  // doesn't work
        sh.Timetables.Add(new Timetable { DayOfWeek = t.DayOfWeek, StartTime = t.StartTime, EndTime = t.EndTime });   // works
  }

  _entities.AddToSchedules(sh);

  _entities.SaveChanges();

is there some logical reason why sh.Timetables.Add(t) doesn't work since its a collection of Timetable?

/M

+1  A: 
s.Timetables.Add(schedule.Timetables)

if this isn't the case, it's likely your question needs more information. What is s.Timetables, schedule.Timetables? (types)

neouser99
schedule.Timetables is a Entitycollection<Timetable> and I can't seem to add more than 1 if I put s.Timetables.Add. "cannot convert from 'System.Data.Objects.DataClasses.EntityCollection<BookingSystem.Data.Models.Timetable>' to 'BookingSystem.Data.Models.Timetable'"
molgan
Add() takes a base object, not a collection. Iterate through the source collection with foreach, and Add() each object to the destination collection.
Donnie DeBoer
+2  A: 
foreach(var time in schedule.Timetables){
     s.Timetables.Add(time)
}

You can loop over the time tables in schedule.Timetables and add them to your new entity.

Dan
sadly I get an error (swedish one), something about value has been modified and it cant loop through them
molgan
Are you getting an InvalidOperationException in foreach because the source collection was modified? If so, make sure you aren't trying to add elements of schedule.Timetables to itself (as opposed to adding them to s.Timetables)
Donnie DeBoer
updated my post. And I get that exception. Not sure why though, its the newly created object I want to save to dateabase so
molgan
molgan - I'm pretty sure it's because of EF automatic fixup modifying the collection under the hood. See my answer below
Alex James
+1  A: 

Another option would be:

((List<TimeTable>)s.Timetables).AddRange(((List<TimeTable>)schedule.Timetables));
Bryan Rowe
If Dan's answer didn't work, mine won't either.
Bryan Rowe
They both should work.
Donnie DeBoer
+1  A: 

Look at the first few lines:

Schedule s = _entities.Schedules.Where(x => x.ScheduleID == schedule.ScheduleID && x.BookingObject.BookingObjectID == bookingObjectID).FirstOrDefault();

if(s == null)
    s = new Schedule();

On the first line, you're querying the database for an object with the same ScheduleID as schedule and storing the returned reference in s. Assuming that object is available in the database, you're effectively pointing s at the same object as schedule. That means s.Timetables and schedule.Timetables are the same collection, which will cause the exception you're getting during the foreach.

I assume you only want to clone the object pointed to by schedule and insert it into the database if it is not already in the database. In that case:

Schedule s = _entities.Schedules.Where(x => x.ScheduleID == schedule.ScheduleID && x.BookingObject.BookingObjectID == bookingObjectID).FirstOrDefault();

if(s == null)
{
    s = new Schedule();

    s.ScheduleStart = schedule.ScheduleStart;
    s.ScheduleEnd = schedule.ScheduleEnd;

    foreach (var t in schedule.Timetables)
    {   
        s.Timetables.Add(t);
    }

    _entities.AddToSchedules(s);

    _entities.SaveChanges();
}
Donnie DeBoer
changed but I get same exception still.
molgan
when you debug and step through, do you see anything informative happening?
Bryan Rowe
+1  A: 

UPDATE: Just confirmed that this is likely to be the reason. And created a new tip in my tips series to explain.

I can think of one possible reason.

Is the relationship between schedule.Timetables one to many? I.e. a timetable can only be assigned to one schedule at a time?

If so this is failing:

  foreach (var t in schedule.Timetables)  {       
     sh.Timetables.Add(t); 
  }

Because as you add the 't' to a different schedule it is automatically removed from the old schedule.Timetables collection, which of course modifies the collection you are enumerating, which is a no-no.

if so the solution is simply to do something like this:

  var timetables = schedule.Timetables.ToArray();
  foreach (var t in timetables)  {       
     sh.Timetables.Add(t); 
  }

Here you enumerate the collection, before you start modifying it.

Is that it?

Alex

Alex James