简体   繁体   English

ASP.NET Web API OData-将DTO查询转换为实体查询

[英]ASP.NET Web API OData - Translating DTO queries into Entity queries

We are currently investigating the use of OData query syntax in our Web APIs. 我们目前正在调查Web API中OData查询语法的使用。 We are not looking to implement a full OData implementation - merely leverage the query syntax. 我们不打算实现完整的OData实现-仅利用查询语法。

It is generally considered good application architecture to separate your application into several layers. 通常,将应用程序划分为多个层是一种好的应用程序体系结构。 In modern web applications these layers would include a data layer and UI/Transport layer which may model the information stored in your database differently when sending it to your customers. 在现代Web应用程序中,这些层将包括数据层和UI /传输层,当将其发送给客户时,它们可能会对存储在数据库中的信息进行不同的建模。

eg: Your may have a database (Entity Framework) model that looks like this: 例如:您的数据库(实体框架)模型可能如下所示:

public class Employee
{
    public Guid Id {get; set;}
    public string Name {get; set;}
    public int AccessLevel {get; set;}
}

but your Web APIs may expose this data to your customers in a different wire format: 但是您的Web API可能会以其他有线格式向您的客户公开此数据:

public class EmployeeDto
{
    public string Name {get; set;}
    public string SecurityClearence {get; set;}
}

Using ASP.NET Web API and (presumably??) the Microsoft ASP.NET Web API OData libraries how would we achieve a scenario whereby our customers would write a query against the DTO format eg: 使用ASP.NET Web API和Microsoft ASP.NET Web API OData库(大概是?),我们将如何实现一种方案,使我们的客户针对DTO格式编写查询,例如:

?$filter=(SecurityClearence eq 'TopSecret')

... and we would then translate that against our data format. ...然后我们将其转换为我们的数据格式。 eg: 例如:

?filter=(AccessLevel eq 007)

or some other format that will allow me to dynamically query my database such as an Expression. 或其他允许我动态查询数据库的格式,例如表达式。 eg: 例如:

db.Employees.Where(translatedExpression);

I have thought of several ways to achieve this manually but I'm keen to know how other people would solve this because I feel my implementation so far is quite crude and unlikely to hold up to scrutiny. 我已经想到了几种手动完成此操作的方法,但是我很想知道其他人将如何解决此问题,因为我认为到目前为止,我的实现还很粗糙,不太可能接受审查。

Are there features of the Web API OData libraries (and related EDM libraries) that would achieve some or all of this for me? Web API OData库(和相关的EDM库)是否具有可以为我实现部分或全部功能的功能?

Gavin, 加文

I know I might be way too late for this party, but here are my two cents on this matter. 我知道我参加这个聚会可能为时已晚,但是这是我在这件事上的两分钱。

Back in 2013, I was working in a project and came up with this very same scenario. 早在2013年,我当时就在一个项目中工作,并提出了同样的方案。 I had an entity model and also a DTO model to be transferred in and out the service layer. 我有一个实体模型,还有一个DTO模型,可以在服务层中进出。 I did my research but did not find any libraries that would allow me to: 1. Map from my entity model to my DTO model in an automated way and 2. Translate filtering and sorting expressions on the DTO to the entity model. 我进行了研究,但没有找到任何库可以允许我执行以下操作:1.以自动方式将实体模型映射到DTO模型,并将2. DTO上的过滤和排序表达式转换为实体模型。

In the end I decided to code my own "projections" framework. 最后,我决定编写自己的“投影”框架。 A few months ago I published the code at GitHub and uploaded a NuGet package in case someone would need to do something like that. 几个月前,我在GitHub上发布了该代码,并上传了一个NuGet包,以防有人需要这样做。

Now, in case you decide to try it, you have to build and configure a ProjectionsModel (similar to how you would configure a EF code-first data model) and specify how the DTO model classes map to the entity model ones. 现在,如果您决定尝试使用它,则必须构建和配置一个ProjectionsModel(类似于配置EF代码优先数据模型的方式),并指定DTO模型类如何映射到实体模型。

using ExpressionFramework.Projections;

