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

10
我们目前正在研究在Web API中使用OData查询语法。我们不打算实现完整的OData实现,只是利用查询语法。
通常认为将应用程序分成几个层是良好的应用架构。在现代Web应用程序中,这些层包括数据层和UI/传输层,当将其发送给客户时,可能会以不同的方式对存储在数据库中的信息进行建模。
例如:您可能有一个数据库(Entity Framework)模型,看起来像这样:
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)

或者其他可以允许我动态查询数据库的格式,例如表达式。 例如:

db.Employees.Where(translatedExpression);

我已经考虑了几种手动实现的方法,但我很想知道其他人将如何解决这个问题,因为我觉得我的实现方式还比较粗糙,不太可能经受住审查。

Web API OData库(以及相关的EDM库)是否有一些功能可以帮助我实现部分或全部内容?

3个回答

2

Gavin,

我知道我可能太晚了,但是我想就这个问题发表一下我的看法。

在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方法中。

如果您想了解更多关于这个库的信息,请告诉我。


你所完成的工作真是太棒了。非常感谢你。 - user326608

1
我们一直在使用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/

我会查看那个包,之前我也考虑过自己编写类似的东西。但出于以下两个原因,我并不喜欢我写出来的代码:1)投影操作是在SQL中完成的,这意味着我们不能再使用关键索引进行查询。2)我们对API进行版本管理,我不想为每个API版本编写不同的投影操作。我更喜欢的方法是在查询进入数据库之前将其翻译成另一种形式。虽然这可能更困难一些。 - Gavin Osborn

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接