14

Project エンティティと ProjectDTO があります。ProjectDTO を受け取って返し、OData をサポートできるようにする WebAPI コントローラー メソッドを作成しようとしています。

問題は、Project DTO ではなく Project エンティティを使用してデータベースをクエリできる ORM を使用していることです。ProjectDTO に基づいて OData から Project エンティティ クエリにフィルタリング/並べ替え/ページングを適用する方法はありますか?

public ODataQueryResult<ProjectDTO> GetProjects(ODataQueryOptions<ProjectDTO> query)
{
    var context = new ORM_Context();

    var projects = context.Projects; // IQueryable<Project>
    var projectDtos = query.ApplyTo(projectDTOs)); // <-- I want to achieve something similar here
    var projectDTOs =
        projects.Select(
            x =>
            new ProjectDTO
                {
                    Id = x.Id,
                    Name = x.Name
                });

    var projectsQueriedList = projectDtos.ToList();

    var result = new ODataQueryResult<ProjectDTO>(projectsQueriedList, totalCount);

    return result;
}
4

3 に答える 3

4

このようなもの(コンパイルは試していません)

using(var dataContext = new ORM_Context())
{
    var projects = dataContext.Projects; // IQueryable<Project>

    //Create a set of ODataQueryOptions for the internal class
    ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
    modelBuilder.EntitySet<Project>("Project"); 
    var context = new ODataQueryContext(
         modelBuilder.GetEdmModel(), typeof(Project));
    var newOptions = new ODataQueryOptions<Project>(context, Request);

    var t = new ODataValidationSettings() { MaxTop = 25 };
    var s = new ODataQuerySettings() { PageSize = 25 };
    newOptions.Validate(t);
    IEnumerable<Project> internalResults =
        (IEnumerable<Project>)newOptions.ApplyTo(projects, s);

    int skip = newOptions.Skip == null ? 0 : newOptions.Skip.Value;
    int take = newOptions.Top == null ? 25 : newOptions.Top.Value;

    var projectDTOs =
            internalResults.Skip(skip).Take(take).Select(x =>
                new ProjectDTO
                    {
                        Id = x.Id,
                        Name = x.Name
                    });

    var projectsQueriedList = projectDtos.ToList();
    var result = new ODataQueryResult<ProjectDTO>(
        projectsQueriedList, totalCount);
    return result;
}
于 2013-06-06T13:36:40.367 に答える
2

これを行う最も簡単な方法は、AutoMapper を使用することだと思います。だから、あなたのDTOのために

    [DataContract(Name = "Products")]
    public class ProductDTO
    {
        [Key]
        [DataMember]
        public string MyProductMember1 { get; set; }

        [DataMember]
        public string MyProductMember2 { get; set; }
        ...
    }

AutoMapper 構成のどこかに次のように記述する必要があります。

Mapper.CreateMap<Product, ProductDTO>();

そして、OData 用の IEdmModel の構築のどこか:

builder.EntitySet<ProductDTO>("Products");

コントローラーのコードは次のようになります

public class ProductsController : ODataController
{
    [EnableQuery]
    public IHttpActionResult Get()
    {
        var products = context.Products; // IQueryable<Product>
        return Ok(products.Project().To<ProductDTO>());
    }
}

この方法では、ORM エンティティを直接公開する必要はなく、OData を使用してフィルター処理、ページング、カウント、さらにはネストされたコレクションの展開を行うことができます。EF の場合、製品がマップされているテーブルを使用して、対応する SQL 要求に変換されます。ただし、注意してください: より複雑なケース (ネストされたコレクションなど) では、最適化されていない SQL 要求が発生する可能性があります。

于 2015-03-18T16:51:09.500 に答える