Linq 到 sql 表达式树执行区域问题

本文关键字:执行 区域 问题 表达式 sql Linq | 更新日期: 2023-09-27 17:53:27

我遇到了一些问题,想知道是否有办法吃我的蛋糕。

目前,我有一个存储库和查询样式模式,用于我如何使用Linq2Sql,但是我遇到了一个问题,我看不到解决它的好方法。下面是问题的示例:

var someDataMapper = new SomeDataMapper();
var someDataQuery = new GetSomeDataQuery();
var results = SomeRepository.HybridQuery(someDataQuery)
                            .Where(x => x.SomeColumn == 1 || x.SomeColumn == 2)
                            .OrderByDescending(x => x.SomeOtherColumn)
                            .Select(x => someDataMapper.Map(x));
return results.Where(x => x.SomeMappedColumn == "SomeType");

这里要注意的主要部分是映射器,查询,存储库,然后是最终的where子句。我这样做是作为更大重构的一部分,我们发现有很多类似的查询,它们返回的结果集略有不同,但随后以相同的方式将它们映射到特定于领域的模型。因此,例如,获取一个tbl_car,然后将其映射到Car对象。因此,映射器基本上采用一种类型并吐出另一种类型,因此与选择中通常发生的情况完全相同:

// Non mapped version
select(x => new Car 
{
    Id = x.Id,
    Name = x.Name,
    Owner = x.FirstName + x.Surname
});
// Mapped version
select(x => carMapper.Map(x));

因此,汽车映射器在所有执行类似查询的区域上更可重用,返回相同的最终结果,但在此过程中执行不同的位。但是,我不断收到错误,说 Map 无法转换为 SQL,这很好,因为我不希望它,但是我知道因为它在表达式树中,它会尝试转换它。

{"Method 'SomeData Map(SomeTable)' has no supported translation to SQL."}

最后,返回和映射的对象被进一步传递到堆栈中供其他对象使用,这些对象利用 Linq to SQL 的复合能力向查询添加其他条件,最后 ToList(( 或迭代返回的数据,但是它们基于映射模型而不是原始表模型进行过滤, 我相信在上一个问题中回答的完全没问题:

Linq2Sql 检索数据点

因此,总而言之,我是否可以使用如图所示的映射模式,而无需尝试将该单个部分转换为SQL?

Linq 到 sql 表达式树执行区域问题

是的,你可以。把AsEnumerable()放在最后一个Select之前:

var results = SomeRepository.HybridQuery(someDataQuery)
                            .Where(x => x.SomeColumn == 1 || x.SomeColumn == 2)
                            .OrderByDescending(x => x.SomeOtherColumn)
                            .AsEnumerable()
                            .Select(x => someDataMapper.Map(x));

但是请注意,第二个Where - 在SomeMappedColumn上运行的那个 - 现在将在内存中执行,而不是由数据库执行。如果最后一个 where 子句显著减少了结果集,这可能是一个问题。


另一种方法是创建一个返回该映射的表达式树的方法。像下面这样的东西应该可以工作,只要映射中发生的所有事情都可以转换为SQL。

Expression<Func<EntityType, Car>> GetCarMappingExpression()
{
    return new Expression<Func<EntityType, Car>>(x => new Car 
    {
        Id = x.Id,
        Name = x.Name,
        Owner = x.FirstName + x.Surname
    });
}

用法是这样的:

var results = SomeRepository.HybridQuery(someDataQuery)
                            .Where(x => x.SomeColumn == 1 || x.SomeColumn == 2)
                            .OrderByDescending(x => x.SomeOtherColumn)
                            .Select(GetCarMappingExpression());