我正在编写一个通过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;
searchExpression
是Expression<Func<TEntity, bool>>
如您所见,我正在使用FirstOrDefault
尝试实例化查询,并在无法实例化时抛出异常。但是,当表达式良好时,它将执行无用的数据库调用。我可以使用Any
,Count
或其他方法,它可能比FirstOrDefault
稍微便宜一点,但是我想到的所有方法都会耗费大量数据库,虽然我只需要测试我的表达。
有没有其他方法可以说明我的表达式是“好”还是“坏”,没有实际的数据库调用?
更新
或者,更一般地说,有一种方法可以告诉LINQ在构造SQL时无法进行内存查询,因此根本不需要这种测试机制吗?
答案 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
,这应该有效,但它不会回答您的问题。我认为这样的事情不存在。