Array
(
)

Insert, com Prodecure e ADO.NEt

Bruno Costa
   - 21 out 2011

Senhores,
Tenho uma aplicação web asp.net que contém duas Classes Model, Cliente e Endereco.
Na Classe CLiente tenho uma propriedade List<Endereco> enderecos, ou seja, um cliente pode ter mais de um Endereco.
No webform tenho um único formulário que contém dados de ambas as Classes.
No botão Gravar, crio três objetos, um do tipo Cliente, um do Tipo Endereco e a Lista de Enderecos, List<Endereco>.
Assicio cada textbox referente a Classe Cliente com sua respectiva propriedade, assim como os textbox dos endereços do CLiente.
Adiciono os endereços na lista de endereços.
e Passo para minha DAO um objeto do tipo Cliente contendo uma lista de Endereços.
Uso uma procedure para poder adicionar os dados nas duas tabelas no banco.
A dúvida é: Como vou associar os parâmetros do endereço na procedure sendo que eles estão em uma lista?

Agradeço a atenção e ajuda de todos.

Rodrigo Odasaki
   - 22 out 2011

Você deve passar tudo para objeto.
E depois colocar nos parâmetros.

Exemplo:
cmd.Parameters.AddWithValue(columnname, objeto);

Bruno Costa
   - 24 out 2011

Certo, mas como vou pegar por exemplo, o número da casa do cidadão dentro da lista que está em um objeto Cliente e associar a ao parâmetro @numero da procedure?

