2

我正在使用 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 一个 Client,每个 Pet 一个 Veterinarian ,每个 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方法(其中许多我不熟悉)尝试了一些东西,但无济于事。

4

1 回答 1

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 子句中。

于 2013-03-28T16:49:11.597 回答