none
Verificar se registro existe antes da inclusão

    Question

  • Olá a todos!

    Desenvolvi um formulário de cadastro de empresas utilizando SqlDataSource. Tudo está funcionando, porém, gostaria de implementar uma confirmação para saber se o CNPJ já foi cadastrado no sistema.

    Na página .ASPX:

    Code Snippet

    <asp:SqlDataSource ID="sql" runat="server" ConnectionString="<%$ ConnectionStrings:cns_portalda_db %>"
            InsertCommand="INSERT INTO Fabricantes(Solicitante, Fabricante, Marca, DataCadastro, Endereco, CEP, Cidade, Estado, Telefone1, Email, Site, CNPJ, InscricaoEstadual, Status)
            VALUES (@Solicitante, @Fabricante, @Marca, GETDATE(), @Endereco, @CEP, @Cidade, @Estado, @Telefone1, @Email, @Site, @CNPJ, @InscricaoEstadual, 0)">
            <InsertParameters>
                <asp:Parameter Name="Solicitante" />
                <asp:Parameter Name="Fabricante" />
                <asp:Parameter Name="Marca" />
                <asp:Parameter Name="Endereco" />
                <asp:Parameter Name="CEP" />
                <asp:Parameter Name="Cidade" />
                <asp:Parameter Name="Estado" />
                <asp:Parameter Name="Telefone1" />
                <asp:Parameter Name="Email" />
                <asp:Parameter Name="Site" />
                <asp:Parameter Name="CNPJ" />
                <asp:Parameter Name="InscricaoEstadual" />
            </InsertParameters>
        </asp:SqlDataSource>



    No evento click:

    Code Snippet

    sql.InsertParameters["Solicitante"].DefaultValue = txtSolicitante.Text.Trim();
                sql.InsertParameters["Fabricante"].DefaultValue = txtFabricante.Text.Trim();
                sql.InsertParameters["Marca"].DefaultValue = txtMarca.Text.Trim();
                sql.InsertParameters["Endereco"].DefaultValue = txtEndereco.Text.Trim() + txtBairro.Text.Trim().Insert(0, " - ");
                sql.InsertParameters["Cidade"].DefaultValue = txtCidade.Text.Trim();
                sql.InsertParameters["Estado"].DefaultValue = ddlEstado.SelectedValue;
                sql.InsertParameters["CEP"].DefaultValue = txtCEP.Text.Trim().Replace("-", "");
                sql.InsertParameters["Telefone1"].DefaultValue = txtTelefone.Text.Trim();
                sql.InsertParameters["Email"].DefaultValue = txtMail.Text.Trim().ToLower();
                sql.InsertParameters["Site"].DefaultValue = txtSite.Text.Trim();
                sql.InsertParameters["CNPJ"].DefaultValue = txtCNPJ.Text.Trim().Replace("-", "").Replace("/", "").Replace(".", "");
                sql.InsertParameters["InscricaoEstadual"].DefaultValue = txtInscEstadual.Text.Trim().Replace("-", "").Replace("/", "").Replace(".", "");

    sql.Insert();




    Copiei só a parte que interessa, essa estrutura está montada no meio de trys e outras coisas.
    Até agora estou mantendo todas as queries do meu sistema através dos SqlDataSource's, e estou gostando bastante da praticidade e funcionalidade. Qual é a melhor forma de implementar essa verificação?

    Muito obrigado, e um grande abraço a todos.
    Monday, April 28, 2008 2:56 PM

