测试LINQ to SQL表达式

时间:2011-07-27 09:26:21

标签: linq linq-to-sql linq-expressions

我正在编写一个通过LINQ to SQL与MS SQL数据库一起工作的应用程序。我有时需要执行过滤,偶尔我的过滤条件太复杂,无法转换为SQL查询。虽然我试图让它们可翻译,但我希望我的应用程序至少可以工作,但有时会很慢。

LINQ to SQL数据模型隐藏在存储库中,我不想为不同的情况提供多个GetAll方法重载,并且要知道在较高级别使用什么重载。所以我想测试我在存储库中的表达式是否可以翻译,如果不是,则对整个数据集执行内存查询,而不是在查询实例化时抛出NotSupportedException。

这就是我现在所拥有的:

IQueryable<TEntity> table = GetTable<TEntity>();
IQueryable<TEntity> result;
try
{
    result = table.Where(searchExpression);

    //this will test our expression 
    //consuming as little resources as possible (???)        
    result.FirstOrDefault(); 
}
catch (NotSupportedException)
{
    //trying to perform in-memory search if query could not be constructed
    result = table
        .AsEnumerable()
        .Where(searchExpression.Compile())
        .AsQueryable();
}
return result;

searchExpressionExpression<Func<TEntity, bool>>

如您所见,我正在使用FirstOrDefault尝试实例化查询,并在无法实例化时抛出异常。但是,当表达式良好时,它将执行无用的数据库调用。我可以使用AnyCount或其他方法,它可能比FirstOrDefault稍微便宜一点,但是我想到的所有方法都会耗费大量数据库,虽然我只需要测试我的表达。

有没有其他方法可以说明我的表达式是“好”还是“坏”,没有实际的数据库调用?

更新

或者,更一般地说,有一种方法可以告诉LINQ在构造SQL时无法进行内存查询,因此根本不需要这种测试机制吗?

2 个答案:

答案 0 :(得分:2)

而不是

   result.FirstOrDefault(); 

使用

就足够了
    string sqlCommand = dataContext.GetCommand(result).CommandText; 

如果表达式没有生成有效的Sql,则应抛出NotSupportedException,但它实际上并不执行sqlCommand。

答案 1 :(得分:1)

我认为这可以解决您的问题:

IQueryable<TEntity> table = GetTable<TEntity>();  
IQueryable<TEntity> result;
try
{
    return table.Where(searchExpression).ToList();
}
catch (NotSupportedException)
{
    //trying to perform in-memory search if query could not be constructed
    return table
        .AsEnumerable()
        .Where(searchExpression.Compile())
        .ToList();
}

因此返回的方法是将表达式转换为有效的SQL。否则它捕获异常并在内存中运行查询。如果可以检查是否可以转换特定的searchExpression,这应该有效,但它不会回答您的问题。我认为这样的事情不存在。