c# - EF、ASP.NET Web API 和 JSON.NET - 返回限制层次结构

标签 c# entity-framework asp.net-web-api json.net

我正在使用 EF 5 和 ASP.NET Web API 从我的 Controller 返回 JSON。我的例子是宠物服务。对于这个问题,实体是 ClientPetVeterinarian。关系是:

Client => one-to-many => Pet => one-to-one => Veterinarian

并且,颠倒层次结构:

Veterinarian => one-to-many => Pet => one-to-one => Client

在我的 PetsController 中,GetPets 操作如下所示:

var pets= db.Pets
    .Where(p => p.IsActive == true)
    .Include(p => p.Client)
    .Include(p => p.Veterinarian);

return Mapper.Map<IEnumerable<Pet>, IEnumerable<PetDTO>>(pets); // Using Automapper to map to a DTO

生成的 JSON 包含宠物,每个宠物对应一个客户,每个宠物对应一个 vert 并且每个 vert 对应一个宠物集合

我理解为什么宠物集合会显示在 JSON 中,但它与 Controller 操作中的宠物列表不相关(至少现在不相关)。我正在寻找一种优雅的方式来删除宠物的集合。现在我正在使用感觉像是 hack 的东西:

var pets= db.Pets
    .Where(p => p.IsActive == true)
    .Include(p => p.Client)
    .Include(p => p.Veterinarian);

foreach (Pet pet in pets) {
    pet.Veterinarian.Pets = null; // Remove the Pets collection before serializing
}

return Mapper.Map<IEnumerable<Pet>, IEnumerable<PetDTO>>(pets); // Using Automapper to map 

我已经用序列化程序和一些 IQuerable 方法(其中很多我不熟悉)尝试了一些事情,但无济于事。

最佳答案

您可以禁用延迟加载来修剪图形。但这仍然不能始终解决问题。如果你有双向关系(比如 pet <=> Veterinarian),使用 Include 获取关系的一侧也会自动构建另一侧。因此,在您查询之后,即使您没有在 Include 中明确询问,pet.Veterinarian.Pets 也不会为空。

使用 DTO 是我能想到的最佳方式。您可以完全控制对象图。

此外,OData 协议(protocol)已经通过 $select 和 $expand 定义了这种机制,并将控制权交给客户端以指定它需要的对象图的深度和广度。例如,对于您的场景,OData url 看起来像 ~/Pets?$expand=Client,Veterinarian。您是否考虑过 OData 来满足您的需求?

如果您不想每次都创建 DTO,您可以使用匿名对象即时创建。例如,对于您的场景,您可以这样做,

db.Pets.Select(p => new 
{ 
    Id = p.ID, 

    .... other pet properties you want, 

    Veterinarian = new 
    { 
        ID = p.Veterinarian.ID 
        ... other veterinarian properties you want
    },
    Client = 
    {
        ... client properties you need.
    }

});

不过,这只是将映射移动到 select 子句中。

关于c# - EF、ASP.NET Web API 和 JSON.NET - 返回限制层次结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15684484/

相关文章:

c# - 对于 EF 上下文,实例变量和局部变量哪个更好?

json - 自动测试 Web API REST 服务

c# - 在 MySQL、NHibernate 和 C# 中使用自动增量

c# - Unity 2D 中翻转 Sprite 的问题

c# - 如何减少 Asp.Net Identity 中的密码重置 token 长度?

c# - 在控件模板中设置属性

sql-server - 如何使用新生成的数据库添加新的代码优先迁移?

c# - 实现 IAuthenticationFilter、工作单元和依赖注入(inject)

c# - 如何从 WebAPI 中的 HttpResponse 对象获取错误消息?

c# - 单元测试中的模型状态验证