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

时间:2013-01-16 10:10:34

标签: c# sql linq linq-to-sql expression-trees

我有一个问题,想知道是否有办法吃蛋糕并吃掉它。

目前我有一个Repository和Query样式模式,用于我如何使用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");

这里要注意的主要部分是Mapper,Query,Repository,然后是最后的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()或itterate返回的数据,但是他们根据映射的模型进行过滤,而不是原始的表格模型,我认为这完全没问题,如上一个问题所述:

Linq2Sql point of retrieving data

总而言之,如果没有尝试将单个部分转换为SQL,我可以使用我的映射模式吗?

1 个答案:

答案 0 :(得分:5)

是的,你可以。将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());