我正在构建一个应用程序,我想将多个查询批处理到数据库的单个往返中。例如,假设单个页面需要显示用户列表,组列表和权限列表。
所以我存储了procs(或者只是简单的sql命令,比如“select * from Users”),我想执行其中的三个。但是,为了填充这一页,我必须进行3次往返。
现在我可以编写单个存储过程(“getUsersTeamsAndPermissions”)或执行单个SQL命令“select * from Users; exec getTeams; select * from Permissions”。
但我想知道是否有更好的方法来指定在一次往返中完成3次操作。好处包括更容易进行单元测试,并允许数据库引擎将查询并行化。
我正在使用C#3.5和SQL Server 2008。
答案 0 :(得分:37)
像this之类的东西。这个例子可能不是很好,因为它没有正确处理对象,但你明白了。这是一个清理版本:
using (var connection = new SqlConnection(ConnectionString))
using (var command = connection.CreateCommand())
{
connection.Open();
command.CommandText = "select id from test1; select id from test2";
using (var reader = command.ExecuteReader())
{
do
{
while (reader.Read())
{
Console.WriteLine(reader.GetInt32(0));
}
Console.WriteLine("--next command--");
} while (reader.NextResult());
}
}
答案 1 :(得分:8)
您提到的单个多部分命令和存储过程选项是两个选项。您无法以这样的方式执行它们,即它们在数据库上“并行化”。但是,这两个选项都会导致单次往返,所以你在那里很好。没有办法更有效地发送它们。在sql server 2005及更高版本中,完全参数化的多部分命令非常有效。
修改:添加有关为什么将cram整合到一个电话中的信息。
虽然您不想太在意减少通话,但 可能是合法的原因。
答案 2 :(得分:2)
进行一次往返三次比赛确实会更有效。问题是值得麻烦的。整个ADO.Net和C#3.5工具集和框架都反对您尝试的操作。 TableAdapters,Linq2SQL,EF,所有这些都喜欢处理简单的one-call == one-resultset语义。因此,通过尝试击败框架,您可能会失去一些严肃的生产力。
我会说,除非你有一些严肃的测量表明你需要减少往返次数,否则弃权。如果你做最终需要这个,那么使用存储过程至少给出一种API语义。
但是如果您的查询确实是您发布的内容(即选择所有用户,所有团队和所有权限),那么您显然已经拥有了在减少往返次数之前要更大的鱼来炸...先减少结果集。
答案 3 :(得分:1)
答案 4 :(得分:0)
建立临时表?将所有结果插入临时表,然后select * from @temp-table
,如,
@temptable=....
select @temptable.field=mytable.field from mytable
select @temptable.field2=mytable2.field2 from mytable2
等......只有一次数据库之旅,但我不确定它实际上是否更有效率。
答案 5 :(得分:0)
首先,3次往返并不是什么大不了的事。如果你在谈论 300 往返那么那将是另一回事,但对于仅仅3次往返我会认为这是definitley过早优化的情况。
那就是说,我这样做的方式可能是使用SQL执行3个存储的procuedres:
exec dbo.p_myproc_1 @param_1 = @in_param_1, @param_2 = @in_param_2
exec dbo.p_myproc_2
exec dbo.p_myproc_3
然后,您可以像直接执行多个行集一样遍历返回的结果集。