【问题标题】:EF, ASP.NET Web API, and JSON.NET - Limiting Hierarchy ReturnedEF、ASP.NET Web API 和 JSON.NET - 返回的限制层次结构
【发布时间】:2013-03-28 14:29:29
【问题描述】:

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

客户 => 一对多 => 宠物 => 一对一 => 兽医

并且,颠倒层次结构:

兽医 => 一对多 => 宠物 => 一对一 => 客户

在我的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 包含 Pets,每个 Pet 一个客户,每个 Pet 一个兽医并且对于每个 Veterinarian,一个 Pets 集合

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

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 方法(其中很多我不熟悉)尝试了一些东西,但无济于事。

【问题讨论】:

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


    【解决方案1】:

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

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

    此外,OData 协议已经通过 $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 子句中。

    【讨论】:

    • 是的,但目前不支持 OData $expand 选项(Returning child elements in ASP.NET WebAPI OData),这就是我尝试不同方法的原因。有时我可能想要一个特定兽医护理下的宠物列表 - 只是当我要求将宠物列表作为图表的根时。而且我不想为不同的“根对象”情况创建不同的 DTO..
    • 您可以在选择查询中进行映射。我已经用示例更新了答案。
    • 另外,我们刚刚开始在 Web API OData 中支持 $select 和 $expand。它应该很快就会在我们的夜间构建中亮起。
    猜你喜欢
    • 2013-11-22
    • 1970-01-01
    • 1970-01-01
    • 2016-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多