views:

99

answers:

2

I'm working on a Delphi project with a MS SQL Server database, I connected the database with ADOConnection, DataSource and ADOProc components from Borland Delphi 7 and I added this code in behind:

procedure TForm1.Button2Click(Sender: TObject);
begin
  ADOStoredProc1.ProcedureName := 'sp_Delete_Clen';
  ADOStoredProc1.Refresh;
  ADOStoredProc1.Parameters.ParamByName('@clenID').Value := Edit6.Text;
  ADOStoredProc1.Active := True;
  ADOStoredProc1.ExecProc;
end;

The component Edit6 is an editbox that takes the ID of the tuple that should be deleted from the database and ADOStoredProc1 is the stored procedure in the database that takes 1 parametar (the ID you want to delete). The project runs with no problems, I even got a TADOTable and a DBGrid that load the information from the database, but when I try to delete a tuple from the database using its ID written in the EditBox I get this Error: "Cannot perform this operation on a closed dataset" and the breakpoint of the project is when the application tries to add the value for the 'clenID' parameter. Where is my mistake and how to fix it?

+2  A: 

I think the ADOStoredProc1.Refresh method is not appropriate here. In this case the stored procedure does not return a result set. Could you leave it out? And also the line ADOStoredProc1.Active := True. The connection to the database is open I presume? Could you also check the values of the Parameters collection in the Object Inspector?

Erwin
I put the Refresh method because I saw in one of the tutorial examples. I turn the procedure in active in this code because I cannot do that in the Object Inspector, I'm not allowed because "the stored procedure does not return a result set" but I don't have RESULT_SET parameter in the stored procedure like in some of the examples I saw online.
Kex
If the stored procedure does not return a result set, I mean a dataset is not returned from your stored procedure. Your stored procedure deletes a record, it gives not the result back from a select query. Anyway, another tutorial: http://www.podgoretsky.pri.ee/ftp/Docs/Delphi/D5/dg/ado_comp.html#28281
Erwin
I deleted the ADOStoredProcedure and replaced it with an ADOCommand and worked great, thanks anyway.
Kex
+1  A: 

I think you want to call ADOStoredProc1.Parameters.Refresh, not ADOStoredProc1.Refresh.

Also, you should only set Active to True if the SQL Server Stored procedure returns a dataset - i.e. the result of a SELECT statement. Setting Active to True is the same as calling Open.

If the stored procedure only returns a result code (RETURN n), then use ExecProc.

In no case should you use both ADOStoredProc1.Active := True; and ADOStoredProc1.ExecProc;

In summary, you probably want something like

procedure TForm1.btnDeleteClick(Sender: TObject);
begin
  ADOStoredProc1.ProcedureName := 'sp_Delete_Clen';
  ADOStoredProc1.Parameters.Refresh;  // gets the parameter list from SQL Server
  ADOStoredProc1.Parameters.ParamByName('@clenID').Value := edtID.Text;
  ADOStoredProc1.ExecProc;
end;
Gerry
thanks a lot, this one should work, I was calling the wrong Refresh all the time and setting the StoredProcedure to Active was one of the last acts of despair, then I deleted this component and made StoredProcedure call with the ADOCommand component writing it simple:ADOCommand1.CommandText := 'exec sp_Delete_Clen ' + Edit1.Text;..and it works great. In the matter of fact, what is the gain of using ADOStoredProcedure over ADOCommand?
Kex
@Kex amongst the advantages of TADOStoredProc is that you can call Parameters.Refresh to automatically create parameters for you, rather than having to add them yourself. Using parameterised queries reduces the chance of SQL Injection attacks - less of an issue with desktop apps, but still relevant. Generating params, rather than using :Param1, :Param2 etc allows you to add additional parameters with default values (`@Param3 int = null`) without updating the calling code - which can be useful.
Gerry