C# and Sql Server, inserting with proc using BEGIN TRAN

Asked

Viewed 368 times

0

Good night!

I am entering a record using the C# and Windows Forms, I am using a proc that inserts in two tables at once, the code is working, but, I created a rule that the store can only have only 1 manager, I played a select in proc to be able to use as return and use the cmd.Executeescalar (c#), however, it inserts into the table and still throws me an error on the screen

( Error Violation of UNIQUE KEY restriction 'Uq_tblpessoa_cpf'. Not possible insert duplicate key into dbo.Tblpessoa object. The value Duplicate key is (22$%#@).

Unable to enter value NULL in the column Id_Pessoa, table 'DB_BANCO_DE_HORAS.dbo.TblFuncionario'; the column does not allow nulls. Failure in INSERT. ) but if I look in the database the record is , including with idGerente. I hope it was clear :-)

proc code;

  ALTER PROC PR_INSERIR_PESSOA_E_FUNCIONARIO
    --pessoas 
    @Cpf varchar(11),
    @Nome varchar(60),
    @sexo char(1),
    --Funcionario
    @funcao varchar(30),
    @IdGerente int,
    @idLoja int
    as  
        DECLARE @X TABLE (IdPessoa INT)
        DECLARE @CONT INT = 0

        --VALIDANDO SE TEM GERENTE CADASTRADO NA LOJA
        IF(@funcao = 'GERENTE')     
            SET @CONT = (SELECT COUNT(*) FROM TblFuncionario WHERE Id_Loja = @idLoja)

        IF(@CONT <= 0)
        BEGIN       

            BEGIN TRAN

            INSERT INTO TblPessoa (Cpf,Nome,Sexo)
            --essa linha vai pegar o idPessoa que é gerado pelo identity e seta na table @x, no campo da tabela idPessoa
            output inserted.Id_Pessoa into @X
            VALUES
            (@Cpf,@Nome,@sexo)

            if(@IdGerente = '')
                set @IdGerente = null;

            INSERT INTO TblFuncionario (Id_Pessoa,Funcao,Id_Gerente,Ativo,Id_Loja, DataContrato)
            VALUES
            ( (SELECT IdPessoa FROM @X),@funcao,@IdGerente,1,@idLoja,GETDATE())

            IF @@ERROR = 0
                COMMIT
            ELSE
                ROLLBACK    

            select IdPessoa from @X
        END


    GO

C#

public bool InserirFuncionario (Funcionario funcionario)
        {
            int idpessoa = 0;
            bool cadastro = false;
            cmd = new SqlCommand();
            cmd.Connection = ConexaoBancoSQLServer.Conectar();

            cmd.CommandText = "PR_INSERIR_PESSOA_E_FUNCIONARIO";

            cmd.Parameters.AddWithValue("@Cpf", funcionario.cpf);
            cmd.Parameters.AddWithValue("@Nome", funcionario.nome);
            cmd.Parameters.AddWithValue("@sexo", funcionario.sexo);
            cmd.Parameters.AddWithValue("@funcao", funcionario.funcao);

            if(funcionario.id_Gerente.ToString() != "")
                cmd.Parameters.AddWithValue("@IdGerente", funcionario.id_Gerente);

            cmd.Parameters.AddWithValue("@idLoja", funcionario.id_Loja);


            cmd.CommandType = CommandType.StoredProcedure;

            cmd.ExecuteNonQuery();

            try
            {
                idpessoa = int.Parse(cmd.ExecuteScalar().ToString());
                cadastro = true;
            }
            catch (Exception ex)
            {

                Console.WriteLine("Erro " + ex.Message);
            }                        
            cmd.Parameters.Clear();
            cmd.Connection.Close();

            return cadastro;

        }


