SQL Server:存储过程和CLR Proc以不同方式返回数据

时间:2012-09-28 09:20:18

标签: sql-server-2008 delphi delphi-xe2 sqlclr

我正在使用Delphi XE2来调用返回数据的存储过程。存储过程基本上是:

set nocount on -- ensures that Delphi will see that dataset
...
exec StoredProcThatReturnsData
...
update [table]
update [another table]

当主程序是T-SQL程序时,它完成执行主程序,包括最后update语句,然后将数据返回给Delphi。

当主过程是CLR过程时,它会在子过程完成执行时返回数据,并且在我关闭Delphi中的update对象之前不会运行TSQLQuery语句。

Delphi代码如下所示:

rpt := TSQLQuery.Create(nil);
try
  rpt.MaxBlobSize := -1;
  rpt.SQLConnection := ASqlConnection;
  rpt.SQL.Text := 'exec RunMainProc';
  rpt.Open;
  // do some things that depend on the update statements
  // process the 'rpt' data
finally
  FreeAndNil(rpt);
end;

CLR proc看起来像这样:

[Microsoft.SqlServer.Server.SqlProcedure]
public static void RunReport(SqlGuid ReportID, SqlGuid UserID, SqlBoolean ForDownload)
{
  using (SqlConnection con = new SqlConnection("context connection=true"))
  {
    con.Open();
    using (SqlCommand cmd = new SqlCommand())
    {
      cmd.Connection = con;
      cmd.CommandText = "[identical SQL as T-SQL proc]";
      SqlContext.Pipe.ExecuteAndSend(cmd);
    }
  }
}

为什么在返回数据之前T-SQL过程完成执行,而CLR过程在Delphi关闭/销毁update查询之后等待运行rpt语句?

2 个答案:

答案 0 :(得分:1)

感谢Jeroen,我尝试从Delphi以外的地方运行东西并发现问题。

当我将T-SQL过程转换为CLR时,我在子过程中添加了一些调试代码,这使得它返回两个数据集而不是一个。这是第二个挂起数据集导致过程的CLR版本在主过程完成执行之前回送数据。

一旦我删除了调试代码(因此只生成了一个数据集),该过程的T-SQL和CLR版本运行完全相同 - 主要过程在数据之前完成运行交给德尔福。

答案 1 :(得分:0)

您的SP是否会返回记录?似乎没有。那么你不应该调用Open on Query。 Open准备DataSet以获取数据行,并且由于请求可以变长 - 它会根据需要获取它们。当您调用 TDataSet.Next TDataSet.Last 等时。 所以我想,如果你想在.Open之后与SP同步,你可以调用 rpt.Last

但正确的方法是不使用 Open 而是使用 ExecSQL

http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/SqlExpr_TSQLQuery_ExecSQL.html

PS:在C#中,您调用 SqlContext.Pipe.Execute ,而不是打开。同样期望适用于Delphi,在某种意义上,它是.Net和OLE DB的模型