实体框架在回复之前等待完整的对象加载

时间:2019-07-17 09:52:12

标签: entity-framework lazy-loading

我正在尝试使用EntityFramework从数据库中回复带有序列化对象的http请求。 为此,请执行以下操作:

message m = dbContext.messages.FirstOrDefault(e => e.idmessage == id);
return Request.CreateResponse(HttpStatusCode.OK, m);

但是 message 模型具有这样的属性:

public virtual fichero fichero { get; set; }

如果将延迟加载设置为 false ,则返回的 fichero 属性为null,一切正常。如果延迟加载设置为 true ,我会收到一个类似此延迟加载true的异常:

Exception stack trace

我猜可能是因为我试图在从数据库完全加载序列化对象之前返回它,但是我对此并不满意,所以我不确定。

我如何才能等到它满载后再返回?是否有任何 subscribe 或类似的名称?谢谢。

1 个答案:

答案 0 :(得分:2)

  

等到完全加载

延迟加载并不意味着将导航属性(例如fichero fichero)加载到后台。这意味着在请求属性时就会加载它们,例如,当您编写如下代码时:

var message = dbContext.Messages.FirstOrDefault(some query); // one database hit
var fichero = message.Fichero; // another database hit

一旦您访问message.Fichero getter,动态生成的代理类将执行另一个数据库查询以检索Fichero

  

可能是因为我尝试返回序列化的对象

完全正确。 MVC(或Web API或其他任何东西)将使用反射来序列化对象,并且这样做会访问属性的getter,发出另一个数据库查询-但是dbContext已被处置,因此无法用于任何其他查询。

可能的解决方案:

  • 明确加载要从API(.Include(m => m.Fichero)返回的所有内容
  • 禁用延迟加载,因此仅返回您的“ root”实体
  • 将您的实体映射到viewmodel / DTO,无论如何这都是推荐的方法

后者看起来像这样:

public class MessageViewModel
{
    public string Message { get; set; }
    public string FicheroFoo { get; set; }

    // ...
}

var message = dbContext.Messages.FirstOrDefault(some query);

var model = new MessageViewModel
{
    Message = message.Message,
    FicheroFoo = message.Fichero.Foo,
    // ...
};

return Request.CreateResponse(HttpStatusCode.OK, model);