Baixe o app para aproveitar ainda mais
Prévia do material em texto
Curso Programando ASP.NET 3.5: Acesso a dados e recursos Avançados MÓDULO III Atenção: O material deste módulo está disponível apenas como parâmetro de estudos para este Programa de Educação Continuada. É proibida qualquer forma de comercialização do mesmo. Os créditos do conteúdo aqui contido são dados aos seus respectivos autores descritos na Bibliografia Consultada. 120 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores MÓDULO III Acesso a Dados A não ser que seu ramo de negócios seja algo muito específico, a imensa maioria das aplicações que você criar durante sua vida como desenvolvedor de software terá que, de alguma forma, alterar ou consultar dados. Na maior parte das aplicações este é, inclusive, o item mais sensível e importante: um modelo de acesso a dados mal planejado ou mal dimensionado pode tornar qualquer aplicação inútil. Existe uma grande variedade de sistemas de gerenciamento de dados no mercado. Se tivéssemos que desenvolver rotinas de consultas e alterações de dados para cada produto diferente do mercado teríamos uma grande dor de cabeça. Felizmente, a Microsoft deixou tudo pronto: seu modelo de acesso a dados, o ADO.NET, abstrai as nuances de programação de cada sistema, tornando o acesso a dados uma tarefa bem mais simples. O ADO.NET, acrônimo de ActiveX Data Objects, é o modelo de acesso a dados lançado junto com a plataforma .NET. Seu grande diferencial com relação a modelos anteriores é a capacidade de trabalhar com dados sem manter uma conexão permanente com a fonte de informações. Vou explicar melhor: Nos modelos anteriores, a aplicação abria uma conexão, executava uma ou mais operações na base de dados e então a conexão era encerrada. O modelo ADO.NET muda este paradigma: a conexão é aberta, os dados são recuperados e então a conexão é encerrada, operações são realizadas sobre os dados, a conexão é novamente aberta, as alterações são enviadas para a base de dados e então outra vez é conexão é encerrada. Note que a grande diferença é que toda e qualquer operação na base de dados pode ser feita sem que seja mantida uma conexão aberta com a base de dados. Este modelo, como você deve estar imaginando, foi criado pensando na programação de aplicação para a Internet. Nosso curso sobre acesso a dados em .NET será dividido em duas partes principais: inicialmente vamos estudar o acesso a dados de forma declarativa, onde vamos instanciar conexões, objetos de comando, parâmetros, definir propriedades, métodos e eventos, construir instruções SQL, entre outros. Na segunda parte iremos 121 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores utilizar controles visuais de acesso a dados. Na primeira parte escreveremos bastante códigos e utilizaremos poucos controles visuais. Na segunda parte vamos empregar muitos controles visuais e escrever menos códigos. Se você esta pensando em estudar apenas a segunda parte, minha sugestão é para que você NÃO FAÇA ISSO. Controles visuais ajudam muito, lhe dão um grande ganho de produtividade e tornam o nosso trabalho mais divertido, porém não irão resolver todos os problemas que você vai encontrar no seu dia-a-dia como um profissional desenvolvedor de aplicações: muitas vezes é preciso digitar código e resolver os problemas com algumas linhas de programação. Eu diria que na solução da maioria dos problemas de acesso a dados na vida real utilizamos um misto de código e controles visuais. Preparando o Ambiente Você pode criar uma aplicação ASP.NET que acesse praticamente qualquer fonte de dados: Oracle, DB2, Informix, FireBird, etc. Para algumas destas fontes de dados você vai ter sucesso utilizando provedores OleDB ou drivers ODBC gratuitos ou que já acompanham o .NET. Para outros você vai ter que comprar algum produto comercial. Neste curso vamos usar unicamente o SQL Server em nossos exemplos. Os motivos são diversos: este é o sistema gerenciador de banco de dados da Microsoft. O .NET está pronto para sua utilização; é um produto de fácil emprego, bastante intuitivo. Por fim, vale lembrar que como estamos acessando dados em alto nível, ou seja, utilizando uma camada de abstração – o ADO.NET – ao aproveitar outra fonte de dados as diferenças serão sutis, senão inexistentes. Agora qual versão do SQL Server usar? Nos meus exemplos vou utilizar o SQL Server Express 2005 e o banco de dados de demonstração NorthWind. Isto é uma mistura de uma versão do SQL Server com o banco de dados de demonstração de outra versão (O banco Northwind é o banco de dados da versão 2000 do SQL Server). Por que esta mistura? Vou explicar: o banco de dados de demonstração do SQL Server 2005, denominado AdventureWorks, possui um recurso denominado schemas, em que o nome de uma tabela pode ser composto através de um modelo Schema.Nome. É desta forma 122 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores que o AdventuraWorks foi criado. Curiosamente, alguns controles visuais do ASP.NET possuem um bug com esta forma de nomear tabelas. Tal bug não impede sua utilização, mas tornam seu uso um tanto quanto desapropriado em um curso. O banco de dados Northwind não utiliza o recurso de schemas, portanto não apresentam tal problema. Você poderá também usar a versão 2000 ou 2008 do SQL Server, não haverá qualquer diferença com relação ao curso. Também não é obrigatória a utilização da edição Express: qualquer edição é útil. Você pode baixar o banco de dados Northwind no endereço: http://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356- 46A0-8DA2-EEBC53A68034&displaylang=en. Outra forma de localizá-lo rapidamente é fazer uma busca na Internet, simplesmente utilizando a palavra Northwind. O SQL Server Express, 2005 ou 2008 pode ser baixado no endereço: www.microsoft.com/sql. Se você não possui qualquer ferramenta administrativa para SQL Server, recomendo baixar o SQL Server Managment Studio Express, que é capaz de se conectar a qualquer versão ou edição do SQL Server. Uma ferramenta administrativa é indispensável ao decorrer do desenvolvimento de um software ou mesmo para estudos. Na próxima seção vou demonstrar como anexar o banco de dados de demonstração Northwind ao seu SQL Server. Anexando o Banco de Dados NorthWind Primeiramente execute o instalador do banco de dados Northwind. Em meu equipamento os arquivos do banco de dados foram extraídos em uma pasta no caminho C:\SQL Server 2000 Sample Databases. Antes de anexá-lo, você pode querer alterar a sua localização física, para isso basta movê-lo para qualquer outro local de seu computador, lembrando que você deve alterar o arquivo de banco de dados (NORTHWND.MDF) e o arquivo de log de transações (NORTHWND.LDF). O banco de dados pode ser anexado através de um comando TQL ou visualmente, pelo Management Studio. Vamos ver as duas formas. O comando TSQL necessário pode ser visto a seguir: 123 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores EXEC sp_attach_db @dbname = 'NorthWind', @filename1 = 'C:\SQL Server 2000 Sample Databases\NORTHWND.MDF', @filename2 = 'C:\SQL Server 2000 Sample Databases\NORTHWND.LDF' Visualmente, abra o SQL Server Managment Studio, clique com o botão direito sobre Databases e selecione a opção Attach, conforme imagem abaixo: Na janela Attach DataBases clique em Add, em seguida localize e selecione o arquivo Northwind.mdf em seu computador, clique em Ok e emseguida clique em Ok novamente. O banco de dados deverá ser anexado e desta forma estará pronto para uso. Principais Namespaces e Classes do ADO.NET Veremos agora as principais Namespaces e Classes que iremos utilizar durante o nosso curso. As classes necessárias estarão nos Namespaces System.Data e 124 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores System.Data.SQLClient. Os Namespaces devem ser importados, como primeiro item em nosso arquivo de código de servidor, veja os exemplos abaixo: Imports System.data Imports System.Data.SqlClient Partial Class _Default Inherits System.Web.UI.Page End Class using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Data; using System.Data.SqlClient; public partial class Default2 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } } Observe que nos dois exemplos adicionamos apenas duas linhas de código, a diferença está no fato de que no C#, por padrão, diversos outros Namespaces são importados, o que no VB se dá implicitamente. Veremos agora as principais classes que iremos utilizar durante o nosso curso: • SqlConnection: Abre e mantém uma conexão com um gerenciador de banco de dados SQL Server; • SqlCommand: Permite a execução de comandos SQL contra um banco de dados SQL Server; • SqlParameter: Permite a atribuição de parâmetros para comandos SQL para SQL Server; 125 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores • SqlTransaction: Permite a criação e o gerenciamento de transações em banco de dados SQL Server; • SqlDataReader: Permite a recuperação de um conjunto de dados de um banco de dados SQL Server, que estará disponível somente para leitura e pode ser percorrido de forma unidirecional; • DataSet: Permite o armazenamento em memória de um conjunto de dados. Independe da fonte de dados (não necessariamente SQL Server) e não requer conexão com o sistema gerenciador de banco de dados; • DataTable: Permite o armazenamento em memória de um tabela de dados. Independe da fonte de dados (não necessariamente SQL Server) e não requer conexão com o sistema gerenciador de banco de dados. A classe SQLConnection A classe SQLConnection nos permite estabelecer uma conexão com um sistema gerenciador de banco de dados SQL Server. É um objeto fundamental, pois sem uma conexão estabelecida não podemos realizar qualquer operação na base de dados. Primeiramente devemos instanciar um objeto, informar a fonte de dados, abrir a conexão e depois de sua utilização encerrá-la. Para que a conexão seja aberta, algumas informações são fundamentais, sendo elas: a fonte de dados (Servidor SQL Server), o banco de dados a qual queremos nos conectar, o usuário e a senha de conexão. Tais informações devem ser atribuídas na forma de uma string em uma propriedade do objeto de conexão: a string de conexão. Veja abaixo um exemplo em que a conexão é instanciada, a string de conexão é atribuída e posteriormente a conexão é aberta: 'Instância um objeto SqlConnection Dim Conexao As New SqlConnection 'Define a string de conexão Conexao.ConnectionString = "Data Source=FERNANDO\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456" 'Abre a conexão Conexao.Open() 'Encerra a conexão Conexao.Close() 126 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores //Instância um objeto SqlConnection SqlConnection Conexao = new SqlConnection(); //Define a string de conexão Conexao.ConnectionString = "Data Source= FERNANDO \\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456"; //Abre a conexão Conexao.Open(); //Encerra a conexão Conexao.Close(); Observe os elementos que formam a nossa string de conexão: • Data Souce: Define a fonte de dados, ou seja, o servidor SQL Server; • Initial Catalog: Define o banco de dados em que a conexão deve ser realizada; • User ID: Nome do usuário com que deve ser estabelecida a conexão; • Password: Senha do Usuário; Se tudo ocorrer bem não vai acontecer nada na execução do código, pois apenas abrimos e fechamos uma conexão. Porém, se algo der errado, você vai receber um erro de conexão, como o da imagem abaixo: 127 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Neste caso revise as informações em sua string de conexão. É importante salientar também que o SQL Server por padrão não permite conexões remotas. Se você está tentando conexão com o usuário Sa, como no meu exemplo, lembre-se que por padrão este usuário também tem o login desabilitado. Antes de continuarmos, algumas considerações sobre segurança. Em meu exemplo estou utilizando o usuário Sa para conexão. Este é um usuário com privilégios de super administrador e não deve jamais ser utilizado em uma aplicação de produção. Em um curso, porém, seu uso é mais prático, já que não precisamos criar um usuário específico para o mesmo tampouco temos que lidar com eventuais problemas de permissão de acesso. Também é preciso tomar cuidado para não utilizarmos para testes um servidor onde rode uma aplicação de produção, independente do tipo de usuário que iremos nos conectar. Isto é para evitarmos acidentalmente causar danos a informações ou mesmo degradar a performance de aplicações “vivas”. Uma última observação: no primeiro curso aprendemos a tratar erros através de blocos try...catch. A abertura de uma conexão e outras operações em banco de dados são exemplos clássicos de situações em que devemos prever erros em nosso código, afinal o servidor de banco de dados pode ter caído, estar sobrecarregado, simplesmente não existir ou outra situação, dentre infinitas possibilidades. Porém, a fim de clareza, todo o código escrito neste curso, salvo algumas exceções, será apresentado sem os blocos de tratamento de erros. Ao escrever aplicações para a vida real não se esqueça de incluí-los em seu código. Voltando ao objeto SQLConnection, uma propriedade bastante útil é a State, que nos permite verificar a situação da conexão. Por exemplo: antes de uma operação importante você pode querer através de uma estrutura if certificar-se de que a conexão continua aberta. A propriedade State é um enumerador que pode ter os seguintes valores: • Broken: A conexão foi aberta, porém por algum motivo foi quebrada. Deve- se fechar a conexão e abri-la novamente; • Closed: A conexão se encontra encerrada; • Open: A conexão está aberta. Outros valores são possíveis, porém reservados para versões futuras e no momento não nos interessam. Veja abaixo uma nova versão do código de conexão 128 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores anterior. Neste exemplo, um bloco Select/switch verifica o estado da conexão: se a mesma foi quebrada, fecha e reabre a mesma, se estiver fechada, abre. Note que se a conexão já estiver aberta não há nada a ser feito, pois a mesma já está pronta para o uso: 'Instância um objeto SqlConnection Dim Conexao As New SqlConnection("Data Source=FERNANDO\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456") 'Abre a conexão Select Case Conexao.State Case ConnectionState.Broken Conexao.Close() Conexao.Open() Case ConnectionState.Closed Conexao.Open() End Select 'Encerra a conexão Conexao.Close() //Instância um objeto SqlConnectionSqlConnection Conexao = new SqlConnection("Data Source=FERNANDO \\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456"); //Abre a conexão switch (Conexao.State) { case ConnectionState.Broken: Conexao.Close(); Conexao.Open(); break; case ConnectionState.Closed: Conexao.Open(); break; } //Encerra a conexão Conexao.Close(); Outra diferença nesta segunda versão é que a string de conexão foi passada como uma parâmetro através de uma sobrecarga do construtor da classe SQLConnection ao invés de ser atribuído pela propriedade. O resultado prático é o mesmo. 129 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores A classe SQLCommand SQLCommand é outra classe fundamental no acesso a dados, através dele podemos executar um comando SQL em um banco de dados SQL Server. Os elementos mínimos para a sua utilização são: definir a conexão, o comando SQL e execução de fato do comando. Veja o primeiro exemplo abaixo: 'Instância um objeto SqlConnection Dim Conexao As New SqlConnection("Data Source=FERNANDO\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456") 'Abre a conexão Conexao.Open() 'Instância um objeto SqlCommand Dim comando As New SqlCommand 'Define a conexão do comando comando.Connection = Conexao 'Define a instrução SQL comando.CommandText = "INSERT INTO REGION(REGIONID,REGIONDESCRIPTION) VALUES (6,'Other')" 'Executa o comando comando.ExecuteNonQuery() 'Encerra a conexão Conexao.Close() //Instância um objeto SqlConnection SqlConnection Conexao = new SqlConnection("Data Source=FERNANDO\\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456"); //Abre a conexão Conexao.Open(); //Instância um objeto SqlCommand SqlCommand comando = new SqlCommand(); //Define a conexão do comando comando.Connection = Conexao; //Define a instrução SQL comando.CommandText = "INSERT INTO REGION(REGIONID,REGIONDESCRIPTION) VALUES (6,'Other')"; //Executa o comando comando.ExecuteNonQuery(); //Encerra a conexão Conexao.Close(); 130 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores A criação da instância da classe SqlConnection já é conhecida. Observe que o código acima instancia um objeto SqlCommand, atribui um objeto SqlConnection a propriedade Connection, define uma instrução SQL através da propriedade CommandText e finalmente executa o comando através do método ExecuteNonQuery. A Instrução SQL é um comando Insert bem simples. Note que se você executar o código mais de uma vez terá um erro de violação de chave primária, a não ser que altere REGIONID para um valor diferente de 6. O mais importante no código é o método de execução. Existem diversos métodos de execução na classe SqlCommand, cada um com um propósito diferente, vamos estudá-los: • ExecuteNonQuery: Executa o comando e retorna o número de linhas que foram afetadas pelo comando. Por exemplo, caso seja uma comando SQL Delete, o método retorna o número de linhas que foram excluídas. Ideal para execução de comandos SQL que não retornam um conjunto de resultados, como instruções INSERT, UPDATE e DELETE. • ExecuteReader: Executa um comando SQL, instancia e retorna um objeto SQLDataReader. O Objeto SQLDataReader é capaz de receber um conjunto de registros, de leitura unidirecional e somente leitura. Vamos estudar a classe SqlDataReader na próxima seção. • ExecuteScalar: Executa um comando SQL e retorna apenas o valor da primeira coluna da primeira linha do resultado. Um exemplo de seu uso é em instruções escalares, como COUNT, SUM ou AVG. A classe SQLDataReader A classe SQLDataReader é capaz de receber um conjunto de registros, de leitura unidirecional e somente leitura. É instanciada através do método ExecuteReader de um objeto do tipo SqlCommand, o que na prática significa que a mesma deve ser apenas declarada, e não instanciada em nosso código, já que a instância é criada pelo método. Leitura unidirecional quer dizer que o conjunto de registros só pode ser percorrido em uma direção: para frente. Somente leitura significa que não podemos alterar os dados 131 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores recuperados. Outra característica desta classe é que o objeto requer acesso exclusivo à conexão durante a recuperação de dados. As características desta classe a tornam ideal para leitura de dados que não necessitam de alteração, já que as suas características de direção única e somente leitura fazem com que a recuperação dos dados seja extremamente rápida. Se os últimos parágrafos pareceram um pouco complicados, o exemplo a seguir vai ajudar a esclarecer. Antes de digitar o código, adicione um controle ListBox à sua página: 'Instância um objeto SqlConnection Dim Conexao As New SqlConnection("Data Source=FERNANDO\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456") 'Abre a conexão Conexao.Open() 'Instância um objeto SqlCommand Dim comando As New SqlCommand Atribui a conexão do comando comando.Connection = Conexao 'Define a instrução SQL comando.CommandText = "SELECT ShipperID,CompanyName FROM SHIPPERS" 'Instância um objeto SQLDataReader Dim SqlReader As SqlDataReader = comando.ExecuteReader 'Atribui o SqlReader a um controle visual With ListBox1 .DataSource = sqlreader .DataTextField = "CompanyName" .DataValueField = "ShipperID" .DataBind() End With 'Encerra a conexão Conexao.Close() //Instância um objeto SqlConnection SqlConnection Conexao = new SqlConnection("Data Source= FERNANDO \\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456"); //Abre a conexão Conexao.Open(); //Instância um objeto SqlCommand SqlCommand comando = new SqlCommand(); //Atribui a conexão do comando comando.Connection = Conexao; //Define a instrução SQL comando.CommandText = "SELECT ShipperID,CompanyName FROM SHIPPERS"; 132 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores //Instância um objeto SQLDataReader SqlDataReader SqlReader = comando.ExecuteReader(); //Atribui o SqlReader a um controle visual ListBox1.DataSource = SqlReader; ListBox1.DataTextField = "CompanyName"; ListBox1.DataValueField = "ShipperID"; ListBox1.DataBind(); //Encerra a conexão Conexao.Close(); Note que a declaração do SQLDataReader é feita sem a palavra New, já que a instância da classe é criada pelo método ExecuteReader do objeto comando. Associamos então o objeto SqlReader a um objeto ListBox através de sua propriedade DataSource. Em seguida definimos os valores para as propriedades DataTextField e DataValueField com os campos incluídos em nossa instrução SQL. Finalmente, o método DataBind traz o conjunto de registros ao controle: 133 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Outro problema comum que podemos encontrar é ter de percorrer registros de uma tabela, um a um. A classe SqlDataReader permite isso através do método read, que, a cada execução, avança um registro do conjunto de resultados, enquanto houverem registros. No exemplo abaixo percorremos a tabela de detalhes de pedidos e realizamos a soma do campo quantidade: 'Instância um objeto SqlConnection Dim Conexao As New SqlConnection("Data Source=FERNANDO\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456") 'Abre a conexão Conexao.Open() 'Instância um objeto SqlCommand Dim comando As New SqlCommand 'Define a conexão do comando comando.Connection= Conexao 'Define a instrução SQL comando.CommandText = "SELECT Quantity FROM [Order Details]" 'Instância um objeto SQLDataReader Dim SqlReader As SqlDataReader = comando.ExecuteReader 'Cria variável para leitura Dim Total As Integer 'Percorre os registros somando o total While SqlReader.Read Total += SqlReader(0) End While 'Encerra a conexão Conexao.Close() //Instância um objeto SqlConnection SqlConnection Conexao = new SqlConnection("Data Source=FERNANDO\\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456"); //Abre a conexão Conexao.Open(); //Instância um objeto SqlCommand SqlCommand comando = new SqlCommand(); //Define a conexão do comando comando.Connection = Conexao; //Define a instrução SQL comando.CommandText = "SELECT Quantity FROM [Order Details]"; //Instância um objeto SQLDataReader SqlDataReader SqlReader = comando.ExecuteReader(); //Cria variável para leitura int Total = 0; 134 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores //Percorre os registros somando o total while (SqlReader.Read()) { Total += Convert.ToInt32(SqlReader[0]); } //Encerra a conexão Conexao.Close(); O resultado na variável Total ao final do laço deve ser o mesmo se executada uma instrução SQL de soma dos valores do campo Quantity. Observe que a leitura do campo se dá através do índice do mesmo na instrução SQL, que no exemplo é zero. Existe uma sobrecarga que permite a leitura pelo nome do campo, obviamente que neste caso o mesmo deverá ser informado entre aspas. Classe SqlParameter Normalmente, a formação de um comando SQL se dará de forma dinâmica. Por exemplo, a instrução SQL abaixo retorna o último nome do empregado de código 1: SELECT LASTNAME FROM EMPLOYEES WHERE EMPLOYEEID = '1' Porém, podemos necessitar definir dinamicamente o código do empregado que queremos retornar, através de um valor informado em uma página, por exemplo, e assim definir a instrução SQL dinamicamente. À primeira vista, uma forma simples de resolver este problema poderia ser algo como no fragmento de código abaixo: comando.CommandText = "SELECT LASTNAME FROM EMPLOYEES WHERE EMPLOYEEID = " & TextBox1.Text comando.CommandText = "SELECT LASTNAME FROM EMPLOYEES WHERE EMPLOYEEID = " + TextBox1.Text; 135 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores A ideia é simples: a instrução SQL é montada concatenada à propriedade CommandText. O exemplo funciona, seu grande problema é relacionado à segurança. Tal comando pode causar uma das falhas mais comuns e exploradas em aplicações: Injeção de SQL. O que aconteceria se, no TextBox, ao invés de digitar o código do empregado, você digitasse o texto abaixo: '1'; DELETE FROM CUSTOMERDEMOGRAPHICS Simples, todos os itens da tabela CustomerDemographics serão apagados. O uso de objetos de parâmetros, como o SqlParameter, torna a programação um pouco mais difícil, pois requer mais linhas de código, mas com certeza torna a programação mais elegante, e, acima de tudo, muito mais segura. O processo do uso da classe SqlParameter inicia com a instância de um objeto, definição de propriedades, como nome da parâmetro, tipo de dado e valor e finalmente o parâmetro é adicionado a coleção de parâmetros do objeto SqlCommand através do método Add. Na instrução Sql, os parâmetros devem ter o nome composto pelo prefixo @ e devem coincidir com o nome atribuído ao objeto SqlParameter. Vejamos um exemplo: 'Instância um objeto SqlConnection Dim Conexao As New SqlConnection("Data Source=FERNANDO\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456") 'Abre a conexão Conexao.Open() 'Instância um objeto SqlCommand Dim comando As New SqlCommand 'Define a conexão do comando comando.Connection = Conexao 'Define a instrução SQL comando.CommandText = "SELECT LASTNAME FROM EMPLOYEES WHERE EMPLOYEEID = @EMPLOYEEID" 'Instância um objeto SqlParameter Dim Parametro As New SqlParameter 'Atribui os dados necessários ao parametro Parametro.ParameterName = "@EMPLOYEEID" Parametro.SqlDbType = SqlDbType.VarChar Parametro.Value = TextBox1.Text 136 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores 'Adiciona o parametro ao SqlCommand comando.Parameters.Add(Parametro) 'Atribui o sobrenome a uma variável Dim sobrenome As String = comando.ExecuteScalar //Instância um objeto SqlConnection SqlConnection Conexao = new SqlConnection("Data Source= FERNANDO \\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456"); //Abre a conexão Conexao.Open(); //Instância um objeto SqlCommand SqlCommand comando = new SqlCommand(); //Define a conexão do comando comando.Connection = Conexao; //Define a instrução SQL comando.CommandText = "SELECT LASTNAME FROM EMPLOYEES WHERE EMPLOYEEID = @EMPLOYEEID"; //Instância um objeto SqlParameter SqlParameter Parametro = new SqlParameter(); //Atribui os dados necessários ao parametro Parametro.ParameterName = "@EMPLOYEEID"; Parametro.SqlDbType = SqlDbType.VarChar; Parametro.Value = TextBox1.Text; //Adiciona o parametro ao SqlCommand comando.Parameters.Add(Parametro); //Atribui o sobrenome a uma variável String sobrenome = Convert.ToString( comando.ExecuteScalar()); Observe que na cláusula where da instrução Sql, Employeeid deverá receber seus valores através de uma variável, no nosso exemplo fornecido através de um parâmetro. Em seguida instanciamos um objeto do tipo SqlParameter, definimos seu nome – que deve ser igual ao nome da variável da instrução SQL – seu tipo, através do enumerador SqlDbType, e finalmente seu valor, onde o código mostra que virá da propriedade Text do controle TextBox1. Ao executar este exemplo, experimente preencher o valor do TextBox1 com o exemplo de Sql Injection que testamos anteriormente: O ASP.NET exibe uma mensagem de erro ao invés de apagar todos os itens da tabela CUSTOMERDEMOGRAPHICS. Se sua instrução Sql tem mais de um 137 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores parâmetro, basta instanciar quantos objetos SqlParameter forem necessários, sem esquecer de adicioná-los à coleção de parâmetros da instância de seu SqlCommand. Classe SqlTransaction Quando trabalhamos com aplicações que envolvem o acesso a dados, é comum necessitarmos tratar um conjunto de operações de forma única. Por um conjunto de operações se entende a execução de diversos comandos em uma ou mais fontes de dados, comandos estes que podem ser instruções de exclusão, alteração, inclusão. O exemplo clássico que a literatura usa para entendermos na prática o conceito de transações é o da movimentação bancária: você vai transferir um montante de sua conta para um terceiro. Tecnicamente falando, isto implica em diversas operações em banco de dados, mas basicamente um valor é debitado de uma conta e creditado em outra. Se por acaso ocorrer alguma falha no sistema entre o crédito e o débito, e sabemos que sistemas falham, o montante que deveria ser transferido simplesmente deixará de existir. Transações garantem a atomicidade da operação: se após o débito algo der errado, a operação é desfeita e a integridade das informações é mantida. Um exemplo comum do uso de transações é entre blocos protegidos try.catch, conforme estudamos no primeiro curso. Se a execução do código entrar no bloco catch, significa que ocorreu um erro e a transação deve ser desfeita, caso contrário, a transação ocorreu com sucesso e pode ser confirmada. No exemplo abaixo, o objetivo é inserirum registro na tabela Region e em seguida um registro na tabela Territories. Um dos valores incluídos na tabela Territories é uma chave estrangeira para o registro da tabela Region que acabou de ser inserido no mesmo bloco de código. Porém, caso haja algo de errado na inserção em Territories, queremos que a inclusão de Region, que já foi executada, seja desfeita. Como a instrução Sql de inserção da tabela Territories vai causar uma violação de chave primária, já que já existe no banco de dados um território cuja a chave primária é 85014, a segunda inserção vai causar uma exceção de banco de dados e será executado o código de rollback dentro do bloco catch. Como a inserção na tabela Region 138 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores está utilizando a mesma transação, a inclusão da Região será desfeita. Você pode confirmar isto fazendo uma consulta diretamente no banco de dados através do Sql Server Mangment Studio, por exemplo. 'Instância um objeto SqlConnection Dim Conexao As New SqlConnection("Data Source=FERNANDO\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456") 'Abre a conexão Conexao.Open() 'Instancia um objeto SqlCommand Dim comando As New SqlCommand 'Define o comando Sql comando.CommandText = "INSERT INTO REGION (REGIONID,REGIONDESCRIPTION) VALUES(10,'North')" 'Define a conexão comando.Connection = Conexao 'Instância um objeto SqlTransaction Dim Transacao As SqlTransaction = Conexao.BeginTransaction 'Atribui o objeto SqlTransaction ao comando comando.Transaction = Transacao 'Inclui a Região, até aqui não deve ocorrer erro comando.ExecuteNonQuery() 'Prepara o comando para inserir o território comando.CommandText = "INSERT INTO TERRITORIES (TERRITORYID,TERRITORYDESCRIPTION,REGIONID) VALUES ('85014','Phoenix',10)" Try 'Executa a inserção do território 'Deve ocorrer erro porque a instrução Sql causa uma violação de Chave Primária comando.ExecuteNonQuery() Catch ex As Exception 'Desfaz a transação Transacao.Rollback() Exit Sub End Try 'Confirma a transação, este código não deve ser executado Transacao.Commit() 'Encerra a conexão Conexao.Close() 139 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores //Instância um objeto SqlConnection SqlConnection Conexao = new SqlConnection("Data Source= FERNANDO \\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456"); //Abre a conexão Conexao.Open(); //Instancia um objeto SqlCommand SqlCommand comando = new SqlCommand(); //Define o comando Sql comando.CommandText = "INSERT INTO REGION (REGIONID,REGIONDESCRIPTION) VALUES(10,//North//)"; //Define a conexão comando.Connection = Conexao; //Instância um objeto SqlTransaction SqlTransaction Transacao = Conexao.BeginTransaction(); //Atribui o objeto SqlTransaction ao comando comando.Transaction = Transacao; //Inclui a Região, até aqui não deve ocorrer erro comando.ExecuteNonQuery(); //Prepara o comando para inserir o território comando.CommandText = "INSERT INTO TERRITORIES (TERRITORYID,TERRITORYDESCRIPTION,REGIONID) VALUES ('85014','Phoenix',10)"; try { //Executa a inserção do território //Deve ocorrer erro porque a instrução Sql causa uma //violação de Chave Primária comando.ExecuteNonQuery(); } catch { //Desfaz a transação Transacao.Rollback(); return; } //Confirma a transação, este código não deve ser executado Transacao.Commit(); //Encerra a conexão Conexao.Close(); 140 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Para ver a transação ser confirmada e as duas inserções serem efetivadas, basta alterar o valor para o campo TerritoryID no Sql de inserção a fim de que não cause a violação de chave primária. Classes DataSet e DataTable Todas as classes relacionadas a dados que estudamos até aqui possuem o prefixo SQL. Isto se deve ao fato de que são classes desenvolvidas para o sistema gerenciador de banco de dados Sql Server. As principais classes que veremos nesta sessão são independentes da fonte de dados, e por isso se chamam DataSet e DataTable. Um Dataset pode armazenar um conjunto de dados das mais diversas fontes: posso ter uma tabela oriunda de um arquivo Accesss, outra de Oracle e uma terceira de Sql Server: todas juntas e interoperáveis, como se fosse um único banco de dados. E é exatamente esta a ideia de um DataSet: um banco de dados em memória. O DataSet não mantém conexão com sua fonte de dados: fazemos a recuperação dos dados, adicionamos ao DataSet, os dados são alterados em memória e depois, se necessários, as alterações são executadas contra a fonte de dados original. Durante este processo, não é necessária que a conexão de dados seja aberta: o dataset sequer sabe qual a origem de dados, já que os mesmos chegam até ele em um formato universal. Porém, como o formato dos dados no DataSet é universal, é preciso que ocorra uma transformação do formato específico da fonte de dados para esse formato padrão. Quando a fonte de dados é Sql Server, isto é feito através da classe SqlDataAdapter. Dim conexao As New SqlConnection 'Instância um objeto SqlConnection Dim Conexao As New SqlConnection("Data Source=FERNANDO\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456") 'Abre a conexão Conexao.Open() 'Prepara um comando Dim comando As New SqlCommand comando.Connection = conexao comando.CommandText = "SELECT REGIONID,REGIONDESCRIPTION FROM REGION" 'Instãncia um SqlDataAdapter 141 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Dim Adaptador As New SqlDataAdapter Adaptador.SelectCommand = comando 'Instância um DataSet Dim DataSet As New DataSet 'O método Fill do SqlDataAdapter popula o DataSet com os Registros 'de acordo com a instrução Sql do SqlCommand Adaptador.Fill(DataSet) 'A conexão não é mais necessária conexao.Close() 'Vinculamos o DataSet ao ListBox With ListBox1 .DataSource = DataSet .DataValueField = "REGIONID" .DataTextField = "REGIONDESCRIPTION" .DataBind() End With //Instância um objeto SqlConnection SqlConnection Conexao = new SqlConnection("Data Source= FERNANDO \\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456"); //Abre a conexão Conexao.Open(); //Prepara um comando SqlCommand comando = new SqlCommand(); comando.Connection = conexao; comando.CommandText = "SELECT REGIONID,REGIONDESCRIPTION FROM REGION"; //Instãncia um SqlDataAdapter SqlDataAdapter Adaptador = new SqlDataAdapter(); Adaptador.SelectCommand = comando; //Instância um DataSet DataSet DataSet = new DataSet(); //O método Fill do SqlDataAdapter popula o DataSet com os Registros //de acordo com a instrução Sql do SqlCommand Adaptador.Fill(DataSet); //A conexão não é mais necessária conexao.Close(); //Vinculamos o DataSet ao ListBox ListBox1.DataSource = DataSet; ListBox1.DataValueField = "REGIONID"; ListBox1.DataTextField = "REGIONDESCRIPTION"; ListBox1.DataBind(); O código acima apenas recupera e listas dados. Seria mais eficiente com a utilização de um SqlDataReader, lembrando que em seção anterior falamos que o SqlDataReader é um cursor somente leitura e unidirecional, portanto muito mais veloz. 142 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Vamos ver como podemos usar as classes DataSet e DataTable para a manipulação de dados. Note que no modelo acima fornecemos um comando de seleção. Se vamos, por exemplo,incluir dados, teremos também que fornecer uma instrução Sql de inclusão através da propriedade InsertCommand do SqlDataAdapter. Alternativamente, podemos utilizar a classe SqlCommandBuilder para que as instruções Sql de Inserção, Exclusão e Alteração sejam criadas automaticamente para o SqlDataAdapter. Para isto dar certo, é necessário que a instrução Sql de Seleção fornecida contenha a chave primária da tabela. No exemplo a seguir, incluímos um registro na tabela Regions. Note que utilizamos um objeto DataTable ao invés de um DataSet, algo totalmente possível pois estamos trabalhando com uma única tabela. Observe também o uso de um objeto DataRow, objeto este que representa uma linha da tabela. Depois de definirmos o valor para a linha, adicionamos à linha a tabela e atualizamos a fonte de dados. Outra observação importante no código é que não há abertura ou fechamento explícito da conexão com o banco de dados. Isto é possível porque o SqlDataAdapter faz o gerenciamento automático da conexão: se encontrar a mesma aberta, utiliza e a mantém aberta, porém, caso encontre a conexão fechada, faz a abertura e ao final fecha a conexão. Dim conexao As New SqlConnection 'Instância um objeto SqlConnection Dim Conexao As New SqlConnection("Data Source=FERNANDO\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456") 'Prepara um comando Dim comando As New SqlCommand comando.Connection = conexao comando.CommandText = "SELECT REGIONID,REGIONDESCRIPTION FROM REGION" 'Instãncia um SqlDataAdapter Dim Adaptador As New SqlDataAdapter Adaptador.SelectCommand = comando 'Instância um objeto SqlCommandBuilder Dim Builder As New SqlCommandBuilder 'Define o SqlAdatpter Builder.DataAdapter = Adaptador 'Instância um Datatable Dim Tabela As New DataTable 'O método Fill do SqlDataAdapter popula a tabela com os Registros 'de acordo com a instrução Sql do SqlCommand 143 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Adaptador.Fill(Tabela) 'Instância um objeto DataRow Dim Linha As DataRow = Tabela.NewRow 'Define os valores para a linha a ser incluida Linha("REGIONID") = 20 Linha("REGIONDESCRIPTION") = "New Orleans" 'Adiciona a linha a tabela 'Esta operação ainda está em memória Tabela.Rows.Add(Linha) 'Atualiza a tabela de dados no Sql Server Adaptador.Update(Tabela) //Instância um objeto SqlConnection SqlConnection Conexao = new SqlConnection("Data Source= FERNANDO \\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456"); //Abre a conexão Conexao.Open(); //Prepara um comando SqlCommand comando = new SqlCommand(); comando.Connection = conexao; comando.CommandText = "SELECT REGIONID,REGIONDESCRIPTION FROM REGION"; //Instãncia um SqlDataAdapter SqlDataAdapter Adaptador = new SqlDataAdapter(); Adaptador.SelectCommand = comando; //Instância um objeto SqlCommandBuilder SqlCommandBuilder Builder = new SqlCommandBuilder(); //Define o SqlAdatpter Builder.DataAdapter = Adaptador; //Instância um Datatable DataTable Tabela = new DataTable(); //O método Fill do SqlDataAdapter popula a tabela com os Registros //de acordo com a instrução Sql do SqlCommand Adaptador.Fill(Tabela); //Instância um objeto DataRow DataRow Linha = Tabela.NewRow(); //Define os valores para a linha a ser incluida Linha["REGIONID"] = 20; Linha["REGIONDESCRIPTION"]= "new Orleans"; //Adiciona a linha a tabela //Esta operação ainda está em memória Tabela.Rows.Add(Linha); //Atualiza a tabela de dados no Sql Server Adaptador.Update(Tabela); 144 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Juntando Tudo Nesta seção vamos criar uma pequena aplicação, de uma única página, que utiliza a maioria dos recursos de programação que estudamos até aqui. Antes, porém, uma observação sobre a string de conexão. Em todos os exemplos até aqui definimos nossa string de conexão junto com nosso código, ou seja, dentro dos arquivos vb e cs. Isto, na vida real nos trará dois problemas: primeiro que as informações de conexão são muito dinâmicas. Quando seu sistema entrar em produção elas terão que ser alteradas, quando seu sistema gerenciador de banco de dados mudar elas terão que ser alteradas e assim por diante. O segundo problema é que normalmente abrimos conexões em diversos pontos da aplicação. Ficaria muito difícil gerenciar dezenas, centenas ou até milhares de strings de conexão espalhadas no seu código fonte. O ASP.NET resolve isso permitindo que você defina uma ou mais strings de conexão em seu arquivo de configuração da aplicação, o web.config. Desta forma você tem as suas informações de conexão centralizadas: será necessária a alteração em um único lugar. Também você não vai precisar alterar seu código fonte para mudar sua fonte de dados. Vamos ver como isso pode ser feito: Primeiro adicionamos a string de conexão ao web.config: <connectionStrings> <add name="NorthWindConnectionString" connectionString="Data Source=FERNANDO\SQLEXPRESS;Initial Catalog=NorthWind;User ID=sa;Password=123456" providerName="System.Data.SqlClient"/> </connectionStrings> No meu web.config ela foi colocada logo após o elemento <appSettings/>. Entre os atributos, temos name, que dá um nome único para a string, isso é útil especialmente se você tem mais de uma fonte de dados e necessita de mais de uma string de conexão. O segundo atributo, connectionString, é a string de conexão propriamente dita, semelhante a que utilizamos em nosso código fonte nas seções anteriores. Finalmente, o último elemento define o provedor de acesso a dados, que para Sql Server é o SqlClient. 145 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores A próxima etapa é como atribuir nossa string de conexão às nossas instâncias das classes SqlConnection. Isso pode ser feito através do método ConnectionStrings da classe ConfigurationManager. O método deve receber como parâmetro o nome da string de conexão, conforme definido no web.config, que no nosso exemplo nomeamos como NorthWindConnectionString. Veja os exemplos: 'Instância um objeto SqlConnection Dim Conexao As New SqlConnection 'Define a string de conexão Conexao.ConnectionString = ConfigurationManager.ConnectionStrings("NorthWindConnectionString").Conne ctionString 'Abre a conexão Conexao.Open() //Define a string de conexão SqlConnection conexao = new SqlConnection(); //Define a string de conexão conexao.ConnectionString = ConfigurationManager.ConnectionStrings["NorthWindConnectionString"].Conne ctionString; conexao.Open(); Agora voltamos ao exemplo. O objetivo é permitir exibir, incluir e excluir registros da tabela Region do banco de dados NorthWind. Para isso, monte uma página semelhante ao modelo a seguir: 146 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Inicialmente devemos incluir as cláusulas Imports/using no topo de nosso arquivo de código: Imports System.Data.SqlClient Imports System.Data using System.Data.SqlClient; Dentro da classe vamos declarar duas variáveis privadas, uma para conexão e outra para execução de comandos. Faremos desta forma para que possamos aproveitar as variáveis no restante da página: Private Conexao As New SqlConnection Private Comando As New SqlCommand private SqlConnection Conexao = new SqlConnection(); private SqlCommand Comando = new SqlCommand(); 147 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aosseus respectivos autores Criamos então um procedimento RecuperaRegioes, que tem por objetivo recuperar os registros da tabela regiões. A criação deste procedimento separado permite que a listagem de regiões seja atualizada quando um registro é incluído ou excluído: Private Sub RecuperaRegioes() Conexao.Open() 'Define a instrução Sql Comando.CommandText = "SELECT REGIONID,REGIONDESCRIPTION FROM REGION" 'Instância um SqlDataReader Dim DataReader As SqlDataReader = Comando.ExecuteReader 'Popula o ListBox With ListBox1 .DataTextField = "REGIONDESCRIPTION" .DataValueField = "REGIONID" .DataSource = DataReader .DataBind() End With 'Fecha a conexão Conexao.Close() End Sub private void RecuperaRegioes() { Conexao.Open(); //Define a instrução Sql comando.CommandText = "SELECT REGIONID,REGIONDESCRIPTION FROM REGION"; //Instância um SqlDataReader SqlDataReader DataReader = comando.ExecuteReader(); //Popula o ListBox { ListBox1.DataTextField = "REGIONDESCRIPTION"; ListBox1.DataValueField = "REGIONID"; ListBox1.DataSource = DataReader; ListBox1.DataBind(); } //Fecha a conexão Conexao.Close(); } O botão de exclusão tem uma instrução Sql Delete, que recebe como parâmetro a chave do registro da tabela Region que está sendo excluída. Note que no bloco de código em que populamos o ListBox, a chave da tabela foi adicionada à propriedade DataValueField. 148 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles ButtonExcluir.Click Conexao.Open() 'Define a instrução Sql Comando.CommandText = "DELETE FROM REGION WHERE REGIONID = @REGIONID" 'Instância e define o parametro Dim Parametro As New SqlParameter Parametro.ParameterName = "@REGIONID" Parametro.SqlDbType = SqlDbType.Int 'O valor para o parametro vem da propriedade SelectedValue do ListBox 'Que foi populada com a chave da tabela Parametro.Value = ListBox1.SelectedValue Comando.Parameters.Add(Parametro) Comando.ExecuteNonQuery() Conexao.Close() 'Atualiza a lista de regiões, sem o registro excluido RecuperaRegioes() End Sub protected void Button1_Click(object sender, EventArgs e) { Conexao.Open(); //Define a instrução Sql comando.CommandText = "DELETE FROM REGION WHERE REGIONID = @REGIONID"; //Instância e define o parametro SqlParameter Parametro = new SqlParameter(); Parametro.ParameterName = "@REGIONID"; Parametro.SqlDbType = SqlDbType.Int; //O valor para o parametro vem da propriedade SelectedValue do ListBox //Que foi populada com a chave da tabela Parametro.Value = ListBox1.SelectedValue; comando.Parameters.Add(Parametro); comando.ExecuteNonQuery(); Conexao.Close(); //Atualiza a lista de regiões, sem o registro excluido RecuperaRegioes(); } O botão de inclusão não tem surpresas, exceto pelo fato de utilizarmos duas instâncias da classe SqlParameter, uma para cada parâmetro da instrução: Protected Sub Button3_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button3.Click 149 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Conexao.Open() 'Define a instrução Sql Comando.CommandText = "INSERT INTO REGION (REGIONID,REGIONDESCRIPTION) VALUES (@REGIONID,@REGIONDESCRIPTION)" 'Primeiro Parâmetro Dim Parametro As New SqlParameter Parametro.ParameterName = "@REGIONID" Parametro.SqlDbType = SqlDbType.Int Parametro.Value = TextBoxCodigo.Text Comando.Parameters.Add(Parametro) 'Segundo Parâmetro Dim Parametro2 As New SqlParameter Parametro2.ParameterName = "@REGIONDESCRIPTION" Parametro2.SqlDbType = SqlDbType.VarChar Parametro2.Value = TextBoxRegiao.Text Comando.Parameters.Add(Parametro2) Comando.ExecuteNonQuery() Conexao.Close() 'Atualiza a lista de regiões, com o registro incluido RecuperaRegioes() End Sub protected void Button3_Click(object sender, EventArgs e) { Conexao.Open(); //Define a instrução Sql comando.CommandText = "INSERT INTO REGION (REGIONID,REGIONDESCRIPTION) VALUES (@REGIONID,@REGIONDESCRIPTION)"; //Primeiro Parâmetro SqlParameter Parametro = new SqlParameter(); Parametro.ParameterName = "@REGIONID"; Parametro.SqlDbType = SqlDbType.Int; Parametro.Value = TextBoxCodigo.Text; comando.Parameters.Add(Parametro); //Segundo Parâmetro SqlParameter Parametro2 = new SqlParameter(); Parametro2.ParameterName = "@REGIONDESCRIPTION"; Parametro2.SqlDbType = SqlDbType.VarChar; Parametro2.Value = TextBoxRegiao.Text; comando.Parameters.Add(Parametro2); comando.ExecuteNonQuery(); Conexao.Close(); //Atualiza a lista de regiões, com o registro incluido RecuperaRegioes(); } 150 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Finalmente vamos adicionar algum código ao nosso evento Page Load, com intenção de inicializar a string de conexão e definir a conexão do comando. Também populamos a lista de regiões, porém com um detalhe: esta população deve ser feita apenas na primeira execução da página, por isso a chamada do procedimento dentro de um bloco if. Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 'Define a string de conexão Conexao.ConnectionString = ConfigurationManager.ConnectionStrings("NorthWindConnectionString").Conne ctionString 'Define a conexão do comando Comando.Connection = Conexao 'Se não for um postback, popula o ListBox, caso contrário, 'os eventos de inclusão ou exclusão serão responsáveis pela atualização If Not IsPostBack Then RecuperaRegioes() End If End Sub protected void Page_Load(object sender, EventArgs e) { Conexao.ConnectionString = ConfigurationManager.ConnectionStrings["NorthWindConnectionString"].Conne ctionString; //Define a conexão do comando comando.Connection = Conexao; //Se não for um postback, popula o ListBox, caso contrário, //os eventos de inclusão ou exclusão serão responsáveis pela atualização if (!IsPostBack) { RecuperaRegioes(); } } Se você se perdeu em algum ponto, segue abaixo a listagem de todo o código do arquivo code behind: Imports System.Data.SqlClient Imports System.Data Partial Class Default4 Inherits System.Web.UI.Page Private Conexao As New SqlConnection Private Comando As New SqlCommand 151 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Private Sub RecuperaRegioes() Conexao.Open() 'Define a instrução Sql Comando.CommandText = "SELECT REGIONID,REGIONDESCRIPTION FROM REGION" 'Instância um SqlDataReader Dim DataReader As SqlDataReader = Comando.ExecuteReader 'Popula o ListBox With ListBox1 .DataTextField = "REGIONDESCRIPTION" .DataValueField = "REGIONID" .DataSource = DataReader .DataBind() End With 'Fecha a conexão Conexao.Close() End Sub Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 'Define a string de conexão Conexao.ConnectionString = ConfigurationManager.ConnectionStrings("NorthWindConnectionString").Conne ctionString 'Define a conexão do comando Comando.Connection = Conexao 'Se não for um postback, popula o ListBox, caso contrário, 'os eventos de inclusão ou exclusão serão responsáveis pela atualização If Not IsPostBack Then RecuperaRegioes() End If End Sub Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles ButtonExcluir.Click Conexao.Open() 'Define a instrução Sql Comando.CommandText = "DELETE FROM REGION WHERE REGIONID = @REGIONID" 'Instância e define o parametro Dim Parametro As New SqlParameter Parametro.ParameterName= "@REGIONID" Parametro.SqlDbType = SqlDbType.Int 'O valor para o parametro vem da propriedade SelectedValue do ListBox 'Que foi populada com a chave da tabela Parametro.Value = ListBox1.SelectedValue Comando.Parameters.Add(Parametro) Comando.ExecuteNonQuery() Conexao.Close() 'Atualiza a lista de regiões, sem o registro excluido RecuperaRegioes() End Sub Protected Sub Button3_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button3.Click 152 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Conexao.Open() 'Define a instrução Sql Comando.CommandText = "INSERT INTO REGION (REGIONID,REGIONDESCRIPTION) VALUES (@REGIONID,@REGIONDESCRIPTION)" Dim Parametro As New SqlParameter 'Primeiro Parâmetro Parametro.ParameterName = "@REGIONID" Parametro.SqlDbType = SqlDbType.Int Parametro.Value = TextBoxCodigo.Text Comando.Parameters.Add(Parametro) 'Segundo Parâmetro Dim Parametro2 As New SqlParameter Parametro2.ParameterName = "@REGIONDESCRIPTION" Parametro2.SqlDbType = SqlDbType.VarChar Parametro2.Value = TextBoxRegiao.Text Comando.Parameters.Add(Parametro2) Comando.ExecuteNonQuery() Conexao.Close() 'Atualiza a lista de regiões, com o registro incluido RecuperaRegioes() End Sub End Class using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Data.SqlClient; public partial class Default7 : System.Web.UI.Page { private SqlConnection Conexao = new SqlConnection(); private SqlCommand comando = new SqlCommand(); private void RecuperaRegioes() { Conexao.Open(); //Define a instrução Sql comando.CommandText = "SELECT REGIONID,REGIONDESCRIPTION FROM REGION"; //Instância um SqlDataReader SqlDataReader DataReader = comando.ExecuteReader(); //Popula o ListBox { ListBox1.DataTextField = "REGIONDESCRIPTION"; 153 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores ListBox1.DataValueField = "REGIONID"; ListBox1.DataSource = DataReader; ListBox1.DataBind(); } //Fecha a conexão Conexao.Close(); } protected void Page_Load(object sender, EventArgs e) { Conexao.ConnectionString = ConfigurationManager.ConnectionStrings["NorthWindConnectionString"].Conne ctionString; //Define a conexão do comando comando.Connection = Conexao; //Se não for um postback, popula o ListBox, caso contrário, //os eventos de inclusão ou exclusão serão responsáveis pela atualização if (!IsPostBack) { RecuperaRegioes(); } } protected void Button1_Click(object sender, EventArgs e) { Conexao.Open(); //Define a instrução Sql comando.CommandText = "DELETE FROM REGION WHERE REGIONID = @REGIONID"; //Instância e define o parametro SqlParameter Parametro = new SqlParameter(); Parametro.ParameterName = "@REGIONID"; Parametro.SqlDbType = SqlDbType.Int; //O valor para o parametro vem da propriedade SelectedValue do ListBox //Que foi populada com a chave da tabela Parametro.Value = ListBox1.SelectedValue; comando.Parameters.Add(Parametro); comando.ExecuteNonQuery(); Conexao.Close(); //Atualiza a lista de regiões, sem o registro excluido RecuperaRegioes(); } protected void Button3_Click(object sender, EventArgs e) { Conexao.Open(); //Define a instrução Sql comando.CommandText = "INSERT INTO REGION (REGIONID,REGIONDESCRIPTION) VALUES (@REGIONID,@REGIONDESCRIPTION)"; //Primeiro Parâmetro SqlParameter Parametro = new SqlParameter(); Parametro.ParameterName = "@REGIONID"; Parametro.SqlDbType = SqlDbType.Int; Parametro.Value = TextBoxCodigo.Text; comando.Parameters.Add(Parametro); //Segundo Parâmetro 154 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores SqlParameter Parametro2 = new SqlParameter(); Parametro2.ParameterName = "@REGIONDESCRIPTION"; Parametro2.SqlDbType = SqlDbType.VarChar; Parametro2.Value = TextBoxRegiao.Text; comando.Parameters.Add(Parametro2); comando.ExecuteNonQuery(); Conexao.Close(); //Atualiza a lista de regiões, com o registro incluido RecuperaRegioes(); } } O que mais você pode fazer para aperfeiçoar esta pequena aplicação? Seguem abaixo algumas sugestões: • Validar a entrada de dados de inserção, ou seja, certificar-se que o usuário informou um código e uma região. Validar se o código é inteiro; • Verificar se a inserção não vai causar uma violação de chave primária; • Na exclusão, certificar-se que existe um valor selecionado no ListBox; • Proteger seu código com blocos try.catch onde houver probabilidade maior de ocorrência de erros. Controles Visuais Agora que você passou pelo mais difícil, vem o prêmio: a programação declarativa é mais cansativa, a programação visual é mais divertida e a produtividade é muito superior. Como disse em seção anterior, um bom desenvolvedor tem que obrigatoriamente conhecer os dois modelos de programação. Você verá também que mesmo na programação visual alguns problemas têm que ser resolvidos escrevendo-se código. Os controles visuais estão localizados na guia Data, conforme imagem abaixo: 155 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Não vou explicar cada um dos controles neste momento, já que iremos descobrir alguns deles durante o curso. Antes de entrarmos em nosso primeiro exemplo, vamos falar um pouco da programação para internet antes do ASP.NET. No ASP Clássico, ou mesmo em outras linguagens de programação Web, exibir uma tabela qualquer em uma página de internet era um trabalho grandioso: você teria que criar um recordset, percorrê- lo e simultaneamente criar tags tables, td e tr. Entre o início da programação e a versão final poderiam ir horas ou até mesmo dias. Vamos ver agora que exibir uma tabela em uma página Web pode ser feito rapidamente, sem a digitação de uma única linha de código. Primeiramente crie uma nova aplicação ASP.NET ou adicione um novo Web Form se você já estiver com a aplicação aberta. Localize a guia Data e arraste um controle GridView para seus Web Form. Na Smat Tag do controle, selecione New Data Source em Choose Data Source, como na imagem abaixo: 156 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores É exibida a Janela DataSource Configuration Wizard. Neste assistente será criado um controle SqlDataSource, que nos permite acessar uma base de dados em um servidor Sql Server. Você também poderia arrastar este controle da guia Data e configurá-lo da mesma forma. A diferença é que pela Smart Tag do GridView, o SQLDataSorce já é criado vinculado ao controle visual. Na primeira etapa do assistente, selecione DataBase, mantenha o valor padrão para o campo Specify na ID for the data source: 157 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Clique em Ok. Na próxima etapa você deve configurar o acesso ao banco de dados. No DropDownList desta janela são listadas conexões já encontradas no web.config da aplicação. Como não temos ainda nenhuma conexão configurada, não haverá valores listados: 158 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Para criarmos uma nova conexão,clique em New Connection. Na janela Choose Data Source, selecione Microsoft SQL Server: 159 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Clique em continue. Agora devemos fazer a configuração de fato da conexão. A janela Add Connection vai montar, de forma visual, a string de conexão que nas seções anteriores escrevemos no código. As informações necessárias são basicamente as mesmas: nome do servidor SQL Server em Server Name, se você não sabe o nome do servidor pode solicitar que os servidores disponíveis na rede sejam listados, clicando em Refresh. O tipo de conexão, que em nossa aplicação deverá ser Use SQL Server Authentication, ao selecionar esta opção automaticamente os campos User Name e Password são habilitados. Você deve informar o usuário de conexão e sua senha, respectivamente. Marque também a opção Save My Password, para que a senha seja salva junto com as demais informações de conexão. Finalmente, em Select or enter a database name, se as informações de conexão estiverem corretas, serão listados os banco de dados disponíveis no servidor. Selecione Northwind para nosso exemplo. 160 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Você ainda pode usar o botão Test Connection para testar sua conexão. Normalmente se os bancos de dados foram listados, a conexão já está funcionando. Clique em Ok. O VS nos trás de volta a janela Configure Data Source, desta vez com a conexão configurada. Note que se clicarmos no sinal + na parte central esquerda da janela podemos ver a string de conexão criada. Clique em Next. Nesta etapa devemos manter marcada a opção Yes, save this connection as para que o VS mantenha a string de conexão no Web.Config e, assim, possa ser reaproveitada por outros controles. Opcionalmente você pode alterar o nome da string de conexão: Clique novamente em Next. Esta é a etapa mais interessante de nosso Wizard. Aqui o VS montará automaticamente todas as instruções SQL necessárias para a configuração do controle. Na parte superior dois botões de rádio nos permitem escolher entre criar uma instrução Sql ou Stored Procedure para execução dos comandos ou 161 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores definir colunas de uma tabela ou view. Vamos utilizar a segunda opção. Abaixo, em Name, definimos qual tabela será incluída na consulta, o DropDownList lista todas as tabelas e views do banco de dados de nossa string de conexão: Clique agora no botão Advanced. O VS, além da instrução Select, pode gerar automaticamente os comandos SQL de inserção, atualização e exclusão, para isso devemos marcar o primeiro chekbox: 162 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Ter estes comandos criados é importante se queremos ter controles com funcionalidades de manipulação de dados. A segunda opção cria as instruções de atualização de exclusão de forma a detectar problemas de concorrência no banco de dados. Não vamos utilizar esta opção. Um ponto importante é que a criação das instruções de exclusão, inclusão e atualização só estão habilitadas porque ao selecionarmos os campos para inclusão na consulta incluímos a chave primária da tabela. Você pode testar isso, feche a janela Advanced, desmarque a coluna OrderID e abra novamente a tela Advanced. Note que todas as opções estão desabilitadas. Podemos seguir adiante. A última etapa nos permite testar a consulta, para isso clique no botão Test Query, se tudo estiver ok, a tela retorna o resultado da consulta: 163 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Ao finalizar o assistente você está de volta ao Web Form, como o GridView populado com dados fictícios, mas já seguindo o esquema dos campos selecionados. Foi criado também um controle SqlDataSource, já configurado. O SqlDataSource está vinculado ao GridView através da propriedade DataSourceID deste último. Antes de rodar a aplicação, examine as propriedade do SqlDataSource criado. Verifique propriedades como SelectQuery, UpdateQuery, DeleteQuery e InserQuery. Note que nestas propriedades são armazenados os comandos SQL criados: 164 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Podemos alterar estes comandos manualmente, desde que, obviamente, estejamos sabendo o que estamos fazendo. Existe ainda a possibilidade de utilizarmos a ferramenta Query Builder, que nos permite montar comandos complexos em uma interface visual. Para conhecer a ferramenta basta clicar no botão Query Builder na janela de exibição do comando. Tudo a fazer agora é rodar a aplicação: 165 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Exiba o código fonte da página e veja que o VS renderizou o GridView em elementos table, td e tr. Vamos aperfeiçoar nosso GridView. Primeiramente vamos dar um visual mais legal. Poderíamos fazer isso usando Thems ou mesmo CSS, mas vamos utilizar uma solução mais rápida: abra a Smart Tag do Grid View e clique na opção Auto Format. É exibida uma janela com várias opções de formatação pré-definidas. Ao selecionar uma opção podemos pré visualizá-la à direita: 166 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Depois de escolhida a opção, clique em ok. Rode a aplicação e veja a mudança no visual. Vamos agora adicionar mais funcionalidades ao GridView. Abra novamente a Smart Tag do controle e observe uma série de botões de verificação na parte inferior: Vamos ver o que cada opção significa: • Enable Paging: Habilita paginação em seu GridView. Para entender o que é paginação, lembre-se de quando você faz uma busca na internet: você pode navegar entre os conjuntos de resultados através de números, normalmente dispostos no rodapé da página. Cada número apresenta um conjunto de resultados. A paginação do GridView apresenta, por padrão, 10 linhas por página. Este valor pode ser alterado através da propriedade PageSize. • Enable Sorting: Habilita ordenação do GridView por uma determinada Coluna. Quando esta propriedade é habilitada, o título da coluna se torna um Link (você pode ver isso em tempo de design), que quando clicado ordena o resultado de forma ascendente por aquela coluna. Clicando novamente na mesma coluna, a ordenação se dá de forma descendente. 167 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores • Enable Editing: Habilita a edição de uma linha. Quando esta opção é marcada, o GridView ganha à direita um botão Edit, que quando clicado em tempo de execução, coloca a linha em modo de edição. • Enable Deleting: Habilita a exclusão de uma linha. Quando esta opção é marcada, o GridView ganha à direita um botão Delete, que quando clicado em tempo de execução, exclui o registro. • Enable Selection: Habilita a seleção de uma linha. Quando esta opção é marcada, o GridView ganha à direita um botão Select, que quando clicado em tempo de execução, seleciona a linha. É importante entender que algumas opções podem não estar disponíveis.Por exemplo, se não foi criada uma instrução Sql de Exclusão no SqlDataSource, a opção Enable Deleting não estará disponível. Também cabe lembrar que algumas operações estão restritas à integridade do banco de dados. Por exemplo, você não vai conseguir excluir um pedido se houver alguma integridade referencial com alguma outra tabela no banco de dados. Rode a aplicação. 168 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Teste as funcionalidades de seu GridView: Experimente ordenar colunas, paginar, alterar registros, etc. Note que, ao colocar uma linha em modo de edição, os botões Edit, Delete e Select são substituídos, apenas naquela linha, pelos botões Update e Cancel. Criamos um Grid View que nos permite alterar, excluir e selecionar registros, ordenar por colunas e ainda com recurso automático de paginação. Tudo isso sem escrever uma única linha de código. Examinando a página com mais cuidado, você vai perceber que seu GridView tem alguns problemas que precisam ser resolvidos, vamos enumerá-los para que as soluções sejam mostradas de forma ordenada: 1. Os títulos das colunas estão com os nomes da tabelas. O ideal é que pudéssemos personalizar estas informações; 2. Os títulos dos botões de comando estão em inglês. Também seria bom poder traduzi-los; 3. As datas carecem de máscaras, para não mostrar as informações de hora; 4. As colunas CustomerID e EmployeeID são chaves estrangeiras, e por isso são códigos que apontam para valores em outras tabelas. Seria interessante exibirmos CompanyName e LastName, por exemplo, ao invés de CustomerID e EmployeeID. O primeiro problema tem uma solução rápida e simples. Clique na opção Edit Columns do Smart Tag do GridView. É aberto o editor de colunas. Ele mostra os campos disponíveis, ou que podem ser incluídos no Grid, abaixo os campos já incluídos no Grid e à direita a lista de propriedade do campo selecionado. Em Selected fields, localize e selecione CommandField. Procure as propriedades com o sufixo Text, como CancelText, e as altere para o português: 169 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Você ainda pode mudar o tipo de botão na propriedade ButtonType. Observe que no meu exemplo alterei de Link para Button. Note também que nos campos selecionados, CommandField é agora o último campo da listagem. Você pode ordenar os campos da forma que quiser, basta selecioná-lo e movê-lo utilizando os botões de subir e descer ao lado da listagem. Clique em ok. Observe na imagem abaixo que agora temos botões ao invés de links, traduzidos e do lado direito do GridView: 170 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores O segundo problema é traduzir os títulos da coluna. O caminho é semelhante. Clique na opção Edit Columns do Smart Tag do GridView. É aberto o editor de colunas. Para cada coluna localize e traduza a propriedade HeaderText: 171 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Note que alterei CustomerID para Cliente, ao invés de modificar para código do cliente. Isto porque nosso último problema é exatamente trocar o código pelo Nome da Empresa. Depois de traduzir todas as colunas, clique em ok e observe o resultado. 172 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores O terceiro problema, formatar as datas, segue o mesmo caminho: clique na opção Edit Columns do Smart Tag do GridView. É aberto o editor de colunas. Para cada coluna de tipo data, localize a propriedade DataFormatString, e adicione o texto {0:d}, sendo o primeiro caractere zero e a letra d minúscula. Observe a imagem abaixo: A string de formatação está dizendo que o primeiro parâmetro, e neste caso como se trata de um campo temos apenas um, seja formatado como data, o que é representado pelo d minúsculo. Nosso quarto é último problema, visualizar os textos das chaves estrangeiras ao invés dos códigos, é um pouco mais difícil, porém está longe de ser complexo. Vamos precisar criar um SqlDataSource que aponte para a tabela em que a chave estrangeira faz referência. Em seguida vamos converter a coluna em TempleField e adicionar um DropDownList que seja populado com a tabela estrangeira, mas que exiba o registro de acordo com o código daquela linha. 173 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Vamos mostrar o procedimento para a coluna Cliente. Primeiramente adicione um controle SqlDataSource ao seu Web Form. Na Smart Tag clique em Configure Data Souce. Na primeira etapa selecione o string de conexão que já está disponível em seu web.config. Na segunda etapa você deve escolher a tabela Customers e marcar apenas as colunas CustomerID e CompanyName. Não é necessário solicitar a criação dos demais comandos Sql, já que o SqlDataSource vai ser usado apenas para listar dados em um DropDownList. Execute as próximas etapas do Wizard e o finalize. Por que escolhemos as colunas CustomerID e CompanyName? CustomerID é a chave primária da tabela Customers, consequentemente é a chave estrangeira na tabela Orders que popula nosso GridView. Esta coluna é necessária para identificar qual linha da tabela deve ser exibida. CompanyName é o campo que vai ser exibido ao usuário: 174 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores lembre-se que estamos fazendo isto para que o usuário não tenha que ver o código (CustomerID) do cliente no GridView. Nossa próxima etapa é transformar a coluna Customer em um TemplateField. Um TemplateField é uma coluna onde podemos personalizar de forma mais profunda o seu comportamento. Clique na opção Edit Columns do Smart Tag do GridView. É aberto o editor de colunas. Selecione o campo cliente, em seguida clique em Convert this field into a TemplateField. Esta opção está disponível na forma de um link, logo acima do botão ok: Agora vamos editar o template criado. Clique com o botão direito do mouse sobre o GridView, localize a opção Edit Template e em seguida clique sobre Column[1] – Cliente: 175 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores Note que o GridView entra em modo de edição de template, dividindo-se em várias regiões que funcionam como containers, onde podemos colocar controles. No ItemTemplate existe um controle Label e no EditItemTemplate um controle TextBox. Remova ambos os controles e adicione, em cada uma destas duas regiões, um controle DropDownList. Seu template deverá ficar semelhante à imagem abaixo: 176 Este material deve ser utilizado apenas como parâmetro de estudo deste Programa. Os créditos deste conteúdo são dados aos seus respectivos autores A próxima etapa é configurar os controles DropDownList. Primeiramente devemos definir a origem dos dados, ou seja, de onde virão as informações para sua listagem. Para isto selecione a opção ChoseDataSource em sua Smart Tag. Em Select a data source escolha SqlDataSource2, que foi o controle que configuramos para apontar para a tabela de clientes. Select data field to display in the DropDownList deve conter o campo que
Compartilhar