测试 LINQ to SQL 表达式

发布于 2024-11-27 01:32:59 字数 1304 浏览 2 评论 0 原文

我正在编写一个通过 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>

如您所见,我正在使用 FirstOrDefault 来尝试实例化查询并在无法实例化时抛出异常。然而,当表达式良好时,它会执行无用的数据库调用。我可以使用 AnyCount 或其他方法,它很可能比 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

寒尘 2024-12-04 01:32:59

而不是

   result.FirstOrDefault(); 

使用就足够了

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

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

Instead of

   result.FirstOrDefault(); 

would it be sufficient to use

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

?

If the expression does not generate valid Sql, this should throw a NotSupportedException, but it does not actually execute the sqlCommand.

遮云壑 2024-12-04 01:32:59

我认为这会解决你的问题:

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 ,它不会回答您的问题。我认为这样的事情不存在。

I think this will solve your problem:

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();
}

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文