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

时间:2013-11-28 03:06:02

标签: c# asp.net-web-api expression ado.net-entity-data-model asp.net-web-api-odata

我们目前正在研究在我们的Web API中使用OData查询语法。 我们不打算实现完整的OData实现 - 只是利用查询语法。

通常认为将应用程序分成多个层是一种很好的应用程序架构。 在现代Web应用程序中,这些层将包括数据层和UI /传输层,可以在将数据发送给客户时对存储在数据库中的信息进行不同的建模。

例如:您可能拥有如下所示的数据库(实体框架)模型:

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

但您的Web API可能会以不同的电子格式向客户公开这些数据:

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

使用ASP.NET Web API和(可能是??)Microsoft ASP.NET Web API OData库我们如何实现一个场景,客户可以根据DTO格式编写查询 例如:

?$filter=(SecurityClearence eq 'TopSecret')

...然后我们会根据我们的数据格式进行翻译。 例如:

?filter=(AccessLevel eq 007)

或其他一些格式允许我动态查询我的数据库,例如Expression。 例如:

db.Employees.Where(translatedExpression);

我已经考虑了几种手动实现这一目标的方法,但我很想知道其他人会如何解决这个问题,因为我觉得到目前为止我的实施是非常粗糙的,不太可能经得起审查。

是否有Web API OData库(以及相关的EDM库)的功能可以为我实现部分或全部功能?

3 个答案:

答案 0 :(得分:2)

加文,

我知道这个派对我可能已经太迟了,但这件事就是我的两分钱。

早在2013年,我在一个项目中工作,并提出了同样的情况。我有一个实体模型,还有一个DTO模型,可以进出服务层。我做了我的研究,但没有找到任何允许我的库:1。以自动方式从我的实体模型映射到我的DTO模型,2。将DTO上的过滤和排序表达式转换为实体模型。

最后,我决定编写自己的"投影"框架。几个月前,我在GitHub发布了代码并上传了一个NuGet包,以防有人需要做类似的事情。

现在,如果您决定尝试它,您必须构建和配置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());
                });
        }
    }
}

然后,您可以创建一个模型并使用它来投影和过滤DTO查询到实体查询中:

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

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

即使强悍的过滤不是示例的一部分,您也可以创建QueryFilterQuerySorter个对象的集合,并将它们作为参数发送到Project方法。

如果您想了解有关此库的更多信息,请与我们联系。

答案 1 :(得分:0)

我们一直在使用Entity Framework,Automapper和LinqToQueryable的组合。

典型的控制器操作如下所示:

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

我们需要的nuget包是LinqToQuerystringlinqtoquerystring.entityframeworkLinqToQuerystring.WebApi。文档在这里:http://linqtoquerystring.net/

答案 2 :(得分:0)

我们公司也希望这样做。我一直在考虑的一个可能的解决方案是创建一个自定义的IQueryable LINQ Provider。此提供程序可以将清理模型转换为数据库模型并在适当的字段上进行查询,以及转换数据。

一块蛋糕,对吧?嗯..是的..我们还没有开始。

如果有人有其他建议,请与我们联系。

Walkthrough: Creating an IQueryable LINQ Provider

LINQ: Building an IQueryable Provider - Part I