Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
测试LINQ到SQL表达式_Linq_Linq To Sql_Linq Expressions - Fatal编程技术网

测试LINQ到SQL表达式

测试LINQ到SQL表达式,linq,linq-to-sql,linq-expressions,Linq,Linq To Sql,Linq Expressions,我正在编写一个通过LINQtoSQL与MS SQL数据库一起工作的应用程序。有时我需要执行过滤,有时我的过滤条件太复杂,无法转换为SQL查询。当我试图使它们可翻译时,我希望我的应用程序至少能工作,尽管有时速度很慢 LINQtoSQL数据模型隐藏在存储库中,我不想为不同的情况提供几个GetAll方法重载,也不想知道在上层使用什么重载。所以我想在存储库中测试我的表达式是否可翻译,如果不是,则对整个数据集执行内存中的查询,而不是在查询实例化时抛出NotSupportedException 这就是我现在

我正在编写一个通过LINQtoSQL与MS SQL数据库一起工作的应用程序。有时我需要执行过滤,有时我的过滤条件太复杂,无法转换为SQL查询。当我试图使它们可翻译时,我希望我的应用程序至少能工作,尽管有时速度很慢

LINQtoSQL数据模型隐藏在存储库中,我不想为不同的情况提供几个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;
IQueryable table=GetTable();
可预测的结果;
尝试
{
结果=表。其中(搜索表达式);
//这将测试我们的表情
//消耗尽可能少的资源(???)
result.FirstOrDefault();
}
捕获(不支持异常)
{
//如果无法构造查询,则尝试执行内存内搜索
结果=表格
.可计算的()
.Where(searchExpression.Compile())
.AsQueryable();
}
返回结果;
searchExpression
Expression

如您所见,我使用
FirstOrDefault
尝试实例化查询,如果无法实例化,则抛出异常。但是,当表达式良好时,它将执行无用的数据库调用。我可以使用
Any
Count
或其他方法,它可能比
FirstOrDefault
便宜一点,但我想到的所有方法都会花费大量的时间访问数据库,而我所需要的只是测试我的表达式

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

更新:


或者,更一般地说,是否有一种方法可以告诉LINQ在构建SQL失败时进行内存查询,这样就根本不需要这种测试机制了?

我认为这将解决您的问题:

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();
}
IQueryable table=GetTable();
可预测的结果;
尝试
{
返回表.Where(searchExpression).ToList();
}
捕获(不支持异常)
{
//如果无法构造查询,则尝试执行内存内搜索
返回表
.可计算的()
.Where(searchExpression.Compile())
.ToList();
}
因此,当表达式转换为有效的SQL时,方法返回。否则,它将捕获异常并在内存中运行查询。这应该是可行的,但如果可以检查特定的
searchExpression
是否可以转换,它就不能回答您的问题。我认为这样的事情不存在。

而不是

   result.FirstOrDefault(); 
使用它是否足够

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


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

我认为您在这里有一个设计缺陷:您的存储库不应返回
IQueryable
,而只返回与数据库解耦的集合。当你这么做的时候,你的问题就不存在了。你没看到什么?为什么它让你的问题消失,或者为什么它是一个设计缺陷?为什么它让我的问题消失。我可能同意,将
IQueryable
返回给使用者可能是一个缺陷,因为这样一来,消费者就可以使用不受控制的不可翻译表达式运行任意查询,这将导致意外的运行时错误。但我想要的是能够在我的存储库中运行任意查询。方法签名看起来是这样的:
GetAll(Expression searchExpression)
,我需要保证无论是谁调用它,无论传递给它的是什么合法表达式,它都会返回经过筛选的项集合,至少在内存中是这样。关于该缺陷:是的,这就是我的意思。关于您的问题:不知何故,我忽略了
searchExpression
将只针对一个表进行计算。您能给我举一个不受支持的
searchExpression
的例子吗?我假设在使用用户定义的方法时会发生这种情况??用户定义的方法、在分部类中定义的属性等等。我们的想法不是尝试“SQLize”每个表达式——已经有很多表达式了,我现在实际上正在对它们进行SQLize——而是保证返回集合。SQLization可能需要数周的时间,但该站点现在需要启动并运行。不过,在某些方面我们可以承受缓慢的速度,这也将实例化查询,我不希望这种情况发生得那么早。如果我最后数一数这些东西呢?或者检查是否有?我仍然可以从SQL server获取整个数据集。您的方法基本上与我的
FirstOrDefault()
相同:直接在存储库中实例化查询并捕获实例化异常。不过,我的更好,因为它不获取整个数据集,而只获取第一条记录。使用
Any()
可能更好,因为它只能从SQL server获取true/false,而不是整个结构。@Michael:如果表达式无法转换为SQL,则不会命中任何数据库。因此,如果
searchExpression
无法转换为SQL,则
try
块中的部分将抛出异常,而不会命中数据库。在任何情况下,你将只有一个数据库命中。我想,这正是我需要的。谢谢