EF外键约束阻止我编辑表中的记录

时间:2015-03-10 20:50:38

标签: c# entity-framework asp.net-mvc-4

我有点问题。我有一张桌子与一张桌子有三种关系:

 public class ResourceAction
{
    public int Id { get; set; }
    public int ResourceId { get; set; }
    public virtual Resource Resource{ get; set; } //main fk
    public virtual Resource ResourceBeingSent { get; set; } //reference
    public virtual Resource ResponseObject { get; set; } //reference
   ResourceAction()
   {
       ResourceBeingSent = new Resource();
       ResponseObject = new Resource();
   }
   }

现在这两个引用是可选的,我可以通过在删除记录之前删除它们来创建和删除。但是在尝试编辑现有项目时遇到问题。我得到一个约束错误,我通过将其添加到我的数据库上下文中删除了对这两个引用的约束:

       modelBuilder.Entity<ResourceAction>()
   .HasOptional(f => f.ResourceBeingSent)
   .WithMany()
   .WillCascadeOnDelete(false);

      modelBuilder.Entity<ResourceAction>()
    .HasOptional(f => f.ResponseObject)
   .WithMany()
   .WillCascadeOnDelete(false);

我在这里结束了,我试过改变实体的状态进行修改并传入记录,我也试过传入改变的值我仍然得到错误:

    db.Entry(originalResourceAction).CurrentValues.SetValues(vres);
            db.Entry(originalResourceAction).State =         EntityState.Modified;
            db.SaveChanges();

如果有人能指点我为什么可以创建,删除但不能编辑......那就太好了!

我已经包含了堆栈跟踪,基本上它说它受资源表中的外键(这是必需的)约束。 注意用户无法编辑(主)资源外键,在更新过程中不会更改。

构建数据库的EF模式是(它包括为清晰起见而省略的字段)。

      CreateTable(
            "dbo.ResourceActions",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false, maxLength: 100),
                    HttpMethods = c.Int(nullable: false),
                    ResourceId = c.Int(nullable: false),
                    Description = c.String(),
                    ObjectSentIsList = c.Boolean(nullable: false),
                    ObjectResponseIsList = c.Boolean(nullable: false),
                    RespondWithObject = c.Boolean(nullable: false),
                    FriendlyName = c.String(),
                    Deprecated = c.Boolean(nullable: false),
                    ResourceBeingSent_Id = c.Int(),
                    ResponseObject_Id = c.Int(),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.Resources", t => t.ResourceId, cascadeDelete: true)
            .ForeignKey("dbo.Resources", t => t.ResourceBeingSent_Id)
            .ForeignKey("dbo.Resources", t => t.ResponseObject_Id)
            .Index(t => t.ResourceId)
            .Index(t => t.ResourceBeingSent_Id)
            .Index(t => t.ResponseObject_Id);

编辑添加了整个actionResult

注意之前,我只是传入整个对象,这是我最近尝试传递用户可以修改的位。 (仍然得到相同的错误)。

  public ActionResult Edit(ResourceAction resourceAction)
    {
        if (ModelState.IsValid)
        {
            ResourceAction originalResourceAction = db.ResourceActions.Include(c => c.Resource).FirstOrDefault( c => c.Id == resourceAction.Id);

            ViewResourceAction vres = new ViewResourceAction();

            vres.Description = resourceAction.Description;
            vres.FriendlyName = resourceAction.FriendlyName;
            vres.HttpMethods = resourceAction.HttpMethods;
            vres.ObjectResponseIsList = resourceAction.ObjectResponseIsList;
            vres.Name = resourceAction.Name.Replace(" ", "_");
            vres.ObjectSentIsList = resourceAction.ObjectSentIsList;
            vres.RespondWithObject = resourceAction.RespondWithObject;

            if (resourceAction.ResourceBeingSent.Id > 0)
            {
                 vres.ResourceBeingSent =  db.Resources.Find(resourceAction.ResourceBeingSent.Id);
            }
            else
            {
                 vres.ResourceBeingSent =  null;
            }
            if (resourceAction.ResponseObject.Id > 0)
            {
                 vres.ResourceBeingSent =  db.Resources.Find(resourceAction.ResponseObject.Id);
            }
            else
            {
                 vres.ResourceBeingSent =  null;
            }

            db.Entry(originalResourceAction).CurrentValues.SetValues(vres);
            db.Entry(originalResourceAction).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Edit","Resources", new{id = resourceAction.ResourceId});
        }
        ViewBag.ResourceId = new SelectList(db.Resources, "Id", "Name", resourceAction.ResourceId);
        return View(resourceAction);

我的错误跟踪是:

  [SqlException (0x80131904): The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.Resources_dbo._Version_VersionId". The conflict occurred in database "APIEntities-01", table "dbo._Version", column 'Id'.
The statement has been terminated.]
   System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +1767866
   System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +5352418
   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.SqlDataReader.TryConsumeMetaData() +61
   System.Data.SqlClient.SqlDataReader.get_MetaData() +90
   System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +365
   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.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +53
   System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +134
   System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) +41
   System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) +10
   System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<Reader>b__c(DbCommand t, DbCommandInterceptionContext`1 c) +9
   System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch(TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed) +72
   System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext) +356
   System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior) +166
   System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) +10
   System.Data.Entity.Core.Mapping.Update.Internal.DynamicUpdateCommand.Execute(Dictionary`2 identifierValues, List`1 generatedValues) +234
   System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update() +139

[UpdateException: An error occurred while updating the entries. See the inner exception for details.]
   System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update() +319
   System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.<Update>b__2(UpdateTranslator ut) +9
   System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.Update(T noChangesResult, Func`2 updateFunction) +120
   System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.Update() +77
   System.Data.Entity.Core.Objects.ObjectContext.<SaveChangesToStore>b__35() +11
   System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction(Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) +288
   System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions options, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction) +163
   System.Data.Entity.Core.Objects.<>c__DisplayClass2a.<SaveChangesInternal>b__27() +22
   System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Func`1 operation) +164
   System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions options, Boolean executeInExistingTransaction) +222
   System.Data.Entity.Core.Objects.ObjectContext.SaveChanges(SaveOptions options) +7
   System.Data.Entity.Internal.InternalContext.SaveChanges() +114

[DbUpdateException: An error occurred while updating the entries. See the inner exception for details.]
   System.Data.Entity.Internal.InternalContext.SaveChanges() +199
   System.Data.Entity.Internal.LazyInternalContext.SaveChanges() +27
   System.Data.Entity.DbContext.SaveChanges() +20
   RockHopper.Controllers.ResourceActionsController.Edit(ResourceAction resourceAction) in d:\API Manager\RockHopper\Controllers\ResourceActionsController.cs:177
   lambda_method(Closure , ControllerBase , Object[] ) +104
   System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +14
   System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +157
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
   System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +22
   System.Web.Mvc.Async.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult) +29
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +32
   System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d() +50
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +225
   System.Web.Mvc.Async.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34
   System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +26
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +100
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +13
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +39
   System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +12
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +28
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +29
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
   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() +9657896
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

1 个答案:

答案 0 :(得分:1)

毒液在构造函数中:

ResourceAction()
{
   ResourceBeingSent = new Resource();
   ResponseObject = new Resource();
}

您在那里初始化引用属性,这意味着对象将始终以新的Resource开头,并且永远不会加载现有的对象,更不用说修改了。

删除这些初始化。在代码中添加新的Resource以创建第一个新对象。加载(Include)并设置其值,如果你想修改它。

另请参阅:EF codefirst : Should I initialize navigation properties?