背景:我正在使用EF6和数据库优先。
我遇到了一个让我感到困惑的场景。创建新对象,用新对象填充“导航属性”并调用SaveChanges之后,将重置导航属性。在SaveChanges调用之后,引用导航属性的第一行代码将最终从数据库中重新获取数据。这是预期的行为,有人可以解释为什么这样做吗?这是我的方案的示例代码块:
using (DbContext context = new DbContext) {
Foo foo = context.Foos.Create();
context.Foos.Add(foo);
...
Bar bar = context.Bars.Create();
context.Bars.Add(bar);
...
FooBar foobar = context.FooBars.Create();
context.FooBars.Add(foobar)
foobar.Foo = foo;
foobar.Bar = bar;
//foo.FooBars is already populated, so 1 is returned and no database query is executed.
int count = foo.FooBars.Count;
context.SaveChanges();
//This causes a new query against the database - Why?
count = foo.FooBars.Count;
}
我不能说100%,但是我怀疑这种行为是专门做出的。
至于为什么会这样,问题的根源在于该DbCollectionEntry.IsLoaded
属性是false
直到导航属性隐式延迟加载或使用Load
method显式加载。
同样,当实体处于“已添加”状态时,似乎也抑制了延迟加载,这就是为什么第一次调用不会触发重新加载的原因。但是,一旦调用SaveChanges
,实体状态将变为未修改状态,尽管集合并没有真正设置为“ null”或未清除,但是下一次访问集合属性的尝试将触发延迟重新加载。
// ...
Console.WriteLine(context.Entry(foo).Collection(e => e.FooBars).IsLoaded); // false
//foo.FooBars is already populated, so 1 is returned and no database query is executed.
int count = foo.FooBars.Count;
// Cache the collection property into a variable
var foo_FooBars = foo.FooBars;
context.SaveChanges();
Console.WriteLine(context.Entry(foo).State); // Unchanged!
Console.WriteLine(context.Entry(foo).Collection(e => e.FooBars).IsLoaded); // false
// The collection is still there, this does not trigger database query
count = foo_FooBars.Count;
// This causes a new query against the database
count = foo.FooBars.Count;
如果要避免重新加载,解决方法是将IsLoaded
属性显式设置为true
。
// ...
context.SaveChanges();
context.Entry(foo).Collection(e => e.FooBars).IsLoaded = true;
context.Entry(bar).Collection(e => e.FooBars).IsLoaded = true;
// No new query against the database :)
count = foo.FooBars.Count;
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句