public bool inserirCliente(Model.ClienteModel cliente)
{
SqlConnection con = new SqlConnection(ConStr);
string sql = InserirCliente;
SqlCommand cmd = new SqlCommand(sql, con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue(@nome, cliente.Nome);
cmd.Parameters.AddWithValue(@telefoneResidencial, cliente.TelefoneResidencial);
cmd.Parameters.AddWithValue(@telefoneRecados, cliente.TelefoneRecados);
cmd.Parameters.AddWithValue(@telefoneCelular, cliente.TelefoneCelular);
cmd.Parameters.AddWithValue(@dataNascimento, cliente.DataNascimento);
cmd.Parameters.AddWithValue(@cpf, cliente.Cpf);
cmd.Parameters.AddWithValue(@email, cliente.Email);
cmd.Parameters.AddWithValue(@senha, cliente.Senha);
cmd.Parameters.AddWithValue(@ativo, cliente.Ativo);
// aqui tenho o parâmetro tipo que diz se o endereço é rua, avenida e etc....
// e a lista Enderecos dentro do objeto cliente
cmd.Parameters.AddWithValue(@tipo, cliente.Enderecos.);
con.Open();

try
{
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
return false;
throw ex;
}
finally
{
con.Close();
}
return true;
}

Fabio Rosa
   - 24 out 2011

Olá pessoal, vou deixar aqui minha opinião, se me permitem...

Neste caso Bruno, como você provavelmente tenha 2 tabelas no banco de dados (Cliente e Endereço), você teria em sua tabela
Endereço uma Foreign Key com o Código do Cliente para manter a relação de 1 para muitos.

Então baseado nesta afirmação, eu faria um segundo método, que receberia uma instância da classe Endereço e também o
código do cliente ao qual este endereço pertence. Faria neste método a inclusão de um único endereço para o cliente, basicamente
como você fez para o cliente e postou aqui.

Tendo o método acima concluído, no método onde você insere o cliente, apenas faça a inclusão do cliente, sem se preocupar com
o endereço por enquanto. Quando você fechar a conexão da inclusão do cliente, realize um foreach em cada endereço da lista
contida na instância do cliente, recebida por parâmetro, sendo que cada instância desta lista será uma instância da classe
Endereço, chame o segundo método e passe o código do cliente que acabou de incluir e a instância do endereço a ser incluído para
o mesmo.

Não sei se é a melhor forma de resolver, mas é o que eu faria a princípio...

Espero ter ajudado.

Abraços..

Bruno Costa
   - 24 out 2011

Entendi.

Valeu pela ajuda..
Ótima solução...
Vou fazer desta forma e ver se consigo otimizar...

Obrigado.

Bruno Costa
   - 25 out 2011

Fiz assim:

public bool inserirCliente(Model.ClienteModel cliente)
{
SqlConnection con = new SqlConnection(ConStr);

string sql = InserirCliente;
SqlCommand cmd = new SqlCommand(sql, con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue(@nome, cliente.Nome);
cmd.Parameters.AddWithValue(@telefoneResidencial, cliente.TelefoneResidencial);
cmd.Parameters.AddWithValue(@telefoneRecados, cliente.TelefoneRecados);
cmd.Parameters.AddWithValue(@telefoneCelular, cliente.TelefoneCelular);
cmd.Parameters.AddWithValue(@dataNascimento, cliente.DataNascimento);
cmd.Parameters.AddWithValue(@cpf, cliente.Cpf);
cmd.Parameters.AddWithValue(@email, cliente.Email);
cmd.Parameters.AddWithValue(@senha, cliente.Senha);
cmd.Parameters.AddWithValue(@ativo, cliente.Ativo);
cmd.Parameters.AddWithValue(@tipo, cliente.Enderecos[1].Tipo);
cmd.Parameters.AddWithValue(@cep, cliente.Enderecos[1].Cep);

con.Open();

try
{
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
return false;
throw ex;
}
finally
{
con.Close();
}
return true;
}

Fabio Rosa
   - 25 out 2011

Bruno,

Neste caso você está gravando, na tabela de clientes, apenas o Tipo e o Cep do segundo endereço vinculado ao cliente....

É este seu objetivo?

Att.

Rodrigo Odasaki
   - 26 out 2011

Bruno, como o Fabio mesmo disse você vai precisar ter 2 tabelas já que vai ter um relacionamento 1 para muitos.

Exemplo:
1 usuário pode ter 1 ou N endereços, esses endereços devem ficar em outra tabela chamada Endereco a qual possui um
relacionamento com a tabela Usuario.

Usuario X Endereço

Tabela Usuario
UserId Type: int (PK)
Nome Type: varchar(50)

Tabela Endereco
Id int Type: int(PK)
UserId Type: int(FK)
Endereco Type: varchar(50)

Só que vocÊ vai precisar cadastrar primeiro o usuário e depois em outro form os endereços setando o id do usuário.
Ou se quiser fazer o cadastro em um único método, terá que criar uma procedure que devolva o ID do usuário cadastrado para
poder utilizar este id na hora de salvar os endereços.

Exemplo de uma proc:

CREATE PROCEDURE [dbo].[spImovelInsert]
@ImovelId int output,
@Titulo varchar(50),
@Preco decimal(18, 2),
@OcultaPreco bit,
@Ativo bit,
@Destaque bit,
@Descricao nvarchar(1000),
@DataCriacao datetime,
@CategoriaId int,
@FinalidadeId int,
@BairroId int

AS

INSERT INTO Imovel
(Titulo, Preco, OcultaPreco, Ativo, Destaque, Descricao, DataCriacao, CategoriaId, FinalidadeId, BairroId)
VALUES
(@Titulo, @Preco, @OcultaPreco, @Ativo, @Destaque, @Descricao, @DataCriacao, @CategoriaId, @FinalidadeId, @BairroId)

SELECT @ImovelId = @@IDENTITY

SELECT @ImovelId = SCOPE_IDENTITY()

Rodrigo Odasaki
   - 26 out 2011

Exemplo no código com o meu modelo para um site que eu fiz imobiliário em ADO.NET

SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings[ConnectionString].ConnectionString);
SqlCommand cmd = new SqlCommand(spImovelInsert, con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue(@Titulo, tituloTextBox.Text);
cmd.Parameters.AddWithValue(@Preco, Convert.ToDouble(precoTextBox.Text));
cmd.Parameters.AddWithValue(@OcultaPreco, ocultaPrecoComboBox.SelectedValue);
cmd.Parameters.AddWithValue(@Ativo, ativoComboBox.SelectedValue);
cmd.Parameters.AddWithValue(@Destaque, destaqueComboBox.SelectedValue);
cmd.Parameters.AddWithValue(@Descricao, descricaoTextBox.Text);
cmd.Parameters.AddWithValue(@DataCriacao, DateTime.Now);
cmd.Parameters.AddWithValue(@CategoriaId, categoriaComboBox.SelectedValue);
cmd.Parameters.AddWithValue(@FinalidadeId, finalidadeComboBox.SelectedValue);
cmd.Parameters.AddWithValue(@BairroId, bairroComboBox.SelectedValue);

SqlParameter ImovelId = new SqlParameter(@ImovelId, SqlDbType.Int);
ImovelId.Direction = ParameterDirection.Output;
cmd.Parameters.Add(ImovelId);

con.Open();
cmd.ExecuteNonQuery();

if (con.State != ConnectionState.Open)
{
con.Open();
}

try
{
cmd.ExecuteNonQuery();
}
catch (Exception)
{
throw;
}
finally
{
if (con.State != ConnectionState.Closed)
{
con.Close();
}
}

//Recupera na viriável valorId o id do imóvel que foi criado.
int valorId = Convert.ToInt32(cmd.Parameters[@ImovelId].Value.ToString());

Rodrigo Odasaki
   - 26 out 2011

Depois com o ID retornado você vai utilizar no mesmo código para salvar os endereços do seu usuário.

Rodrigo Odasaki
   - 26 out 2011

Retificando:

Na hora de copiar o código do meu projeto, acabei copiando o código 2x para informar o tipo CommandTyp e para abrir a conexão e dar o comando ExecuteNonQuery...

Bruno Costa
   - 26 out 2011


Citação:
Bruno,

Neste caso você está gravando, na tabela de clientes, apenas o Tipo e o Cep do segundo endereço vinculado ao cliente....

É este seu objetivo?

Att.


Vixe coloquei o índice errado. No caso é Zero.

Completando o código o que fiz foi verificar se a lista tem mais de um endereço, se tiver passo todos os parâmetros do cliente, do 1º endereço e do 2ºendereço, para a procedure InserirCliente.
Nesta procedure, faço um insert na tabela Clientes passando os parâmetros referente aos clientes.
Peguei o Id deste cliente usando o SCOPE_IDENTITY()
E faço dois inserts na tabela de Endereços com seus parametros e colocando o Id do cliente obtido com o SCOPE_IDENTITY().