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

0

Good evening!

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

  

(Error Violating restriction UNIQUE KEY 'UQ_TblPessoa_Cpf'.   You can insert the duplicate key into the object 'dbo.TblPeople'. The value   duplicate key is (22 $% # @).

Can not enter the NULL value in the Id_Pessoa column, 'DB_BANCO_DE_HORAS.dbo.TblFuncionario'; table, the column does not allow nulls. INSERT failed.) But if I look in the database the record is included, even with the idGerent. I hope it has become 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; }

    }
}
    
asked by anonymous 02.08.2017 / 03:41

2 answers

0

Hello, I was able to resolve this rule by deploying a trigger 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 to 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);
        }


    }
    
03.08.2017 / 05:15
0

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

I gave an improvement in 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 #

1st, do not run the same CMD 3 times.

cmd.ExecuteNonQuery();

is

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

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

3rd quit your connection use Using for example .

    
02.08.2017 / 13:31