[英]EF: Create/Remove relation from Many-to-Many relations when `AutoDetectChangesEnabled` and `ProxyCreationEnabled` are disabled on DbContext
了解Foo.Id
和Bar.Id
如何在不从数据库加载实体的情况下创建它们的关系。
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();
}
如果我理解正确,则希望将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> { 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()
如果我们明确地在末尾调用DbContext.ChangeTracker.DetectChanges()
),我最初的解决方案是将第二个实体附加到“原始”集合上,然后模拟修改也是DbContext.ChangeTracker.DetectChanges()
),但我应该承认ObjectContext
您发现的解决方案看起来更加自然(奇怪的是,该功能尚未通过DbContext
),因此我个人投票赞成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.