EF - 项目从集合中删除但不从数据库中删除

时间:2013-08-15 20:11:01

标签: asp.net-mvc entity-framework

遇到这个奇怪的问题。我正在使用以下代码来管理表单中的集合:

    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);
        }
    }

代码正在成功更新Links集合,这在视图中正确反映,但它不会从数据库表中删除子记录。这意味着如果我删除一个集合项,然后再添加一个具有相同组合键的集合项,则抛出以下异常:

  

System.Data.SqlClient.SqlException:违反PRIMARY KEY   约束'PK_dbo.EventResource'。无法插入重复键   对象'dbo.EventResource'。重复键值为(1,1)。该   声明已被终止。

其他相关信息:

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>();
    }
}

活动资源

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; }
}

资源类型

public class ResourceType
{   
    [Key]
    public int ID { get; set; }

    [Required]
    public string Name { get; set; }
}

来自上下文类别的内容

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

2 个答案:

答案 0 :(得分:0)

更改

form.Event.Links.Remove(resource);

context.EventResources.Remove(resource);

现在它起作用了......奇怪的是,我不必在网站的任何其他部分执行此操作,我以相同的方式管理集合,但就是这样。

答案 1 :(得分:-1)

每当您从收藏中删除某些内容时,都应致电form.SaveChanges()。确保在调用SaveChanges()时,必须先删除实体,然后才能插入内容。