EF:在DbContext上禁用“AutoDetectChangesEnabled”和“ProxyCreateEnabl
本文关键字:AutoDetectChangesEnabled ProxyCreateEnabl DbContext EF | 更新日期: 2023-09-27 18:09:05
-
知道
Foo.Id
和Bar.Id
如何在不从DB加载实体的情况下创建它们的关系。class Foo { public int Id { get; set; } public Lst<Bar> Bars { get; set; } } class Bar { public int Id { get; set; } public Lst<Foo> Foos { get; set; } }
此外,此配置在
DbContext
构造函数中被禁用:Configuration.AutoDetectChangesEnabled = false; Configuration.ProxyCreationEnabled = false; Configuration.LazyLoadingEnabled = false;
-
如何才能消除这种关系?
示例:
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<Bar>() };
var bar = new Bar { Id = 3, Foos = new List<Foo>() };
// 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<T1, T2>(
IObjectContextAdapter ctx,
T1 a,
T2 b,
Expression<Func<T1, object>> 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<Bar>()};
var bar = new Bar { Id = 3, Foos = new List<Foo>() };
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();
}
如果我理解正确,您希望在不查找Foo实体的情况下将Bar对象添加到现有的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> { 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
解决方案看起来更自然(奇怪的是,这样的功能没有通过DbContext
公开(,所以我个人的投票就在那里。