0

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

    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:违反主键约束“PK_dbo.EventResource”。无法在对象“dbo.EventResource”中插入重复键。重复键值为 (1, 1)。该语句已终止。

其他相关信息:

事件控制器

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

事件

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

堆栈跟踪

[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
4

2 回答 2

0

改变了

form.Event.Links.Remove(resource);

context.EventResources.Remove(resource);

现在它可以工作了……奇怪的是,我不必在网站的任何其他部分以相同的方式管理集合,但就这样吧。

于 2013-08-15T20:32:01.663 回答
-1

每当您从集合中删除某些内容时,您都应该调用form.SaveChanges(). 确保在调用 SaveChanges() 时必须先删除实体,然后再插入内容。

于 2013-08-15T20:17:00.883 回答