2009-06-18 96 views
0

我目前有一个对应于业务对象的“过滤器”对象。此对象具有与我希望能够过滤/搜索此类业务对象列表的不同方式有关的属性。目前,这些Filter对象有一个方法,它构建一个where子句的内容,然后将其传递给SQL Server 2000存储过程,并与select查询的其余部分进行联合。然后使用Exec执行最后一个字符串。替代执行动态sql

目前除了我担心与缺乏执行计划缓存的性能问题能正常工作。在一些研究中我看到了使用调用sp_executesql;这是一个更好的解决方案还是有更好的约定为我在做什么?

更新:我认为使用sp_executesql的问题的一部分是基于我的过滤器中的集合,我需要生成一个OR语句列表。我不确定'参数化'查询是否是我的解决方案。

例如

var whereClause = new StringBuilder(); 
    if (Status.Count > 0) 
    { 
     whereClause.Append("("); 
     foreach (OrderStatus item in Status) 
     { 
      whereClause.AppendFormat("Orders.Status = {0} OR ", (int)item); 
     }   

     whereClause.Remove(whereClause.Length - 4, 3); 
     whereClause.Append(") AND "); 
    } 

回答

0

现代RDBMS'es(真的不能说是否考虑SQL Server 2000中的“现代”的一个)是ad-hoc查询优化,所以有一个可以忽略不计的性能损失(如果任何)。有什么困扰我的是你使用sproc来构建动态SQL:这是一个庞大的调试/支持PITA。

+0

这是不正确的,因为同时当您使用sp_executesql的参数与你计划重用和过程缓存没有得到任何臃肿即席查询将得到不同的计划,每一次。你不会得到转换...如果你有nvarchar列并执行Col ='bla'你会得到一个转换,因为'bla'是varchar – SQLMenace 2009-06-18 13:59:14

+0

我同意你关于调试问题,然而主要的select查询字符串是一个相当简单的列选择和动态部分从负责清理数据并构造sql的对象传递。因此,对于大多数调试问题,我有一个地方可以看看Filter对象中的哪一个。 – jwarzech 2009-06-18 14:02:54

+0

我认为安东意味着说参数化即席查询肯定会得到缓存,并具有类似于存储特效的性能。 – 2009-06-18 14:11:02

1

你应该使用sp_executesql,原因很简单,就像你说的,查询计划存储和未来的执行将被优化。它通常也似乎比执行更好地处理动态SQL。

3

是,sp_executesql的将“缓存”的执行查询的计划它执行。

另一方面,不是通过区域查询的存储过程,构建完整的查询存在,并执行动态SQL,你可以建立在.NET上侧整个查询和使用ADO.NET命令对象执行。所有通过ADO.NET执行的查询都默认为“缓存”。

+1

只会缓存它被正确使用,一些开发人员将exec更改为sp_executesql,并且不使用sp_executesql中的params,这不会有所帮助。请参阅http://blogs.lessthandot.com/index.php/DataMgmt/ DataDesign/changing-exec-to-sp_executesql-doesn-tp – SQLMenace 2009-06-18 14:02:24

+0

+1:支持从SQL Server完全构建SQL语句。更好的跟踪/记录,更好的调试,更好的代码可读性。 – van 2009-06-18 14:03:25

0

sp_executesql的是更好的选择。你有没有考虑过不使用存储过程,或至少拿出一些动力?我认为从任何一种注射都会更安全。我写的过滤器很像你正在谈论的,但我试图照顾我的代码中的输入,而不是在存储过程中。我非常喜欢动态的sql,但有时候更加安全。

+0

我真的很想使用linq-sql:0) - 遗憾的是现在没有这个应用程序的选项。 – jwarzech 2009-06-18 14:06:03

+0

如果你不介意我的问题......为什么它不是一个选项? – Eric 2009-06-18 14:08:50