Thursday, 15 August 2013

EF - Item Removed From Collection But Not From Database

EF - Item Removed From Collection But Not From Database

Running into this strange issue. I'm using the following code to manage a
collection from a form:
public void UpdateLinks(EventViewModel form)
{
var selectedIds = form.Links.Select(r => r.ResourceTypeID).ToList();
var assignedIds = form.Event.Links.Select(r =>
r.ResourceTypeID).ToList();
foreach (var resource in form.Links)
{
resource.EventID = form.Event.ID;
if (!assignedIds.Contains(resource.ResourceTypeID))
form.Event.Links.Add(resource);
}
foreach (var resource in form.Event.Links.ToList())
{
if (!selectedIds.Contains(resource.ResourceTypeID))
form.Event.Links.Remove(resource);
}
}
The code is successfully updating the Links collection and this is
reflected correctly in the view, however it is not removing the child
record from the database table. That means if I remove a collection item
and then go to add one again that would have the same composite key, the
following exception is thrown:
System.Data.SqlClient.SqlException: Violation of PRIMARY KEY constraint
'PK_dbo.EventResource'. Cannot insert duplicate key in object
'dbo.EventResource'. The duplicate key value is (1, 1). The statement has
been terminated.
Other pertinent info:
EVENT CONTROLLER
[HttpPost]
public ActionResult Edit(EventViewModel form, HttpPostedFileBase[]
eventFiles)
{
if (ModelState.IsValid)
{
eventsService.UpdateEvent(form.Event);
eventsService.UpdateManufacturerTags(form);
eventsService.UpdateFiles(form, eventFiles);
eventsService.UpdateLinks(form);
eventsService.Save();
return RedirectToAction("Details", new { id = form.Event.ID });
}
return View(form);
}
EVENT
public class Event
{
[Key]
public int ID { get; set; }
[Required]
public string Title { get; set; }
[Required]
[DisplayName("Start Time")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString =
"{0:M/d/yyyy h:mm tt}")]
public DateTime? StartTime { get; set; }
[Required]
[DisplayName("End Time")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString =
"{0:M/d/yyyy h:mm tt}")]
public DateTime? EndTime { get; set; }
public string Venue { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
[AllowHtml]
[DataType(DataType.MultilineText)]
public string Description { get; set; }
[DisplayName("Registration Link")]
public string RegistrationUrl { get; set; }
public virtual IList<Manufacturer> Manufacturers { get; set; }
public virtual IList<EventResource> Files { get; set; }
public virtual IList<EventResource> Links { get; set; }
public IEnumerable<EventResource> Resources
{
get { return Files.Concat(Links); }
}
public string LongStartDate
{
get { return StartTime.Value.ToLongDateString(); }
}
public string ShortStartDate
{
get { return StartTime.Value.ToShortDateString(); }
}
public string ShortStartTime
{
get { return StartTime.Value.ToShortTimeString(); }
}
public string LongEndDate
{
get { return EndTime.Value.ToLongDateString(); }
}
public string ShortEndDate
{
get { return EndTime.Value.ToShortDateString(); }
}
public string ShortEndTime
{
get { return EndTime.Value.ToShortTimeString(); }
}
public Event()
{
Manufacturers = new List<Manufacturer>();
Files = new List<EventResource>();
Links = new List<EventResource>();
}
}
EVENT RESOURCE
public class EventResource
{
[Key, Column(Order = 0)]
public int EventID { get; set; }
[Key, Column(Order = 1)]
public int ResourceTypeID { get; set; }
public string Path { get; set; }
public virtual Event Event { get; set; }
public virtual ResourceType Type { get; set; }
}
RESOURCE TYPE
public class ResourceType
{
[Key]
public int ID { get; set; }
[Required]
public string Name { get; set; }
}
PERTINENT LINES FROM CONTEXT CLASS
public DbSet<Event> Events { get; set; }
public DbSet<EventResource> EventResources { get; set; }
public DbSet<ResourceType> ResourceTypes { get; set; }
STACK TRACE
[SqlException (0x80131904): Violation of PRIMARY KEY constraint
'PK_dbo.EventResource'. Cannot insert duplicate key in object
'dbo.EventResource'. The duplicate key value is (1, 1). The statement has
been terminated.]
System.Data.SqlClient.SqlConnection.OnError(SqlException exception,
Boolean breakConnection, Action`1 wrapCloseInAction) +1788622
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException
exception, Boolean breakConnection, Action`1 wrapCloseInAction)
+5377458
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject
stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) +244
System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand
cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet
bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) +1691
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,
RunBehavior runBehavior, String resetOptionsString) +269
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async,
Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds) +1406
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method,
TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean
asyncWrite) +177
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1
completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean
asyncWrite) +205 System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
+160
System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator
translator, EntityConnection connection, Dictionary`2 identifierValues,
List`1 generatedValues) +535
System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager
stateManager, IEntityAdapter adapter) +262
[UpdateException: An error occurred while updating the entries. See the
inner exception for details.]
System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager
stateManager, IEntityAdapter adapter) +444
System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager
entityCache) +146
System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
+571 System.Data.Entity.Internal.InternalContext.SaveChanges() +114
[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.Entity.Internal.InternalContext.SaveChanges() +200
System.Data.Entity.Internal.LazyInternalContext.SaveChanges() +33
System.Data.Entity.DbContext.SaveChanges() +20
PennLighting.DAL.EventsService.Save() in
c:\Users\Dom\Documents\GitHub\PennLighting\PennLighting\DAL\Services\EventsService.cs:164
PennLighting.Controllers.EventsController.Edit(EventViewModel form,
HttpPostedFileBase[] eventFiles) in
c:\Users\Dom\Documents\GitHub\PennLighting\PennLighting\Controllers\EventsController.cs:146
lambda_method(Closure , ControllerBase , Object[] ) +125
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller,
Object[] parameters) +14
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext
controllerContext, IDictionary`2 parameters) +182
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext
controllerContext, ActionDescriptor actionDescriptor, IDictionary`2
parameters) +27
System.Web.Mvc.Async.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41()
+28
System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult
_) +10 System.Web.Mvc.Async.WrappedAsyncResult`1.End() +50
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult
asyncResult) +32
System.Web.Mvc.Async.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33()
+58
System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
+225
System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__36(IAsyncResult
asyncResult) +10 System.Web.Mvc.Async.WrappedAsyncResult`1.End()
+50
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult
asyncResult) +34
System.Web.Mvc.Async.<>c__DisplayClass2a.<BeginInvokeAction>b__20()
+24
System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult
asyncResult) +99 System.Web.Mvc.Async.WrappedAsyncResult`1.End()
+50
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult
asyncResult) +27
System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult
asyncResult) +14
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult
ar) +23 System.Web.Mvc.Async.WrappedAsyncResult`1.End() +55
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +39
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult
ar) +23 System.Web.Mvc.Async.WrappedAsyncResult`1.End() +55
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +29
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult
asyncResult) +10
System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult
asyncResult) +25
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult
ar) +23 System.Web.Mvc.Async.WrappedAsyncResult`1.End() +55
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
+31
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult
result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
+9657028 System.Web.HttpApplication.ExecuteStep(IExecutionStep step,
Boolean& completedSynchronously) +155
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET
Version:4.0.30319.18213

No comments:

Post a Comment