Strange Behaviour moving from firebird sql version 2.5 to version 4

174 views Asked by At

I have a Windows application written in C# using embedded firebird sql version 2.5.5.26952, which I am re-working it to update to embedded firebird sql version 4.0.0.2496. I have update the fdb file to the new version,and all the tables and sprocs, are there. When run a cmd.Fill() command for a selected statement rows are returned, if I do a update for a row in the table, I get the expected results back fine. but If I do a insert nothing is returned, and no errors are thrown, but the data is added to the database. If I run the sproc from the FireRobin application, the data is inserted, and a row is returned, so I'm at a loss to know why it is not working from my C# application. below is slimmed down version of the code.

The 2.5 version is using FirebirdSql.Data.FirebirdClient.4.10.0.0

The 4.0 version is using FirebirdSql.Data.FirebirdClient.9.0.2

using (var cmd = new FbDataAdapter("PROC_UPSERTPEOPLE", _connection)
{
  DataTable data = new DataTable();

  cmd.SelectCommand.Parameters.Add("SURNAME", FbDbType.Text).Value = item.Surname;
  cmd.SelectCommand.Parameters.Add("FORENAMENAME", FbDbType.Text).Value = item.Forename);

  var transaction = _connection.BeginTransaction();
  cmd.SelectCommand.CommandType = CommandType.StoredProcedure;
  cmd.SelectCommand.Transaction = transaction;
  var result = cmd.Fill(data);
  transaction.Commit();
}

On a update result contains 1, and data has the expected result, but on a insert result = 0, and data has no rows in.

Any help would be appreciated.

This is the simple version fo the sproc in question

CREATE OR ALTER PROCEDURE PROC_UPSERTPEOPLE_SLIM
(
  RECID     INTEGER,
  SURNAME   VARCHAR(100),
  FORENAME  VARCHAR(100)
)
RETURNS
(
  ID        INTEGER,
  LSURNAME  VARCHAR(100),
  LFORENAME VARCHAR(100)
)
AS
DECLARE VARIABLE local_id integer;
DECLARE VARIABLE local_surname varchar(100);
DECLARE VARIABLE local_forename varchar(100);
BEGIN

  select
    ID,
    FORENAME,
    SURNAME
  FROM
    APA_PEOPLE
  WHERE
    (:RECID IS NOT NULL AND ID = :RECID)
    OR (:RECID IS NULL
      AND FORENAME = :FORENAME
      AND SURNAME = :SURNAME)
  INTO
    :local_id,
    :local_forename,
    :local_surname;

  IF (:local_id IS NULL) then
  begin
    UPDATE OR INSERT INTO APA_PEOPLE(FORENAME, SURNAME)
    VALUES(:FORENAME, :SURNAME)
    MATCHING (FORENAME, SURNAME);
  end
  else
  begin
    UPDATE APA_PEOPLE SET FORENAME = :FORENAME,
      SURNAME = :SURNAME
    WHERE ID = :local_id;
  end

  FOR
    SELECT
      ID,
      SURNAME,
      FORENAME
    from
      APA_PEOPLE
    WHERE
      (:RECID IS NOT NULL AND ID = :RECID)
      OR (:RECID IS NULL
        AND FORENAME = :FORENAME
        AND SURNAME = :SURNAME)
    INTO
      :ID,
      :LSURNAME,
      :LFORENAME
  DO
  begin
    suspend;
  end

END;

Update

To answer my own question, being mainly a TSQL developer, DSQL seems strange, change the sproc to the following, which is simpler

CREATE OR ALTER PROCEDURE PROC_UPSERTPEOPLE_SLIM (
    RECID integer,
    SURNAME varchar(100),
    FORENAME varchar(100)
)
RETURNS (ID integer)SQL SECURITY INVOKER

AS
BEGIN

  UPDATE OR INSERT INTO APA_PEOPLE(FORENAME, SURNAME)
  VALUES(:FORENAME, :SURNAME)
  MATCHING (FORENAME, SURNAME)
  RETURNING ID INTO :ID;

END;

but also had to change the way it was called, to use

EXECUTE PROCEDURE PROC_UPSERTPEOPLE_SLIM(@RECID, @SURNAME, @FORENAME)

This does seem counter intuitive, I had assumed a stored procedure was a stored procedure, and there are not two different flavors. Oh well it works now, so move on to getting the rest of the app to work.

0

There are 0 answers