Vamos criar uma aplicação
WPF com uma página de Login usando Linq To SQL para mostrar
primeiro que o LINQ to SQL ainda existe e pode ser usado no
Visual Basic 2010 Express Edition e que além disso é muito simples
usar o Linq to SQL.
Vou iniciar mostrando o
funcionamento da aplicação:
- Ao iniciar a aplicação,
o formulário de Login é apresentado:
02. Se o login do usuário e
a senha forem válidos, então será aberta uma página na qual
executamos um vídeo:
03. Se o login e/ou senha
forem inválidos, então será apresentada uma mensagem ao
usuário:
04. No evento Click
do botão Sair, temos a exibição de uma caixa
de mensagem ao usuário solicitando a confirmação para fechar
ou não a aplicação:
É uma aplicação bem
simples, mas que envolve alguns conceitos básicos para iniciantes
em aplicações WPF e que usa o LINQ to SQL para simplificar o
código de acesso às informações de um banco de dados SQL
Server chamado Cadastro.mdf.
Nesse banco de dados, existe a
tabela Usuarios que armazena o login e a senha
do usuário. A estrutura da tabela Usuarios
é mostrada abaixo:
Para simplificar o acesso às informações, vamos usar o Linq to SQL para mapear a tabela Usuarios
como uma classe e assim usar uma consulta Linq to SQL para
acessar as informações na tabela.
LINQ to SQL é uma implementação específica do LINQ para o SQL Server que converte consultas escritas em C# ou Visual Basic em SQL dinâmico, provendo uma interface que permite mapear os objetos do banco de dados, gerando as classes para realizar as operações usando a sintaxe LINQ que também permite realizar alterações nos objetos e atualizar o banco de dados.
Criando o projeto WPF no Visual Basic 2010 Express Edition
Abra o VB 2010 Express Edition e crie um novo projeto no menu File > New Project selecionando o template WPF Application, informando o nome WPF_Login_Linq e clicando em OK.
Agora vamos incluir a partir do menu Project >Add New Item, a partir da janela Templates, o item LINQ to SQL Classes alterando o nome para Login.dbml e clicando no botão Add.
Nesse momento, será exibida a janela
do descritor Objeto Relacional. Expanda os objetos do
banco de dados Cadastro.mdf e selecione a tabela Usuarios
arrastando e soltando-a na janela Object Relational Designer.
Você pode criar o banco de dados Cadastro.mdf e a tabela Usuarios
usando o SQL Server Management Studio Express Edition. É possível fazer isso usando diretamente a ferramenta conforme mostrei
no artigo Usando o SQL Server Management Studio.
Existe também uma forma de criar o banco de dados e a tabela executando os scripts sql
descritos a seguir:
- Script para criar o banco de dados Cadastro.mdf (cria na pasta
c:dados)
USE [master]
GO
CREATE DATABASE [Cadastro] ON PRIMARY
( NAME = N'Cadastro', FILENAME = N'c:dadosCadastro.mdf' , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'Cadastro_log', FILENAME = N'c:dadosMacoratti_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
begin
EXEC [Cadastro].[dbo].[sp_fulltext_database] @action = 'enable'
end
02. Script para criar a tabela Usuarios
USE [Cadastro]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Usuarios](
[id] [int] IDENTITY(1,1) NOT NULL,
[login] [nvarchar](50) NULL,
[nome] [nvarchar](50) NULL,
[senha] [nvarchar](50) NULL,
[email] [nvarchar](80) NULL,
CONSTRAINT [PK_Usuarios] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Para executar os scripts, basta abrir o SQL Server Management Studio
Express e clicar em New Query, copiar e colar os scripts (na
ordem e um de cada vez) e clicar no botão Execute.
As tabelas do banco de dados serão
mapeadas como classes (campos como propriedades, procedures e
funções como métodos)
e você terá no Descritor o conjunto de classes que
representam o banco de dados. Para o nosso exemplo, a tabela Usuarios
será mapeada para a classe Usuario conforme
mostra a imagem acima.
O arquivo Login.dbml contém
o arquivo XML com informações sobre o layout das tabelas que
foram mapeadas e também o descrito com as classes geradas
pelo mapeamento.
Após encerrar o mapeamento, você já terá
acesso aos recursos do LINQ To SQL com direito a intellisense completo das informações referentes às
tabelas mesmo sem conhecer nada sobre elas.
Vamos agora criar a interface na
página MainWindow.xaml usando os seguintes
controles:
- Labels
- TextBox – txtLogin
- PasswordBox – txtSenha
- Button – btnLogin e btnSair
Conforme o layout abaixo:
O código XAML gerado para o
formulário acima é dado a seguir:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Login com LINQ" Height="468" Width="575">
<Grid Background="#0E62FF00" Height="259" Width="458">
<Label Content="Nome do Usuário " Height="28" HorizontalAlignment="Left" Margin="69,58,0,0" Name="Label1" VerticalAlignment="Top" Width="123" Foreground="White" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="198,60,0,0" Name="txtLogin" VerticalAlignment="Top" Width="137" Background="#9C9BE9EB" />
<Label Content="Senha" Height="28" HorizontalAlignment="Left" Margin="71,95,0,0" Name="Label2" VerticalAlignment="Top" Width="106" Foreground="White" />
<Button Content="Login" Height="31" HorizontalAlignment="Left" Margin="189,156,0,0" Name="btnLogin" VerticalAlignment="Top" Width="75" />
<Button Content="Sair" Height="31" HorizontalAlignment="Left" Margin="277,156,0,0" Name="btnSair" VerticalAlignment="Top" Width="75" />
<Image Height="66" HorizontalAlignment="Left" Margin="79,129,0,0" Name="Image1" Stretch="Fill" VerticalAlignment="Top" Width="69" Source="/WPF_Login_Linq;component/Images/login.jpg" />
<PasswordBox Height="23" Margin="200,96,0,0" Name="txtSenha" VerticalAlignment="Top" Password="" Background="#9C9BE9EB" HorizontalAlignment="Left" Width="134" />
</Grid>
<Window.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="Black" Offset="0" />
<GradientStop Color="White" Offset="1" />
</LinearGradientBrush>
</Window.Background>
</Window>
Além da página MainWindow.xaml,
vamos incluir uma nova página no projeto. No menu Project > Add New Item, selecione o template
Page(WPF) e aceite o nome padrão Page1.xaml.
Agora nesta página vamos incluir
apenas uma declaração XAML que usa o controle MediaElement para
exibir um vídeo na página.
<Page x:Class="Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="440" d:DesignWidth="581"
Title="Page1">
<Grid Height="411" Width="588">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48*" />
<ColumnDefinition Width="540*" />
</Grid.ColumnDefinitions>
<MediaElement Source="C:UsersPublicVideosSample Videoslake.wmv" Margin="12,12,12,22" Grid.ColumnSpan="2" />
</Grid>
</Page>
Eu estou usando o vídeo de amostra
do Windows Lake.wmv. A classe MediaElement
representa um controle que contém áudio e/ou vídeo e pode ser usado em dois modos distintos,
dependendo de como o controle está direcionado:
- Modo independente:
neste modo, o MediaElement é análogo a uma
imagem e a URI de origem pode ser especificada
diretamente; - No modo Relógio (Clock): neste modo, o MediaElement pode ser visto como a
origem para uma animação e assim ele terá as entradas
TimeLine e Clock correspondentes na árvore de tempo.
Vejamos agora a implementação do
código na página WPF. Primeiro declaramos os namespaces
usados no projeto:
- Imports System.Linq
- Imports System.Data
- Imports System.ComponentModel
- Imports System.Collections.Generic
A seguir, temos o código do evento Click
do botão Login:
Private Sub btnLogin_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnLogin.Click
If (verificaUsuario(txtLogin.Text.Trim(), txtSenha.Password.Trim()) = True) Then
Dim page1 As New Page1()
Me.Content = page1
Else
Dim result As MessageBoxResult = MessageBox.Show("Login/Senha Inválidos", "Login Inválido")
End If
Nesse código, usamos a
rotina verificaUsuario() passando o login e a
senha para verificar se as credenciais são válidas. Em caso
positivo, abrimos a página Page1() que irá
exibir o vídeo.
A rotina verificaUsuario()
usa os recursos do Linq To SQL para consultar a tabela Usuarios e verificar se o
nome e senha do usuário existem:
Public Function verificaUsuario(ByVal userName As String, ByVal senha As String) As Boolean
Dim db As New LoginDataContext()
Dim nomes = (From lg In db.Usuarios Where lg.login = userName AndAlso lg.senha = senha).SingleOrDefault()
If nomes IsNot Nothing Then
Return True
Else
Return False
End If
End Function
No código estamos criando
uma instância do nosso DataContext: Dim db As New
LoginDataContext(). Aqui o banco de dados é mapeado em
um DataContext permitindo acesso a tabelas de forma
transparente sem nos preocuparmos com conexão.
O DataContext
utiliza a interface IDbConnection do ADO.NET para acessar
o armazenamento e pode ser inicializado tanto com um objeto de
conexão ADO.NET estabelecido ou com uma string de conexão que
possa ser utilizada para criar a conexão.
O DataContext é o
responsável por gerar as instruções SQL da sua linguagem de
consulta e então mapear as linhas de dados retornadas a partir
do seu banco de dados para objetos.
Em seguida executamos a consulta
Linq To SQL: Dim
nomes = (From lg In db.Usuarios Where lg.login = userName AndAlso
lg.senha = senha).SingleOrDefault(). A consulta LINQ To SQL inicia com a
cláusula From e em seguida o operador de condição
Where e no final a cláusual SingeOrDefault.
Observação: O
LINQ possui o método de extensão Single/SingleOrDefault que
pode ser usado para retornar somente um elemento em uma
sequência que satisfaça uma condição específica.
Um dos motivos dessa inversão de
ordens é o uso recurso IntelliSense,
pois, quando você indica primeiro a origem dos dados, ele pode
mostrar as listas de membros de tipos nos objetos em sua
coleção.
Outro motivo, segundo Anders Hejlsberg, seria que esta ordem está mais próxima da
nossa lógica de pensamento.
Quando você digita uma instrução SQL iniciando com Select,
na verdade você já está pensando na origem dos dados,
condições, agrupamentos etc.
A cláusula From é a mais
importante do LINQ To SQL, pois é usada em todas as
consultas. Uma consulta deve sempre começar com From. O Select pode estar
implícito o From não. Esse código define a variável nomes
do tipo Usuario, note que o compilador está inferindo o
tipo da variável, pois ela não foi declarada no código.
Este é um dos recursos da
plataforma .NET, a inferência de tipos, que ocorre quando
não há declaração explícita do tipo do objeto e o compilador
descobre e atribui o tipo correto ao objeto declarado – é o que
acontece neste caso.
Se o nome e a senha existirem,
retornamos True; caso contrário, retornamos False. Para encerrar, temos a seguir o
código dos botões Sair que encerra a
aplicação e do evento Load da janela que
coloca o foco no campo txtLogin:
Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
txtLogin.Focus()
End Sub
Private Sub btnSair_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnSair.Click
If MessageBox.Show("Deseja realmente sair?", "Confirmação", MessageBoxButton.YesNo) = MessageBoxResult.Yes Then
Me.Close()
End If
End Sub
Dessa forma, usando LINQ
to SQL é muito simples tratar com o acesso a dados em sua
aplicação quer seja ela Windows Forms, WPF ou ASP .NET. Aguarde em breve mais
artigos sobre WPF e pegue o projeto completo em WPF_Login_Linq.zip.
Eu sei, é apenas WPF, mas
eu gosto…