Running into a problem with Code-First models in .NET MVC4, using EF4. I'm in Visual Studio 2012, if it matters, connected to a remote server.
I get the following error whenever I try to seed my database with some default values from my code:
---> System.Data.Entity.Infrastructure.DbUpdateException: An error occurred while
saving entities that do not expose foreign key properties for their relationships. The
EntityEntries property will return null because a single entity cannot be identified as
the source of the exception. Handling of exceptions while saving can be made easier by
exposing foreign key properties in your entity types. See the InnerException for
details.
---> System.Data.UpdateException: An error occurred while updating the entries. See the
inner exception for details.
---> System.Data.SqlClient.SqlException: The conversion of a datetime2 data type to a
datetime data type resulted in an out-of-range value.
I have a requirement to use GUIDs for my models, but the line in question is an attempt to call the following:
// schedules is a list of schedules I've already created.
foreach (var scheduleGuid in scheduleGuids)
{
var s = scheduleGuids.IndexOf(scheduleGuid);
var schedule = new Schedule
{
StartDate = new DateTime(1989, 1, 1),
EndDate = new DateTime(1989, 1, 7),
Id = scheduleGuid,
Status = ScheduleStatus.Inactive,
Recurring = true
};
var shifts = new List<Shift>();
var shiftIndex = (s * 5);
var days = shiftIndex + 5;
for (var si = shiftIndex; si < (days); si++)
{
Debug.WriteLine("schedule {0}, shift {1}, total shift: {2}", s, (si > 5 ? si / 5 : si), si);
var shiftGuid = shiftGuids[si];
var d = shiftGuids.IndexOf(shiftGuid);
var shift = new Shift {Schedule = schedule, Id = shiftGuid};
switch (s)
{
case (0):
shift.StartTime = schedule.StartDate.Add(d.Days()).At(6, 30);
shift.Duration = (8.Hours() + 30.Minutes());
break;
case (1):
shift.StartTime = schedule.StartDate.Add(d.Days()).At(6, 30);
shift.Duration = (10.Hours() + 30.Minutes());
break;
case (2):
shift.StartTime = schedule.StartDate.Add(d.Days()).At(8, 30);
shift.Duration = (10.Hours() + 30.Minutes());
break;
case (3):
shift.StartTime = schedule.StartDate.Add(d.Days()).At(9, 30);
shift.Duration = (10.Hours() + 30.Minutes());
break;
case (4):
shift.StartTime = schedule.StartDate.Add(d.Days()).At(11, 30);
shift.Duration = (10.Hours() + 30.Minutes());
break;
case (5):
shift.StartTime = schedule.StartDate.Add(d.Days()).At(22, 00);
shift.Duration = (10.Hours() + 30.Minutes());
break;
case (6):
shift.StartTime = schedule.StartDate.Add(d.Days()).At(20, 00);
shift.Duration = (10.Hours() + 30.Minutes());
break;
}
shift.Description = string.Format("{4}: {0} {1} {2}, {3} - Default Shift", shift.DayOfWeek, shift.StartTime.ToString("MMMM"), shift.DayOfMonth, shift.StartTime.ToString("yyyy"), Enum.GetName(typeof(ShiftType), shift.Type));
//context.Shifts.AddOrUpdate(shift);
shifts.Add(shift);
}
schedule.Shifts = shifts;
schedules.Add(schedule);
context.Shifts.AddOrUpdate(shifts.ToArray());
context.Schedules.AddOrUpdate(schedule);
}
It fails out at context.Shifts.AddOrUpdate(shifts.ToArray());
Here are the models in question:
public class Schedule
{
[Key]
public Guid Id { get; set; }
[ForeignKey("User")]
public Guid? UserId { get; set; }
public virtual ScheduleUser User { get; set; }
public virtual ICollection<ScheduleRule> Rules { get; set; }
public virtual ICollection<Shift> Shifts { get; set; }
[Required]
[DisplayFormat(NullDisplayText = "", DataFormatString= "{0:d}")]
[Display(Name = "Start Date")]
public DateTime StartDate { get; set; }
[Required]
[DisplayFormat(NullDisplayText = "", DataFormatString = "{0:d}")]
[Display(Name = "End Date")]
public DateTime EndDate { get; set; }
[Required]
public bool Recurring { get; set; }
[Required]
public bool Enabled { get; set; }
public bool Temporary
{
get
{
return (ToBeEnabledOn.HasValue && ToBeDisabledOn.HasValue);
}
}
[Column(TypeName = "datetime2")]
public DateTime? EnabledOn { get; set; }
[Column(TypeName = "datetime2")]
public DateTime? ToBeEnabledOn { get; set; }
[Column(TypeName = "datetime2")]
public DateTime? DisabledOn { get; set; }
[Column(TypeName = "datetime2")]
public DateTime? ToBeDisabledOn { get; set; }
public ScheduleStatus Status { get; set; } // this is an enum
}
public class Shift
{
[Key]
public Guid Id { get; set; }
public string Description { get; set; }
public Schedule Schedule { get; set; }
[ForeignKey("Schedule")]
public Guid? ScheduleId { get; set; }
[Column(TypeName = "datetime2")]
public DateTime? Start { get; set; }
[NotMapped]
public DateTime StartTime
{
get
{
return (Start ?? DateTime.Now);
}
set
{
Start = value;
}
}
public long? TimeSpanDurationInTicks { get; set; }
[NotMapped]
public TimeSpan Duration
{
get
{
return new TimeSpan((TimeSpanDurationInTicks ?? 0));
}
set
{
TimeSpanDurationInTicks = value.Ticks;
}
}
}
I'm explicitly setting all my DateTimes as datetime2. There are some other N:N relationships that I have defined using the Fluent API in the Context class for these models, but all those relationships are between Schedule and other models. Shift only has one potential relationship, and that's with its parent Schedule. And a schedule can have several Shifts, so my understanding is that that's a pretty easy 1:N / N:1 or 0 relationship.
I have obviously missed something somewhere, but I can't quite figure out where. I know that most of this was working up until a few hours ago, and I made some mistakes setting up some other relationships, but I've removed all those, and all the extraneous constraints and values are gone from the table.