EF:在DbContext上禁用“AutoDetectChangesEnabled”和“ProxyCreationEnabled”时,从多对多关系创建/删除关系

  1. 知道Foo.IdBar.Id如何在不加载DB实体的情况下创建关系。

     class Foo { public int Id { get; set; } public Lst Bars { get; set; } } class Bar { public int Id { get; set; } public Lst Foos { get; set; } } 

    此配置也在DbContext构造函数中禁用:

     Configuration.AutoDetectChangesEnabled = false; Configuration.ProxyCreationEnabled = false; Configuration.LazyLoadingEnabled = false; 
  2. 以及如何删除这种关系?


例:

 using (var ctx = new DbCtx()) { ctx.Configuration.LazyLoadingEnabled = false; ctx.Configuration.ProxyCreationEnabled = false; ctx.Configuration.AutoDetectChangesEnabled = false; ctx.Database.Log += Console.WriteLine; var foo = new Foo {Id = 1, Bars = new List() }; var bar = new Bar { Id = 3, Foos = new List() }; // This approach wont work, as AutoDetectChanges are disabled ctx.Foos.Attach(foo); ctx.Bars.Attach(bar); foo.Bars.Add(bar); ctx.SaveChanges(); } 

如何在不更改配置的情况下在此处定义关系。

先感谢您。

好的,找到了解决方案,这里是帮助方法:

 static void ChangeRelationship( IObjectContextAdapter ctx, T1 a, T2 b, Expression> getNavigationProperty, EntityState state) where T1: class { ctx .ObjectContext .ObjectStateManager .ChangeRelationshipState( a, b, getNavigationProperty, state ); } 

并在我的例子中使用它来自问题:

 using (var ctx = new DbCtx()) { ctx.Configuration.LazyLoadingEnabled = false; ctx.Configuration.ProxyCreationEnabled = false; ctx.Configuration.AutoDetectChangesEnabled = false; ctx.Database.Log += Console.WriteLine; var foo = new Foo {Id = 1, Bars = new List()}; var bar = new Bar { Id = 3, Foos = new List() }; ctx.Entry(foo).State = EntityState.Unchanged; ctx.Entry(bar).State = EntityState.Unchanged; // create ChangeRelationship(ctx, foo, bar, x => x.Bars, EntityState.Added); ctx.SaveChanges(); // remove ChangeRelationship(ctx, foo, bar, x => x.Bars, EntityState.Deleted); ctx.SaveChanges(); } 

如果我理解正确,您希望将Bar对象添加到现有的Foo实体,而无需查找Foo实体。

比方说,你有Foo(id = 1)已经存在。 想要添加新的Bar(id = 100)实体。

 using (var context = new Context()) { var bar = new Bar() { Id = 100 }; var foo = new Foo() { Id = 1 }; // Only ID is required context.Foos.Attach(foo); bar.Foos.Add(foo); context.Bars.Add(bar); context.SaveChanges(); } 

你问的是可能的。 以下是步骤:

(1)首先创建两个仅指定PK的实体实例,并将其中一个(例如foo )附加到上下文中:

 var foo = new Foo { Id = fooId }; var bar = new Bar { Id = barId }; ctx.Foos.Attach(foo); 

(2)将第二个实体集合设置为包含第一个实体的新列表(即“创建”关系):

 bar.Foos = new List { foo }; 

(3)将第二个实体标记如下:

(A)增加关系:

 ctx.Entry(bar).State = EntityState.Added; 

(B)删除关系:

 ctx.Entry(bar).State = EntityState.Deleted; 

(4)将第二个实体标记为未更改:

 ctx.Entry(bar).State = EntityState.Unchanged; 

就是这样!

一旦你调用ctx.SaveChanges(); ,将在联结表中添加或删除关系。

更新:虽然上面的工作(实际上我的原始解决方案附加第二个实体与“原始”集合,然后模拟修改也有效,如果我们最后调用DbContext.ChangeTracker.DetectChanges()显式),我应该承认ObjectContext你发现的解决方案看起来更自然(奇怪的是,这种function还没有通过DbContext ),所以我的个人投票就在那里。