private void btnSalvar_Click(object sender, EventArgs e)
        {
            try
            {
                Funcionario funcionario = new Funcionario();


                funcionario.nome = txtNome.Text;
                funcionario.cpf = txtCpf.Text;
                funcionario.funcao = cmbFuncao.Text;
                funcionario.id_Loja = Convert.ToInt32(cmbLoja.SelectedValue);

                if(cmbGerente.Text != "")
                    funcionario.id_Gerente = FuncionarioGerenteCombo.func.id_Func;


                if (rdtFeminino.Checked == true || rdtMasculino.Checked == true)
                {
                    if (rdtFeminino.Checked == true)
                        funcionario.sexo = "F";
                    else
                        funcionario.sexo = "M";
                }


                if (funcionarioNegocio.InserirFuncionario(funcionario))
                {
                    MessageBox.Show("Funcionário cadastrado com sucesso!");

                    DialogResult resultado = MessageBox.Show("Deseja Cadastrar outro funcionário?", "Pergunta", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                    if (resultado == DialogResult.No)
                        LimparCampos();
                }
                else
                    MessageBox.Show("Erro");





            }
            catch (Exception erro)
            {

                MessageBox.Show("Erro: " + erro.Message);
            }


        }

namespace ObjetoTransferencia
{
    public class Pessoa
    {
        public int id_Pessoa { get; set; }
        public string cpf { get; set; }
        public string nome { get; set; }
        public string sexo { get; set; }

    }
}


namespace ObjetoTransferencia
{
    public class Funcionario : Pessoa
    {
        public int id_Func { get; set; }
        public string funcao { get; set; }
        public int id_Gerente { get; set; }
        public bool ativo { get; set; }
        public int id_Loja { get; set; }

    }
}
  • the error line is in Business & #Xa;idpessoa = int.Parse(cmd.Executescalar(). Tostring());

  • the error happens in Executaescalar because it is database error, only key breach error, check your Procedure and the data being or trying to enter

2 answers

0

There is something much easier to retrieve the last inserted record than to create a table after inserting the record in it called SCOPE_IDENTITY() I already answered this here;

I got an upgrade on your proc had some unnecessary things.

 ALTER PROC PR_INSERIR_PESSOA_E_FUNCIONARIO
    --pessoas 
    @Cpf varchar(11),
    @Nome varchar(60),
    @sexo char(1),
    --Funcionario
    @funcao varchar(30),
    @IdGerente int,
    @idLoja int
    as  

        --VALIDANDO SE TEM GERENTE CADASTRADO NA LOJA
        IF(@funcao = 'GERENTE') 
        BEGIN    
            DECLARE @CONT INT = (SELECT COUNT(*) FROM TblFuncionario WHERE Id_Loja = @idLoja)


        IF(@CONT <= 0)
            BEGIN       

                BEGIN TRAN

                INSERT INTO TblPessoa (Cpf,Nome,Sexo)VALUES (@Cpf,@Nome,@sexo)
                 DECLARE @PessoaId int = SCOPE_IDENTITY();

                if(@IdGerente = '')
                    set @IdGerente = null;

                INSERT INTO TblFuncionario (Id_Pessoa,Funcao,Id_Gerente,Ativo,Id_Loja, DataContrato)
                VALUES (@PessoaId ,@funcao,@IdGerente,1,@idLoja,GETDATE())

                IF @@ERROR = 0
                    COMMIT
                ELSE
                    ROLLBACK    

                select @PessoaId
            END
        END
    GO

Finally, you have to review 3 things in your C#

1º, do not perform 3 times the same CMD.

cmd.ExecuteNonQuery();

is

    try
    {
        idpessoa = int.Parse(cmd.ExecuteScalar().ToString());

2nd, not the need for you to do cmd.Parameters.Clear().

3rd end your connection use the Using for example.

0


Hello, I managed to solve this rule by implanting a Rigger and changing the proc

CREATE TRIGGER TR_VALIDAR_GERENTE

ON TblFuncionario

FOR INSERT, UPDATE

AS

DECLARE @FUNC VARCHAR(20) = (SELECT Funcao FROM inserted)

DECLARE @COUNT int = (SELECT COUNT(*) FROM TblFuncionario WHERE Funcao = 'GERENTE' and Id_Loja = (select Id_Loja from inserted))

IF(@FUNC = 'GERENTE' AND @COUNT > 1)
    ROLLBACK

CREATE PROC PR_INSERIR_PESSOA_E_FUNCIONARIO

--pessoas 

@Cpf varchar(11),
@Nome varchar(60),
@sexo char(1),

--Funcionario

@funcao varchar(30),
@IdGerente int,
@idLoja int
as  
DECLARE @X TABLE (IdPessoa INT)

BEGIN TRAN

    INSERT INTO TblPessoa (Cpf,Nome,Sexo)
    --essa linha vai pegar o idPessoa que é gerado pelo identity e seta na table @x, no campo da tabela idPessoa
    output inserted.Id_Pessoa into @X
    VALUES
    (@Cpf,@Nome,@sexo)

    if(@IdGerente = '')
        set @IdGerente = null;

    INSERT INTO TblFuncionario (Id_Pessoa,Funcao,Id_Gerente,Ativo,Id_Loja, DataContrato)
    VALUES
    ( (SELECT IdPessoa FROM @X),@funcao,@IdGerente,1,@idLoja,GETDATE())

IF @@ERROR = 0
    COMMIT
ELSE
    ROLLBACK    

And minor changes in C#

public void InserirFuncionario (Funcionario funcionario)
    {

        cmd = new SqlCommand();
        cmd.Connection = ConexaoBancoSQLServer.Conectar();

        cmd.CommandText = "PR_INSERIR_PESSOA_E_FUNCIONARIO";

        cmd.Parameters.AddWithValue("@Cpf", funcionario.cpf);
        cmd.Parameters.AddWithValue("@Nome", funcionario.nome);
        cmd.Parameters.AddWithValue("@sexo", funcionario.sexo);
        cmd.Parameters.AddWithValue("@funcao", funcionario.funcao);

        if(funcionario.id_Gerente.ToString() != "")
            cmd.Parameters.AddWithValue("@IdGerente", funcionario.id_Gerente);

        cmd.Parameters.AddWithValue("@idLoja", funcionario.id_Loja);


        cmd.CommandType = CommandType.StoredProcedure;

        cmd.ExecuteNonQuery();

        cmd.Parameters.Clear();
        cmd.Connection.Close();



    }



private void btnSalvar_Click(object sender, EventArgs e)

    {

        try
        {
            Funcionario funcionario = new Funcionario();


            funcionario.nome = txtNome.Text;
            funcionario.cpf = txtCpf.Text;
            funcionario.funcao = cmbFuncao.Text;
            funcionario.id_Loja = Convert.ToInt32(cmbLoja.SelectedValue);

            if(cmbGerente.Text != "")
                funcionario.id_Gerente = FuncionarioGerenteCombo.func.id_Func;


            if (rdtFeminino.Checked == true || rdtMasculino.Checked == true)
            {
                if (rdtFeminino.Checked == true)
                    funcionario.sexo = "F";
                else
                    funcionario.sexo = "M";
            }


            funcionarioNegocio.InserirFuncionario(funcionario);

            MessageBox.Show("Funcionário cadastrado com sucesso!");

            DialogResult resultado = MessageBox.Show("Deseja Cadastrar outro funcionário?", "Pergunta", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (resultado == DialogResult.No)
                LimparCampos();





        }
        catch (Exception erro)
        {

            MessageBox.Show("Erro: " + erro.Message);
        }


    }

Browser other questions tagged

You are not signed in. Login or sign up in order to post.