正确的方法来检查上下文处理后是否加载了贪婪的实体?

时间:2017-09-08 15:36:45

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

可能不相关,但我正在使用:

  

.NET MVC 5.2.3 w / Razor 3.2.3,Entity Framework 6.1.3 Code First,Visual Studio 2015。

好吧,在我的控制器方法中,我实际上是因为简洁而愚蠢:

using( var context = new MyContext() ) {
    var person = context.Persons.Include( x => x.PostalCode ).FirstOrDefault();
    return View(person);
}

现在,Zip数据输入属性最初不是外键...只是用户输入的5位数字符串。然而,现在,它本质上是一个外键,以便我们可以获得邮政编码信息。

public string Zip { get; set; }
[ForeignKey("Zip")]
public virtual PostalCode PostalCode { get; set; }

不理想的结构......我知道......

但无论如何,如果用户拥有我们系统识别的邮政编码,那么一切都很好,一切都在加载。但是,如果用户具有未知或无效的邮政编码,例如00000,EF看到非空的外键,这会导致以下问题:

在我的视图文件中(所以在我处理了我的上下文之后),我检查了我们贪婪的实体的属性:

@if( person.PostalCode != null && person.PostalCode.IsInServiceArea ) {
    <div>Service Area HTML</div>
}

不幸的是,由于EF覆盖了我的虚拟属性,即使没有PostalCode,它也不是NULL。因此,当此代码运行时,它会抛出一个异常,即ObjectContext已经被处理掉,这意味着EF正在尝试延迟加载一个实体,即使它已经尝试贪婪地加载并且应该知道它不存在{{1} }

明显的解决方案(请不要回答这些问题):

  • 在条目上验证邮政编码,只允许我们知道的邮政编码,并将未知的邮政编码设置为NULL(我喜欢这个,但我没时间重新设计)
  • 在打开上下文时获取IsInServiceArea的值,并将其直接放在我的View Model中,以便在处理上下文之前设置值。 (这实际上是我打算做的,所以我不需要这个答案):

问题

  

在Entity Framework中,Code-First,检查的正确方法是什么   看看是否加载了贪婪的LEFT OUTER JOIN'd实体   上下文被处理掉了?

根据我发现的答案(例如下面的内容),我认为如果没有上下文打开,这可能是不可能的......但是我想不管怎么说:

2 个答案:

答案 0 :(得分:1)

因此,回头看我的评论,你可以完全禁用延迟加载和代理创建。只需找到dbcontext类型的构造函数,然后将这两行添加到方法中:

this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;

通过这种方式,您可以全局禁用它(无论何时创建上下文,运行ctor,都会应用这些设置。)

或者,如果您在上下文对象创建后在上下文对象上设置了这些实例,则可以为一个实例禁用它。

答案 1 :(得分:0)

或者,让您的上下文在整个请求中生效,以便在视图上实现延迟加载。

<强> Startup.Auth.cs

public void ConfigureAuth(IAppBuilder app)
{
    MyContext Create() { return new MyContext(); }
    app.CreatePerOwinContext(Create);
    ...
}

<强> MyController.cs

var context = HttpContext.GetOwinContext().Get<MyContext>();
var person = context.Persons.Include( x => x.PostalCode ).FirstOrDefault();
return View(person);