Answers

  • Ola João,

    O SqlDataSource tem um evento chamado ItemInserted (http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.sqldatasource.inserted.aspx) que é disparado assim que um registro é (ou não) adicionado na sua DB.


    Como parâmetro para este evento, um objeto do tipo SqlDataSourceStatusEventArgs que, por sua vez, traz duas propriedades importantes: Exception e ExceptionHandled. Caso algum erro ocorra durante a inserção (como a violação de algum constraint), a propriedade Exception trará a exceção e, você utiliza a propriedade ExceptionHandled para dizer ao runtime do ASP.NET que você tratou o erro, evitando a exceção seja atirada para o cliente. Um exemplo:

    if( e.Exception != null)
    {
         this.lblMsg.Text = "Erro ocorreu...";
         e.ExceptionHandled = true;
    }

    Tuesday, April 29, 2008 6:23 PM
    Moderator
  • Ola,

    Se está utilizando Sql Server, provavelmente a propriedade Exception retornará uma instância da classe SqlException. Algo como:

    if (e.Exception is SqlException)
    {
        SqlException sql = (SqlException)e.Exception;
        //agora você tem propriedades dos erros do Sql...
    }

    Tuesday, April 29, 2008 6:47 PM
    Moderator
  • João o viniciusgama havia lhe apresentado uma solução da maneira que lhe passei. Em alguns posts acima.

    Mas caso você tenha mais alguma duvida favor postar.

     

    Code Snippet

    BEGIN TRAN

     

    IF EXISTS (SELECT * FROM [TABLE] WHERE CNPJ= @CNPJ AND ID = @ID)

    BEGIN

    SELECT RESULTADO = 'CNPJ JA EXISTE.'

    ROLLBACK TRAN

    RETURN 0

    END

     

    INSERT INTO [TABLE](ID,NOME, CNPJ)

    VALUES(@ID,@NOME, @CNPJ)

     

    IF @@ERROR = 0

    BEGIN

    SELECT RESULTADO = 'INCLUIDO COM SUCESSO'

    COMMIT TRAN

    RETURN @ID

    END

     

     

    Na funcao de inserir fica algo do tipo

    Code Snippet

    Public Function Insere() As Object

    Dim _cmd As SqlCommand = _conn.CreateCommand()

    Dim _strSQL As String = ""

    Dim _arrRetorno As New ArrayList

    _strSQL &= "INSERIR_NEW "

    _strSQL &= "@ID = '" & ID & "', "

    _strSQL &= "@NOME = '" EMAIL & "', "

    _strSQL &= "@CNPJ = '" & CNPJ& "'"

    _conn.Open()

    _cmd.CommandText = _strSQL

    Dim _dr As SqlDataReader = _cmd.ExecuteReader()

    _dr.Read()

    If _dr("resultado") = "INCLUIDO COM SUCESSO" Then

    _arrRetorno.Add(_dr("resultado"))

    _arrRetorno.Add(_dr("id"))

    Else

    _arrRetorno.Add(_dr("resultado"))

    _arrRetorno.Add(0)

    End If

    _dr.Close()

    _conn.Close()

    Return _arrRetorno

    End Function

     

     

    Depois e so voce criar um arraylist chamando a funcao

     

    dim retorno as arraylist = insere(parametros)

     

    retorno(0) e o resultado

    retorno(1) esta o id que foi inserido caso precise para usar em algum lugar

     

     

    SDS.

    Monday, July 21, 2008 7:06 PM

