2

我正在编写一个通过 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尝试实例化查询并在无法实例化时抛出异常。但是,当表达式良好时,它将执行无用的数据库调用。我可以使用Any,Count或其他方法,那样可能会更便宜一些FirstOrDefault,但我想到的所有方法仍然需要花费昂贵的代价来访问数据库,而我所需要的只是测试我的表达方式。

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

更新:

或者,更一般地说,有没有办法告诉 LINQ 在构造 SQL 失败时进行内存查询,从而根本不需要这种测试机制?

4

2 回答 2

2

代替

   result.FirstOrDefault(); 

使用就足够了吗

    string sqlCommand = dataContext.GetCommand(result).CommandText; 

?

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

于 2011-07-27T17:04:47.397 回答
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这应该可以,但是如果可以检查是否可以转换特定内容,它不能回答您的问题。我不认为这样的事情存在。

于 2011-07-27T10:09:37.790 回答