0

null に設定しようとしているオプションの外部キーがあります。私が何を試しても、SaveChanges() で、update ステートメントは外部キーを null ではなく以前の値に設定します。

簡略化された子クラス:

public class Child
{
    [Key, Column(Order = 0), ScaffoldColumn(false)]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [ForeignKey("Parent")]
    public int? ParentId { get; set; }

    public virtual Parent Parent { get; set; }
}

簡略化された親クラス:

public class Parent
{
    [Key, Column(Order = 0), ScaffoldColumn(false)]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public virtual ICollection<Child> Children { get; set; }
}

私が試したこと:

  1. Child オブジェクトをロードし、ParentId を null に設定し、Parent を null に設定します。
  2. Child オブジェクトをロードし、ParentId を null に設定して、エンティティの状態を強制的に変更します
  3. Parent オブジェクトを含む Child オブジェクトをロードし、値を null に設定して、エンティティの状態を強制的に変更します。
  4. 親オブジェクトを読み込み、次に子オブジェクトを読み込み、親オブジェクトから .Remove(child) を読み込みます
  5. Parent オブジェクトをロードし、次に Child オブジェクトと .Remove(child) を Parent からロードし、Child.ParentId を null に、Child.Parent を null に設定します。

現在私は持っています:

public void RemoveChildFromParent(int childId, int parentId)
{
    Parent parent = _context.Parents.Include(x => x.Children).FirstOrDefault(u => u.Id == parentId);
    Child child = parent.Children.SingleOrDefault(u => u.Id == childId);
    parent.Children.Remove(child);
    child.ParentId = null;
    child.Parent = null;
    child.StateOfEntity = StateOfEntity.Modified;

    _context.ApplyStateChanges();
    _context.SaveChanges();
}

変更を保存すると、SQL Update ステートメントはまだ子オブジェクトの ParentId を古い値に設定し、次のエラーが発生します。

System.InvalidOperationException was unhandled by user code
  HResult=-2146233079
  Message=The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: A referential integrity constraint violation occurred: The property values that define the referential constraints are not consistent between principal and dependent objects in the relationship.
  Source=System.Data.Entity
  StackTrace:
       at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
       at System.Data.Entity.Internal.InternalContext.SaveChanges()
       at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
       at System.Data.Entity.DbContext.SaveChanges()
       at Insight.DataLayer.InsightContext.SaveChanges()
       at Insight.DataLayer.ChildRepository.RemoveChildFromParent(Int32 childId, Int32 parentId)
       at Insight.BusinessLayer.ParentManager.RemoveChild(Int32 id, Int32 parentId)
       at Insight.PresentationLayer.Controllers.ParentController.RemoveChild(Int32 id, Int32 parentId)
       at lambda_method(Closure , ControllerBase , Object[] )
       at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
       at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33()
       at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
  InnerException: 

また、問題があるかどうかはわかりませんが、LazyLoadingEnabled = false と AutoDetectChangesEnabled = false があります。

4

2 に答える 2

1

これに対する「エレガントな」解決策があるかどうかはわかりませんが (おそらくテーブル構造を変更しますか?)、この小さな問題により多くの時間を費やす代わりにDbContext.Database.ExecuteSqlCommand()、update ステートメントを使用して手動で記述することにしました。

確かに Entity Framework の方法論の回避策のように感じますが、このシナリオに限定されており、実行に時間がかからず、意図したとおりに機能します。

于 2013-10-01T14:14:55.803 に答える