我正在编写一个通过 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>
如您所见,我正在使用 FirstOrDefault
来尝试实例化查询并在无法实例化时抛出异常。然而,当表达式良好时,它会执行无用的数据库调用。我可以使用 Any
、Count
或其他方法,它很可能比 FirstOrDefault
便宜一点,但仍然是所有方法我的思想在数据库中进行了一次代价高昂的旅行,而我所需要的只是测试我的表达。
有没有其他方法可以在没有实际数据库调用的情况下判断我的表达是“好”还是“坏”?
更新:
或者,更一般地说,有没有办法告诉 LINQ 在构造 SQL 失败时进行内存中查询,这样就根本不需要这种测试机制了?
I am writing an application that works with MS SQL database via LINQ to SQL. I need to perform filtering sometimes, and occasionally my filtering conditions are too complicated to be translated into SQL query. While I am trying to make them translatable, I want my application to at least work, though slow sometimes.
LINQ to SQL data model is hidden inside repositories, and I do not want to provide several GetAll method overloads for different cases and be aware of what overload to use on upper levels. So I want to test my expression inside repository to be translatable and, if no, perform in-memory query against the whole data set instead of throwing NotSupportedException on query instantiating.
This is what I have now:
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
is Expression<Func<TEntity, bool>>
As you see, I am using FirstOrDefault
to try to instantiate the query and throw the exception if it cannot be instantiated. However, it will perform useless database call when the expression is good. I could use Any
, Count
or other method, and it may well be a bit less expensive then FirstOrDefault
, but still all methods that come to my mind make a costly trip to database, while all I need is to test my expression.
Is there any alternative way to say whether my expression is 'good' or 'bad', without actual database call?
UPDATE:
Or, more generally, is there a way to tell LINQ to make in-memory queries when it fails to construct SQL, so that this testing mechanism would not be needed at all?
发布评论
评论(2)
而不是
使用就足够了
?
如果表达式没有生成有效的 Sql,则应该抛出 NotSupportedException,但它实际上并不执行 sqlCommand。
Instead of
would it be sufficient to use
?
If the expression does not generate valid Sql, this should throw a NotSupportedException, but it does not actually execute the sqlCommand.
我认为这会解决你的问题:
所以该方法返回的是表达式被转换为有效的 SQL。否则,它会捕获异常并在内存中运行查询。这应该可行,但如果可以检查是否可以转换特定的
searchExpression
,它不会回答您的问题。我认为这样的事情不存在。I think this will solve your problem:
So the method returns is the expression is converted to valid SQL. Otherwise it catches the exception and runs the query in memory. This should work but it doesn't answer your question if it's possible to check if a specific
searchExpression
can be converted. I don't think such a thing exists.