如何映射针对DTO的OData的查询到另一个实体? [英] How do I map an OData query against a DTO to another entity?

查看:157
本文介绍了如何映射针对DTO的OData的查询到另一个实体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题很类似这样的:<一href=\"http://stackoverflow.com/questions/22969225/how-do-i-map-an-odata-query-against-a-dto-to-an-ef-entity\">How我反对的DTO的OData查询映射到EF实体?
我有一个简单的设置来测试的ASP.NET Web API的OData V4 $过滤功能。我想这样做是为了别名的ProductDTO的某些属性,以匹配产品实体的属性。用户将调用的ProductsController例如有以下要求:

My question is very similar to this one: How do I map an OData query against a DTO to an EF entity? I have a simple setup to test the ASP.NET Web API OData V4 $filter functionality. What I would like to do is to "alias" some properties of the ProductDTO to match the properties of Product entity. The user will call the ProductsController for example with the following request:

获得产品?$ =过滤器显示名称EQ测试

GET products?$filter=DisplayName eq ‘test’

产品类:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Level { get; set; }
    public Product()
    { }
}

该ProductDTO类:

The ProductDTO class:

public class ProductDTO
{
    public int Id { get; set; }
    public string DisplayName { get; set; }
    public int DisplayLevel { get; set; }
    public ProductDTO(Product product)
    {
        this.DisplayName = product.Name;
        this.DisplayLevel = product.Level;
    }
}

ProductsController类:

The ProductsController:

public class ProductsController : ApiController
{
    public IEnumerable<ProductDTO> Get(ODataQueryOptions<Product> q)
    {
        IQueryable<Product> products = this._products.AsQueryable();
        if (q.Filter != null) products = q.Filter.ApplyTo(this._products.AsQueryable(), new ODataQuerySettings()) as IQueryable<Product>;
        return products.Select(p => new ProductDTO(p));
    }
}

当然,我得到了以下异常:

Of course I’m getting the following exception:

找不到一个名为显示名称的type属性'TestAPI.Models.Product

Could not find a property named 'DisplayName' on type 'TestAPI.Models.Product'

我试图通过添加以下行到WebApiConfig.cs使用新引进的失真功能

I tried to use the newly introduced aliasing feature by adding the following lines to the WebApiConfig.cs

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        …
        IEdmModel model = GetModel();
        config.MapODataServiceRoute("*", "*", model);
    }

    private static IEdmModel GetModel()
    {
        ODataModelBuilder builder = new ODataConventionModelBuilder();
        EntitySetConfiguration<Product> products = builder.EntitySet<Product>("Product");
        products.EntityType.Property(p => p.Name).Name = "DisplayName";
        products.EntityType.Property(p => p.Level).Name = "DisplayLevel";
        return builder.GetEdmModel();
    }
}

我想,我使用的是失真功能不正确,因为作为上述相同的异常。如果我调用它的工作原理下面的请求,但是这不是我想要实现的:

I suppose that I'm using the aliasing feature incorrectly, because the same exception as described above is thrown. If I invoke the following request it works, but this is not what I'm trying to achieve:

获得产品?$ =过滤器EQ名称测试

GET products?$filter=Name eq ‘test’

更新:

我同意gdoron,在获取终点应该是这样的:

I agree with gdoron, the Get endpoint should look like this:

public IEnumerable<ProductDTO> Get(ODataQueryOptions<ProductDTO> q)

但是,这不应该是AutoMapper可解?

But this should be solvable without AutoMapper?

推荐答案

我找到了一个解决方案,而无需使用AutoMapper。

I found a solution without using AutoMapper.

ProductsController类现在看起来是这样的:

The ProductsController now looks like this:

public class ProductsController : ApiController
{
    public IEnumerable<ProductDTO> Get(ODataQueryOptions<ProductDTO> q)
    {
        IQueryable<Product> products = this._products.AsQueryable();

        IEdmModel model = GetModel();
        IEdmType type = model.FindDeclaredType("TestAPI.Models.Product");
        IEdmNavigationSource source = model.FindDeclaredEntitySet("Products");
        ODataQueryOptionParser parser = new ODataQueryOptionParser(model, type, source, new Dictionary<string, string> { { "$filter", q.Filter.RawValue } });
        ODataQueryContext context = new ODataQueryContext(model, typeof(Product), q.Context.Path);
        FilterQueryOption filter = new FilterQueryOption(q.Filter.RawValue, context, parser);

        if (filter != null) products = filter.ApplyTo(products, new ODataQuerySettings()) as IQueryable<Product>;
        return products.Select(p => new ProductDTO(p));
    }
}

该WebApiConfig:

The WebApiConfig:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        …
        IEdmModel model = GetModel();
        config.MapODataServiceRoute("*", "*", model);
    }

    private static IEdmModel GetModel()
    {
        ODataModelBuilder builder = new ODataConventionModelBuilder();
        EntitySetConfiguration<Product> product = builder.EntitySet<Product>("Products");
        product.EntityType.Name = "Product";
        product.EntityType.Namespace = "TestAPI.Models";
        product.EntityType.Property(p => p.Name).Name = "DisplayName";
        product.EntityType.Property(p => p.Level).Name = "DisplayLevel";
        return builder.GetEdmModel();
    }
}

这篇关于如何映射针对DTO的OData的查询到另一个实体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