All replies

  • Ola João,

    Acho que a forma mais simples seria utilizar Constraints dentro da sua DB para garantir a unicidade de CNPJs.

     

    Monday, April 28, 2008 3:05 PM
    Moderator
  • Olá Israel, obrigado por responder.

    Já estou utilizando unique constraints nesses campos do banco, porém eu gostaria de implementar uma mensagem amigável ao usuário. O caso é que a empresa em questão pode ter sido cadastrada sem autorização, e a idéia é mostrar uma página com mais informações ou algo assim.
    Monday, April 28, 2008 3:15 PM
  • eu estava pensando exatamente nisso agora a pouco.

     

    estou no mesmo caso do joão.

     

    Eu ja tenho algumas chaves nos meus campos.. a unica conclusão que q eu cheguei foi tentar fazer um select nesse campo CPNJ.  se nao retornar nenhum valor fazer a inclusão..

     

    mas achei muito complicado e estou utilizando o banco duas vezes.

     

    alguem sabe se teria algum jeito menos complicado?

    Monday, April 28, 2008 3:45 PM
  • Normalmente eu faco essa verificacao na SP. Ela retorna o erro personalizado. No codigo vb eu verifico se foi ou nao incluido corretamente e retorno pro usuário se foi feita ou nao a modificacao juntamente com a mensagem da SP.

    Monday, April 28, 2008 6:34 PM
  • Olá Vinicius, obrigado por responder.

    Uma das dúvidas que eu tinha era justamente essa: implementar essa solução no banco ou no código. No banco já está assegurado que um CNPJ duplicado não vai ser inserido, resta a mensagem ao usuário.

    Não tenho prática com SP's, você poderia me dar um exemplo de como fazer isso com as informações do meu banco? Muito obrigado.
    Monday, April 28, 2008 6:39 PM
  • Code Snippet

    BEGIN TRAN

     

    IF EXISTS (SELECT * FROM [TABLE] WHERE CNPJ= @CNPJ AND ID = @ID)

    BEGIN

    SELECT RESULTADO = 'CNPJ JA EXISTE.'

    ROLLBACK TRAN

    RETURN 0

    END

     

    INSERT INTO [TABLE](ID,NOME, CNPJ)

    VALUES(@ID,@NOME, @CNPJ)

     

    IF @@ERROR = 0

    BEGIN

    SELECT RESULTADO = 'INCLUIDO COM SUCESSO'

    COMMIT TRAN

    RETURN @ID

    END

     

     

    Na funcao de inserir fica algo do tipo

    Code Snippet

    Public Function Insere() As Object

    Dim _cmd As SqlCommand = _conn.CreateCommand()

    Dim _strSQL As String = ""

    Dim _arrRetorno As New ArrayList

    _strSQL &= "INSERIR_NEW "

    _strSQL &= "@ID = '" & ID & "', "

    _strSQL &= "@NOME = '" EMAIL & "', "

    _strSQL &= "@CNPJ = '" & CNPJ& "'"

    _conn.Open()

    _cmd.CommandText = _strSQL

    Dim _dr As SqlDataReader = _cmd.ExecuteReader()

    _dr.Read()

    If _dr("resultado") = "INCLUIDO COM SUCESSO" Then

    _arrRetorno.Add(_dr("resultado"))

    _arrRetorno.Add(_dr("id"))

    Else

    _arrRetorno.Add(_dr("resultado"))

    _arrRetorno.Add(0)

    End If

    _dr.Close()

    _conn.Close()

    Return _arrRetorno

    End Function

     

     

    Depois e so voce criar um arraylist chamando a funcao

     

    dim retorno as arraylist = insere(parametros)

     

    retorno(0) e o resultado

    retorno(1) esta o id que foi inserido caso precise para usar em algum lugar

     

    Esse codigo da pra ser melhorado, acho q tem algumas redundancias ai.

     

    espero ter ajudado

    Monday, April 28, 2008 7:28 PM
  • Estou tendo dificuldade para implementar mantendo minha estrutura de SqlDataSource's... o que fazer?
    Tuesday, April 29, 2008 1:31 PM
  • Ola João,

    O SqlDataSource tem um evento chamado ItemInserted (http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.sqldatasource.inserted.aspx) que é disparado assim que um registro é (ou não) adicionado na sua DB.


    Como parâmetro para este evento, um objeto do tipo SqlDataSourceStatusEventArgs que, por sua vez, traz duas propriedades importantes: Exception e ExceptionHandled. Caso algum erro ocorra durante a inserção (como a violação de algum constraint), a propriedade Exception trará a exceção e, você utiliza a propriedade ExceptionHandled para dizer ao runtime do ASP.NET que você tratou o erro, evitando a exceção seja atirada para o cliente. Um exemplo:

    if( e.Exception != null)
    {
         this.lblMsg.Text = "Erro ocorreu...";
         e.ExceptionHandled = true;
    }

    Tuesday, April 29, 2008 6:23 PM
    Moderator
  • Olá, Israel

    Com certeza me ajudou bastante! Estava propenso a utilizar o ItemInserting e tratar durante a inserção, mas seu ponto de vista faz todo o sentido. Apenas para encerrar, existe alguma forma de obter o "tipo" da exceção para um tratamento mais adequado? Exemplo:

    if (exceção = unique constraint violation)
    {show error message}

    Muito obrigado mais uma vez.
    Tuesday, April 29, 2008 6:31 PM
  • Ola,

    Se está utilizando Sql Server, provavelmente a propriedade Exception retornará uma instância da classe SqlException. Algo como:

    if (e.Exception is SqlException)
    {
        SqlException sql = (SqlException)e.Exception;
        //agora você tem propriedades dos erros do Sql...
    }

    Tuesday, April 29, 2008 6:47 PM
    Moderator
  • Mais uma vez obrigado, Israel! Como sempre muito prestativo.

    Um abraço.
    Tuesday, April 29, 2008 6:52 PM
  • Phynton e a quem mais possa interessar.


    Seguindo as instruções do Israel montei a seguinte estrutura como exemplo pro evento OnItemInserted do SqlDataSource:

    Code Snippet

    protected void sql_Inserted(object sender, SqlDataSourceStatusEventArgs e)
        {
            SqlException ex = (SqlException)e.Exception;
            if (ex.Number == 2627)
            {
                lblMsg.Text = "CNPJ já cadastrado.";

                e.ExceptionHandled = true;

            }
        }



    Modifiquei a estrutura inicialmente proposta pelo Israel pois consegui chegar na exception com um caminho um pouco mais curto, causando um overhead menor. Coloquei o ExceptionHandled = true dentro do if, assim ele se refere apenas à exceção 2627 (Violation of UNIQUE KEY constraint). Acho que ficou extremamente funcional, se tiverem alguma melhoria é só falar.

    Aprender essa forma de capturar erros foi fantástico pro meu aprendizado, vou poder utilizar essa estrutura em diversas partes do projeto. Muito obrigado a todos que ajudaram!

    Grande abraço.
    Tuesday, April 29, 2008 8:15 PM
  • João a sua idéia é interessante, só o tratamento de exceções na aplicação é um pouco custoso, por seria mais interessante você tratar esse problema no banco, já que você esta usando SQL Server com procedure, acharia mais interessante você verificar se existe o registro via procedure e caso exista, retornar um flag para a sua aplicação. Com isso você tiraria as exceções da aplicação.

     

    Isso é apenas uma sugestão.

     

    Sds.

    Monday, July 21, 2008 2:55 PM
  • Olá Igor!

    Quando desenvolvi esse snippet ainda não trabalhava com Stored Procedures. Por sinal, ainda estou caminhando no aprendizado de banco de dados. De qualquer forma, concordo com você: quanto mais "pronta" a informação chegar na aplicação, melhor.

    Se não for pedir demais, você poderia postar um exemplo do tratamento através da procedure?

    Um abraço.
    Monday, July 21, 2008 3:58 PM
  • João o viniciusgama havia lhe apresentado uma solução da maneira que lhe passei. Em alguns posts acima.

    Mas caso você tenha mais alguma duvida favor postar.

     

    Code Snippet

    BEGIN TRAN

     

    IF EXISTS (SELECT * FROM [TABLE] WHERE CNPJ= @CNPJ AND ID = @ID)

    BEGIN

    SELECT RESULTADO = 'CNPJ JA EXISTE.'

    ROLLBACK TRAN

    RETURN 0

    END

     

    INSERT INTO [TABLE](ID,NOME, CNPJ)

    VALUES(@ID,@NOME, @CNPJ)

     

    IF @@ERROR = 0

    BEGIN

    SELECT RESULTADO = 'INCLUIDO COM SUCESSO'

    COMMIT TRAN

    RETURN @ID

    END

     

     

    Na funcao de inserir fica algo do tipo

    Code Snippet

    Public Function Insere() As Object

    Dim _cmd As SqlCommand = _conn.CreateCommand()

    Dim _strSQL As String = ""

    Dim _arrRetorno As New ArrayList

    _strSQL &= "INSERIR_NEW "

    _strSQL &= "@ID = '" & ID & "', "

    _strSQL &= "@NOME = '" EMAIL & "', "

    _strSQL &= "@CNPJ = '" & CNPJ& "'"

    _conn.Open()

    _cmd.CommandText = _strSQL

    Dim _dr As SqlDataReader = _cmd.ExecuteReader()

    _dr.Read()

    If _dr("resultado") = "INCLUIDO COM SUCESSO" Then

    _arrRetorno.Add(_dr("resultado"))

    _arrRetorno.Add(_dr("id"))

    Else

    _arrRetorno.Add(_dr("resultado"))

    _arrRetorno.Add(0)

    End If

    _dr.Close()

    _conn.Close()

    Return _arrRetorno

    End Function

     

     

    Depois e so voce criar um arraylist chamando a funcao

     

    dim retorno as arraylist = insere(parametros)

     

    retorno(0) e o resultado

    retorno(1) esta o id que foi inserido caso precise para usar em algum lugar

     

     

    SDS.

    Monday, July 21, 2008 7:06 PM
  • Beleza, Igor!

    Meu post é antigo mas vai ser de utilidade.

    Um abraço!
    Monday, July 21, 2008 7:52 PM
  • Cria uma constraint do Tipo Unique. Nunca vai repitir.

     CONSTRAINT [IX_CPF] UNIQUE NONCLUSTERED
    (
        [CPF] ASC
    )

    No código você trata.

     catch (SqlException ex)
                {
                    if (ex.Message.Contains("
    IX_CPF]"))
                        lblMsg.Text = "CPF JÁ CADASTRADO.";              
                    else
                        lblMsg.Text = ex.Message;
                }


    Monday, July 21, 2008 8:50 PM
  • Queria verificar através de código na aplicação sem utilizar triggers ou stored procedures. Como ficaria??? Estou usando Asp.Net com VB.Net.

     

    Wednesday, September 03, 2008 6:01 AM
  • Olá Artur!

    Na página anterior postei um snippet da solução que encontrei. Vale lembrar que para utilizá-la, você precisa ter uma constraint tipo "unique" no banco - assim você garante na aplicação E no banco de dados que nenhum registro será incluído.

    Não trabalho com VB, mas existem conversores na internet. Copie e cole o código e, se não funcionar, peça orientação a alguém aqui no forum.

    Espero ter ajudado.
    Wednesday, September 03, 2008 12:03 PM