知道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();
}
如何在不更改配置的情况下在此处定义关系。
提前谢谢。
答案 0 :(得分:2)
好的,找到了解决方案,这里是帮助方法:
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();
}
答案 1 :(得分:1)
如果我理解正确,你想要将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();
}
答案 2 :(得分:1)
你问的是可能的。以下是步骤:
(1)首先创建两个仅指定PK的实体实例,并将其中一个(例如foo
)附加到上下文中:
var foo = new Foo { Id = fooId };
var bar = new Bar { Id = barId };
ctx.Foos.Attach(foo);
(2)将第二个实体集合设置为包含第一个实体的新列表(即&#34;创建&#34;关系):
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();
后,将在联结表中添加或删除关系。
更新:虽然上述工作(实际上我的原始解决方案是将第二个实体附加&#34;原始&#34;集合然后模拟修改也可以在我们最后调用{明确地{1}},我应该承认,您找到的DbContext.ChangeTracker.DetectChanges()
解决方案看起来更自然(这种功能尚未通过ObjectContext
公开,这很奇怪),所以我的个人投票去那里。