将 IQueryable where 子句从 DTO 映射到实体

Posted

技术标签:

【中文标题】将 IQueryable where 子句从 DTO 映射到实体【英文标题】:Mapping IQueryable where clause from DTO to Entity 【发布时间】:2015-05-15 00:25:33 【问题描述】:

我有一个 OData WebAPI 方法如下:

        // GET: odata/Employees
    [EnableQuery]
    public IQueryable<DTOs.Employee> GetEmployees()
    
        return this.AttemptOperation(context => 
            
                IQueryable<DTOs.Employee> employees
                    = context.Employees.Project().To<DTOs.Employee>();
                return employees;
            );
    

如果我没有指定过滤器,它会将数据返回给服务。 但是,只要我将 $filter=EmployeeID eq '1' 添加到 URL,就会出现异常。

例外来自我用于对 DynamoDB 执行 LINQ 查询的 AWS DynamoDB 上下文库。但是,它表明上下文没有 DTOs.Employee 表。

这当然很明显,上下文有实体,而不是 DTO。

如何获取客户端指定的 IQueryable where 子句以转换回正确的实体类型?

例如,客户端需要查询 DTOs.Employee.EmployeeID,它需要转换为针对 Entities.Employee.EmployeeID 的 where 子句。

【问题讨论】:

这很奇怪,我记得我们做了类似这样的事情并且它按预期工作。您能否使用简单的实体框架映射模型对此进行测试,并将其与 DynamoDB 中的相同模型进行比较?我怀疑这可能是由 DynamoDB 的可查询提供程序中的某些特殊性引起的。另外,这真的是GetEmployee 方法吗?该代码暗示它是一个GetEmployees 之类的调用。而且我认为它并不真正相关,但AttemptOperation 电话在做什么? 你说得对,它的员工......它可能会被重命名,我从 Visual Studio 模板开始,还没有研究命名约定,因为我只是想让事情正常工作.嗯,我将不得不检查 Linq2DynamoDB 的 IQueryable 提供程序。今天早些时候,我已经与代码维护人员一起修复了阻止投影朝一个方向工作的代码。 AttemptOperation 构建上下文并进行错误处理,我将所有 WebApi 和 MVC 方法包装在该模式中。 我只是深入研究了提供商,看看它在哪里爆炸。它遍历 where 子句的表达式树,并将表 (Entities.Employee) 的实体类型与 Expression.Type 值为 (DTOs.Employee) 的 MemberExpression 进行比较。也许只有我一个人,但我希望数据提供者会收到针对其本机类型的查询。 AutoMapper 是否将 IQueryable 的 where 子句从一种或另一种类型转换?还是我的误解? 我不确定。你或许应该试着和吉米本人谈谈这件事。我仍然怀疑这是一个与 DynamoDB 层不一致的实现细节,但我不知道它到底在做什么。您可以尝试在 AutoMapper 问题跟踪器中将此作为问题发布并指向此处,以便 Jim 可以提供答案(如果他的工具有问题,也许可以修复它)。另外我刚刚注意到您没有使用 AutoMapper 标记问题...将对其进行编辑。 【参考方案1】:

简单:

public IQueryable<DTOs.Employee> GetEmployees()

    return this.AttemptOperation(context => 
        
            // I commented here your old code:
            // IQueryable<DTOs.Employee> employees = context.Employees.Project().To<DTOs.Employee>();

            // This is our new code:
            var employees = context.Employees.Project()

            return employees.select(m=> new EmployeeDto 
                property1 = m.property1,
                property2 = m.property2
            
        );

重要提示:您不能使用 EmployeeDto 构造函数。 Linq 下禁止这样做。

【讨论】:

以上是关于将 IQueryable where 子句从 DTO 映射到实体的主要内容,如果未能解决你的问题,请参考以下文章

NHibernate LinqProvider / IQueryable:在 Where 子句中是不是支持 FirstOrDefault()?

MongoDB+C#+IQueryable - 有一个字符串数组以及如何在 Where 子句中将其加入 Mongos 集合

Linq to Entities 添加 Where 子句以在另一个表中查找 EXISTS

SSIS 数据流,忽略 SQL 语句中的 where 子句

实体框架,如何将 IQueryable 与多个 where 转换为 SQL 一起使用?

在 Oracle 查询中将连接从 Where 子句移动到 From 子句