如何让Entity Framework与我的分离对象图一起工作?

时间:2013-03-01 19:08:19

标签: c# asp.net-mvc-4 entity-framework-5

在我的应用程序中,我们为每个HTTP请求获取了DbContext的新实例。在正常的工作流程中,我们创建一个实体并开始填充其部分导航属性:

// Request 1
var foo = new Foo();
SessionStore.Add("Foo", foo);

// Request 2
var bar = BarDataService.GetBar(barId);

var foo = SessionStore.Get<Foo>("Foo");
foo.Bars.Add(bar);

// Request 3
var baz = BazDataService.GetBaz(bazId);

var foo = SessionStore.Get<Foo>("Foo");
foo.Baz = baz;

完全填充对象图后,我们将实体插入数据库:

var foo = SessionStore.Get<Foo>("Foo");
FooDataService.Add(foo); // BOOM!

Add通常只是将实体添加到DbSet,然后调用保存更改:

Set.Add(entity);
Context.SaveChanges();

显然,由于foo对象包含多个代理对象,每个代理对象都附加到不同的DbContexts,因此失败。我们决定的解决方案是分离我们收到的对象:

// Request 2 (modified)
var bar = BarDataService.GetBar(barId);
BarDataService.Detach(bar);
foo.Bars.Add(bar);

// Similar code for Request 3

var foo = SessionStore.Get<Foo>("Foo");
FooDataService.Add(foo); // Works

这可以之外,因为它现在会创建BarBaz对象的新实例。

我在这里做错了什么?

1 个答案:

答案 0 :(得分:1)

在将Bar添加到上下文之前,您必须附加相关的Bazfoo对象。这会将实体置于状态Unchanged,EF将仅创建foo与相关实体之间的关系,而不是在数据库中创建新的BarBaz对象:

foreach (var bar in foo.Bars)
    context.Bars.Attach(bar);
context.Bazs.Attach(foo.Baz);
context.Foos.Add(foo);
context.SaveChanges();