如何使用AutoMapper和OData扩展子级别的子级别?

时间:2017-02-22 14:42:30

标签: c# asp.net entity-framework-6 odata automapper

我目前正在开发asp.net中的Web服务项目。我尝试在我的函数中包含子元素来检索数据。

它适用于网址:

http://localhost:8080/myEntity/?$expand=myChildElement

但我似乎无法将下面的子元素包括在内:

http://localhost:8080/myEntity/?$expand=myChildElement/mySubChildElement

这是我的功能:

public virtual async Task<IHttpActionResult> GetElements(ODataQueryOptions<TEntity> queryOptions)
{
    IQueryable<TPoco> query = context.Set<TPoco>();

    string[] includes = null;
    string includeText = queryOptions.SelectExpand != null ? queryOptions.SelectExpand.RawExpand : null;
    if(! string.IsNullOrEmpty(includeText))
    {
        includes = queryOptions.SelectExpand.RawExpand.Split(',');
        return Ok(await query.ProjectTo<TEntity>(null, includes).ToListAsync());
    }

    return Ok(await query.ProjectTo<TEntity>().ToListAsync());
}

这是我的TPoco模型的一个例子(myChildElement可以是实体“Project”,mySubChildElement是子实体“ProjectType”):

public class ContractEntity : BaseEntity
{
    public ContractEntity()
    {
        this.Addresses = new HashSet<AddressEntity>();
    }

    override public Guid Id { get; set; }
    override public string DisplayName { get { return No.ToString(); } set { } }
    override public string ClassType { get { return "Contract"; } set { } }
    override public string MarkerColor { get { return Colors.Green.ToString(); } set { } }
    public int? No { get; set; }
    public DateTime? OfficialDate { get; set; }
    public DateTime? ValidDate { get; set; }
    public DateTime? SignatureDate { get; set; }
    public Guid? ProjectId { get; set; }
    [...]

    public virtual ICollection<AccountingItemEntity> AccountingItems { get; set; }
    public virtual ICollection<TagEntity> Tags { get; set; }
    public virtual ProjectEntity Project { get; set; }
    [...]
}

我希望你能帮助我。

1 个答案:

答案 0 :(得分:3)

我这样做,我使用.ProjectTo返回IQueryable的事实,所以我让OData框架处理查询,不是自己调用ToListAsync(),而是返回{{1 }}。

IQueryable

在此示例中,// In some class that is ': ODataController' [EnableQuery] //Attribute makes sure the OData framework handles querying public IQueryable<TDto> Get(ODataQueryOptions<TDto> options) { //The names of the properties requested by the client in the '$expand=' query option string[] requestedExpands = Helpers.Expand.GetMembersToExpandNames(options); // I made a helper for this, you can probably just use your code, or see my impementation below. var set = Db.Set<TEntity>().AsNoTracking(); //You might want to remove AsNoTracking if it doesn't work var converted = set.ProjectTo<TDto>(MapConfig, null, requestedExpands); return converted; } 是我要发送给客户端TDto的类型是Entity Framework POCO类。

我的TEntity我在应用程序启动时设置,在这里我将可扩展属性设置为&#39;显式扩展&#39;模式:

MapConfig

正如我在评论中所说,我通过在网址中嵌套MapConfig = new MapperConfiguration(cfg => { cfg.CreateMap<EFType, DTOType>(MemberList.Destination) .ForMember(c => c.ExpandableProperty, options => options.ExplicitExpansion()); }); 来请求数据:

$expand=

这对我有用,希望你能复制那个成功。

编辑:如果您想展开api/myEntity?$expand=myChildElement($expan‌​d=mySubChildElement) {&n; 39}已要求的扩展程序,请再次查看它。您传递给AutoMapper必须包含1个条目:myEntity.myChildElement.mySubChildElement。我为所有3个实体定义了映射,同样使用string[]选项。

根据@Tim Pohlmann的要求更新我对myChildElement.mySubChildElement的实施:

ExplicitExpansion