2014-01-21 189 views
2

比方说,我有EF模型两个项目可能被投射到下面的DTO:Linq to entity。嵌套投影

public class AddressDto 
{ 
    public int Id { get; set; } 
    public string Address { get; set; } 

    public static Expression<Func<Address, AddressDto>> Address2AddressDto() 
    { 
     return x => new AddressDto() { 
      Id = x.Id, 
      FullName = x.AddressLine 
     }; 
    } 
} 

public class ClientDto 
{ 
    public int Id { get; set; } 
    public int FullName { get; set; } 
    public AddressDto Address { get; set; } 
} 

我怎样才能创建ClientDto重用从AddressDto投影到Client转换嵌套Address投影?基本上,我想是这样的:

public static Expression<Func<Client, ClientDto>> Client2ClientDto() 
{ 
    return x => new ClientDto() { 
     Id = x.Id, 
     FullName = x.FullName, 
     Address 
      = <Apply projection AddressDto.Address2AddressDto to object x.Address> 
    }; 
} 

我知道,我可以这样做:

public static Expression<Func<Client, ClientDto>> Client2ClientDto() 
{ 
    return x => new ClientDto() { 
     Id = x.Id, 
     FullName = x.FullName, 
     Address = new AddressDto() { 
      Id = x.Id, 
      FullName = x.AddressLine 
     } 
    }; 
} 

但我想管理AddressDto投影在一个地方,而不是每次使用这个投影的地方(实对象要复杂得多,代码重复会导致长期的问题)。

在我的来电显示的代码我想要做这样的事情

dbRepo.Clients.Select(Client2ClientDto()) 

我所有的电流试图结束了异常:

的LINQ表达式节点类型“调用”在LINQ不支持到实体。

回答

1

你最好打赌,如果你想遵循这种模式,可能会使用LINQKit。它会告诉你这样做:

public static Expression<Func<Client, ClientDto>> Client2ClientDto() 
{ 
    var addr = AddressDto.Address2AddressDto() 
    return x => new ClientDto() { 
     Id = x.Id, 
     FullName = x.FullName, 
     Address = addr.Invoke(x) 
    }; 
} 

但你必须这样称呼它:

dbRepo.Clients.AsExpandable().Select(Client2ClientDto()) 
0

除非你已经拥有了所有预测的建成,我会考虑AutoMapper。你可以很容易地创建一个静态映射(它会像属性定义默认的地图,但你可以添加其他的映射也一样),你可以在你的静态映射定义投影:

Mapper.CreateMap<Address, AddressDto>(); 
Mapper.CreateMap<Client, ClientDto>(); 

当AutpMapper去转换Client对象,它会看到有一个地图AddressAddressDto定义并将使用该。

+1

Automapper不适用于LINQ to Entities预测。 – StriplingWarrior

+0

不,但如果您先将物体水合,_then_贴图可以起作用。 –

+1

那么,如果我需要首先实现它,那么我可以使用像AddressDto.Address2AddressDto()这样的东西来实现同样的功能。编译()(x.Address)就是问题所在的行。我只是希望在那个时候还有一种方法还没有实现数据。 – AlexanderM