C# MVC 代码首先不返回所有字段



我是MVC的新手,我正在使用Web API 2的代码优先方法。这是我的模型:

儿童模特.cs

[DataContract(IsReference = true)]
public class ChildModel
{
//other fields definition here
//relationship definition
[DataMember]
public int ParentModelID {get; set;}
[DataMember]
public virtual ParentModel ParentModel {get; set;}
}

那么这是我的控制器操作:

public IEnumerable<ChildModel> Get()
{
return db.ChildModels.ToList();
}

所以数据库生成没有问题。它创建表。我可以保存和编辑。只有一个问题,即"获取控制器"操作。当我从前端访问它时,返回的 JSON 如下所示:

[
{$id: 1, Field1: "", Field2: ""},
{$ref: 3}
...
{$id: 10, Field1: "", Field2: ""},
{$ref: 12}
]

它就这样交替进行。第一个 JSON 已完成,然后下一个只是一个$ref字段。可能是什么原因造成的?我还注意到,当我在子模型中删除父模型的导航属性时,除了父模型没有预先加载到子模型的 JSON 中之外,一切似乎都很好。

希望有人能帮助我。

谢谢!

首先,您并不急于在任何地方加载父模型,因为查询中没有Include。当您尝试将数据库对象直接返回到 API 时,该 API 将尝试将它们序列化为 Json 或 XML,从而对您的对象进行全面扫描。

要解决您的问题,您可以这样做:

public IEnumerable<ChildModel> Get()
{
db.Configuration.LazyLoadingEnabled = false;
try
{
return db.ChildModels.Include("ParentModel").ToList();
}
finally
{
db.Configuration.LazyLoadingEnabled = true;
}
}

我负责禁用和重新启用延迟加载,因为您似乎正在与控制器构造函数中的依赖项注入共享db


序列化程序通常在没有IsReference = true的情况下执行的操作是:

  • 序列化子 ID 1
  • 序列化子ParentModel(访问它会触发延迟加载)
  • 序列化父模型(延迟加载)
  • 序列化父模型的ChildModel集合
  • 最终将找到子项 ID 1
  • 再次序列化子 ID 1

无限循环。通过应用IsReference = true可以避免这种情况,因为一旦序列化程序检测到以前序列化的对象,它就不会再次序列化它,而是填充如下内容:

$ref: 3

。表示该对象引用 Id 3 中的另一个对象。

考虑到 ID 为 3 的孩子与 ID 1 具有相同的父级,那么就会发生这种情况:

  • 序列化子 ID 1
  • 序列化子ParentModel(访问它会触发延迟加载)
  • 序列化父模型(延迟加载)
  • 序列化父模型的ChildModel集合(触发延迟加载)
  • ChildModel 的集合是延迟加载的(包含两个子项,ID 1 和 3)
  • ref添加到子项 1(以前已序列化)
  • 序列化子 ID 3
  • 完成的父模型子序列化
  • 完成的父模型序列化
  • 完成的子级 ID 1 序列化

  • ref添加到子项 3(以前已序列化)

  • 序列化子 ID 10
  • 。继续序列化其他对象

这就是为什么我禁用了延迟加载并使用Include()加载父模型。

现在,发生这种情况只是因为您尝试将数据库对象直接返回到 API。这就是为什么人们通常使用投影来返回DTO/ViewModel对象。

如果我没记错的话,EF 使用延迟加载。 在调用列表之前,请尝试将.Include(c => c.ParentModel)添加到控制器操作中。

这应该告诉 EF 解析引用并提取完整的对象。

最新更新