Vraag Bekijk uitvoer van 'print'-statements met ADOConnection in Delphi


Sommige van mijn MS SQL-opgeslagen procedures produceren berichten met behulp van de opdracht 'afdrukken'. In mijn Delphi 2007-toepassing, die verbinding maakt met MS SQL met behulp van TADOConnection, hoe kan ik de uitvoer van die 'afdruk'-opdrachten bekijken?

Belangrijkste vereisten: 1) Ik kan de vraag niet meer dan één keer uitvoeren; het kan dingen bijwerken. 2) Ik moet de 'print'-resultaten zien, zelfs als er datasets worden geretourneerd.


10
2017-10-31 18:42


oorsprong


antwoorden:


Dat was een interessante ...
De OnInfoMessage-gebeurtenis van de ADOConnection werkt, maar de duivel zit in de details!

Hoofdpunten:
gebruik CursorLocation = clUseServer in plaats van de standaard clUseClient.
gebruik Open en niet ExecProc met uw ADOStoredProc.
Gebruik NextRecordset van de huidige om het volgende te krijgen, maar controleer of u er een hebt geopend.
gebruik SET NOCOUNT = ON in uw opgeslagen procedure.

SQL-kant: uw opgeslagen procedure

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[FG_TEST]') AND type in (N'P', N'PC'))
  DROP PROCEDURE [dbo].[FG_TEST]
GO
-- =============================================
-- Author:      François
-- Description: test multi ADO with info
-- =============================================
CREATE PROCEDURE FG_TEST
AS
BEGIN
    -- SET NOCOUNT ON absolutely NEEDED
    SET NOCOUNT ON;

    PRINT '*** start ***'

    SELECT 'one' as Set1Field1

    PRINT '*** done once ***'

    SELECT 'two' as Set2Field2

    PRINT '*** done again ***'

    SELECT 'three' as Set3Field3

    PRINT '***finish ***'
END
GO

Delphi-zijde:
Maak een nieuwe VCL Formulieren-applicatie.
Plaats een memo en een knop in uw formulier.

Kopieer de volgende tekst, wijzig de catalogus en gegevensbron en plak deze in uw formulier

object ADOConnection1: TADOConnection
  ConnectionString = 
    'Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security In' +
    'fo=False;Initial Catalog=xxxYOURxxxDBxxx;Data Source=xxxYOURxxxSERVERxxx'
  CursorLocation = clUseServer
  LoginPrompt = False
  Provider = 'SQLOLEDB.1'
  OnInfoMessage = ADOConnection1InfoMessage
  Left = 24
  Top = 216
end
object ADOStoredProc1: TADOStoredProc
  Connection = ADOConnection1
  CursorLocation = clUseServer
  ProcedureName = 'FG_TEST;1'
  Parameters = <>
  Left = 24
  Top = 264
end

In de OnInfoMessage van de ADOConnection gezet

Memo1.Lines.Add(Error.Description);

Plak deze code voor de ButtonClick

procedure TForm1.Button1Click(Sender: TObject);
const
  adStateOpen = $00000001; // or defined in ADOInt
var
  I: Integer;
  ARecordSet: _Recordset;
begin
  Memo1.Lines.Add('==========================');

  ADOStoredProc1.Open; // not ExecProc !!!!!

  ARecordSet := ADOStoredProc1.Recordset;
  while Assigned(ARecordSet) do
  begin
    // do whatever with current RecordSet
    while not ADOStoredProc1.Eof do
    begin
      Memo1.Lines.Add(ADOStoredProc1.Fields[0].FieldName + ': ' + ADOStoredProc1.Fields[0].Value);
      ADOStoredProc1.Next;
    end;
    // switch to subsequent RecordSet if any
    ARecordSet := ADOStoredProc1.NextRecordset(I);
    if Assigned(ARecordSet) and ((ARecordSet.State and adStateOpen) <> 0) then
      ADOStoredProc1.Recordset := ARecordSet
    else
      Break;
  end;

  ADOStoredProc1.Close;
end;

9
2017-11-01 00:27



In de verbindingsklassen van .net is er een gebeurtenis met de naam InfoMessage. In een handler voor deze gebeurtenis kunt u de InfoMessage (afdrukinstructies) ophalen uit de gebeurtenisargumenten.

Ik geloof dat Delphi een soortgelijk evenement heeft genaamd "OnInfoMessage" dat je zou kunnen helpen.


3
2017-10-31 18:58



Ik denk niet dat dat mogelijk is. U kunt een tijdelijke tabel gebruiken om afdrukinstructies te dumpen en deze samen met de resultaten te retourneren.


1
2017-10-31 18:48



Enkele verbeteringen aan de code van Francois (zoals getest met DXE2) om rekening te houden met meerdere afdrukinstructies en de resultaten van een variabel aantal selecties. De veranderingen zijn subtiel.

procedure TForm1.ADOConnection1InfoMessage(Connection: TADOConnection;
  const Error: Error; var EventStatus: TEventStatus);
var
  i: integer;
begin
  // show ALL print statements
  for i := 0 to AdoConnection1.Errors.Count - 1 do
  begin
    // was: cxMemo1.Lines.Add(Error.Description);
    cxMemo1.Lines.Add(
      ADOConnection1.Errors.Item[i].Description);
  end;
end;

procedure TForm1.cxButton1Click(Sender: TObject);
const
  adStateOpen = $00000001; // or uses ADOInt
var
  records: Integer;
  ARecordSet: _RecordSet;
begin
  cxMemo1.Lines.Add('==========================');

  ADOStoredProc1.Open;

  try
    ARecordSet := ADOStoredProc1.RecordSet; // initial fetch
    while Assigned(ARecordSet) do
    begin
      // assign the recordset to a DataSets recordset to traverse
      AdoDataSet1.Recordset := ARecordSet;
      // do whatever with current ARecordSet
      while not ADODataSet1.eof do
      begin
        cxMemo1.Lines.Add(ADODataSet1.Fields[0].FieldName + 
          ': ' + ADODataSet1.Fields[0].Value);
        AdoDataSet1.Next;
      end;
      // fetch next recordset if there is one
      ARecordSet := ADOStoredProc1.NextRecordSet(records);
      if Assigned(ARecordSet) and ((ARecordSet.State and adStateOpen) <> 0) then
        ADOStoredProc1.Recordset := ARecordSet
      else
        Break;
    end;
  finally
    ADOStoredProc1.Close;
  end;

end;

0
2017-10-30 18:35