namespace TestDTO
{
    public class MyProjectionModel : ProjectionModel
    {
        protected override void OnModelCreating(ProjectionModelBuilder modelBuilder)
        {
            modelBuilder
                .Projection<UserAccountDTO>()
                .ForSource<UserAccountEntity>(configuration => 
                {
                    configuration.Property(dto => dto.RoleCount).ExtractFrom(entity => entity.Roles.Count());
                });
        }
    }
}

Then, you can create a model and use it to project and filter DTO queries into entity queries: 然后,您可以创建一个模型,并使用它来将DTO查询投影并过滤到实体查询中:

IQueryable<UserAccountEntity> usersQuery = usersList.AsQueryable();

var myProjectionModel = new MyProjectionModel();
var dtoUsersList = myProjectionModel.Project<UserAccountDTO, UserAccountEntity>(usersQuery).ToList();

Even tough filtering is not part of the example, you can create a collection of QueryFilter and QuerySorter objects and send them as parameters to the Project method. 即使QueryFilter过滤也不在示例中,您也可以创建QueryFilterQuerySorter对象的集合,并将它们作为参数发送到Project方法。

Let me know if you want to know more about this library. 如果您想进一步了解此库,请告诉我。

We have been using a combination of Entity Framework, Automapper and LinqToQueryable. 我们一直在使用Entity Framework,Automapper和LinqToQueryable的组合。

A typical controller action would look like this: 典型的控制器动作如下所示:

[HttpGet]
[LinqToQueryable]
public IEnumerable<SomeViewModel> SomeAction()
{
    return _databaseContext.Entities
                           .Where(e => e.SomeProp = "Example")
                           .Project()
                           .To<SomeViewModel>();
}

The nuget packages we needed were, LinqToQuerystring , linqtoquerystring.entityframework , LinqToQuerystring.WebApi . 我们需要的nuget包是LinqToQuerystringlinqtoquerystring.entityframeworkLinqToQuerystring.WebApi The docs are here: http://linqtoquerystring.net/ 该文档在这里: http : //linqtoquerystring.net/

Our company is looking to do this as well. 我们公司也希望做到这一点。 One possible solution I have been mulling over is creating a custom IQueryable LINQ Provider. 我一直在考虑的一种可能的解决方案是创建一个自定义的IQueryable LINQ提供程序。 This provider would be able to translate the clean model to the database model and query on the appropriate fields, as well as transform the data. 该提供程序将能够将干净的模型转换为数据库模型,并在适当的字段上进行查询,以及转换数据。

Piece of cake, right? 小菜一碟吧? Um.. yea.. we haven't started yet. 嗯..是的..我们还没有开始。

If anyone has additional suggestions, let me know. 如果有人有其他建议,请告诉我。

Walkthrough: Creating an IQueryable LINQ Provider 演练:创建一个IQueryable LINQ提供程序

LINQ: Building an IQueryable Provider - Part I LINQ:构建可查询的提供程序-第一部分

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Odata Asp.NET WebApi在实体/ DTO中返回json属性 - Odata Asp.NET WebApi return json property in entity/DTO ASP.NET中的oData,REST和Web API - oData, REST and Web API in asp.net 使用实体框架和 OData 查询的导航 DTO 属性 - Navigational DTO properties using Entity Framework with OData Queries 具有空间属性的实体上的ASP.NET Web API OData(v4)POST - ASP.NET Web API OData (v4) POST on Entity with SPATIAL PROPERTY 在asp.net web api中支持@ odata.bind(在帖子期间链接到现有实体) - support of @odata.bind in asp.net web api (link to existing entity during post) ASP.Net Core Web API 使用 OData 实现单个实体 URI 失败 - ASP.Net Core Web API implementation with OData fails for a single entity URI 如何在DTO和ASP.NET Web API和Unity中使用接口? - How to use interfaces in DTO with ASP.NET Web API and Unity? DTO上的ASP.Net Web API验证属性? - ASP.Net Web API Validation Attributes on DTO? 如何使用 asp.net web API 2(使用 TPL/Reactive)缓冲和批处理 REST get 查询? - How to buffer and batch REST get queries with asp.net web API 2 (using TPL/Reactive)? ASP.NET 内核 Web API - 执行“LastOrDefault”操作的查询必须具有确定的排序顺序 - ASP.NET Core Web API - Queries performing 'LastOrDefault' operation must have a deterministic sort order
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM