Mostrando postagens com marcador sql. Mostrar todas as postagens
Mostrando postagens com marcador sql. Mostrar todas as postagens

terça-feira, 30 de abril de 2013

LINQ x Stored Procedure

LINQ utiliza a Stored Procedure (SP) como sendo um métodos em seu contexto de dados.

No exemplo a seguir vou criar uma SP para listar todos os clientes com o nome Celso Zequim. veja o código:

CREATE PROCEDURE BuscaCliente      @nome varchar(255)     
     
AS
BEGIN
      SELECT * from Cliente where nome = @nome
END
 
No Visual Studio adicione um arquivo do tipo LINQ to SQL, no meu caso vou adicionar com o nome Banco.dbml.




Ao criar o arquivo, adicionei uma nova conexão em Server Explorer apontando para meu banco de dados de testes.  e naveguei até a pasta StoredProcedures


Clique e arraste a StoredProcedures para dentro do arquivo Banco.dbml.
o resultado será o seguitne:


Será adicionado um Método com o nome da SP.

No arquivo Program.cs é só chamar a SP:


   static void Main(string[] args)
   {
       BancoDataContext bd = new BancoDataContext();

  var resultado = bd.BuscaCliente("celso zequim");
  foreach (var r in resultado)
  {
 Console.Write(r.nome);
  }
  Console.ReadKey();

   }


Pressione F5 e veja o Resultado:


sexta-feira, 26 de abril de 2013

LINQ to SQL - Inner Join e Left Join


Fazer Inner Join e Left Join utilizando LINQ é muito simples.

Eu tenho a seguinte estrutura de banco de dados:

Dados ara a tabela TipoAnimal:

  • Canino
  • Felino
Dados para a Tabela Cliente:
  • Celso Zequim 
  • Ana Paula
para a tabela Animal eu inseri um registro, dizendo que o Celso Zequim possui um Animal do tipo Canino com o nome de Babalu.


Para realizar um consulta no SQL Server para trazer os Todos os clientes e seus respectivos animais, ficaria dessa maneira:

select Cliente.Nome, Animal.Nome as Animal, TipoAnimal.Nome as Tipo from Cliente
inner join Animal on animal.idcliente = cliente.id
inner join TipoAnimal on Animal.idTipoAnimal = TipoAnimal.id


Para realizar essa query no LINQ teriamos:

var Resultado = from _C in bd.Clientes
join _A in bd.Animals on _C.id equals _A.idCliente
join _T in bd.TipoAnimals on _A.idTipoAnimal equals _T.id      
select new
{
         Nome = _C.nome,
         Animal = _A.nome,
         Tipo = _T.nome
};
Se eu quiser trazer todos os clientes, independente se eles tem animais ou não, teremos a seguinte query, com Left Join:

select Cliente.Nome, Animal.Nome as Animal, TipoAnimal.Nome as Tipo from Cliente
Left join Animal on animal.idcliente = cliente.id
Left join TipoAnimal on Animal.idTipoAnimal = TipoAnimal.id



Já no LINQ teríamos:

  var Resultado = from _C in bd.Clientes
join _A in bd.Animals on _C.id equals _A.idCliente into _a
from _A in   _a.DefaultIfEmpty()
join _T in bd.TipoAnimals on _A.idTipoAnimal equals _T.id     into _t 
from _T in _a.DefaultIfEmpty()
select new
{
         Nome = _C.nome,
         Animal = _A.nome,
         Tipo = _T.nome
};


É um pouco mais complicado a construção, porém  com o tempo se torna automático. 

Exportando dados de uma tabela SQL - Update e Inser

Hoje no forum da MSDN postaram uma uma dúvida de como exportar dados de uma tabela do banco de dados SQL Server e gerar um script para inserção e atualização. 

A necessidade da pessoa era poder fazer o Backup de uma tabela em qualquer momento. 

Esse código abaixo resolve esse problema:

static string ExportarDados(string tabela)
        {
            int i, j;
            string res1 = "", res2 = "";

            string queryStrutura = "select syscolumns.xtype,length,isnullable,syscolumns.name from syscolumns,sysobjects where syscolumns.id=sysobjects.id and sysobjects.name='" + tabela + "' order by colid";
            string query = "select * from " + tabela;
            DataTable dt = ObterDados(queryStrutura);
            DataTable d = ObterDados(query);
            DateTime data;
            string sql;
            for (j = 0; j < d.Rows.Count; j++)
            {
                sql = "if (select count(*) from " + tabela + " where " + dt.Rows[0][3].ToString() + "='" + d.Rows[j][0].ToString()  + "')=0 begin\r\n";
                sql += "insert " + tabela + " values(";
                for (i = 0; i < dt.Rows.Count; i++)
                {
                    switch ( dt.Rows[i][0].ToString())
                    {
                        case "35":
                        case "36":
                        case "167":
                        case "175": // campo do tipo texto
                            if (dt.Rows[i][2].ToString() == "1" && d.Rows[j][i] ==null)
                                sql += "null";
                            else
                                sql += "'" + d.Rows[j][i].ToString().Replace("'", "''") + "'";
                            break;
                        case "108": //campo do tipo numérico
                            if (dt.Rows[i][2].ToString() == "1" && d.Rows[j][i] == null)
                                sql += "null";
                            else
                                sql += d.Rows[j][i].ToString();
                            break;
                        case "61": //campo do tipo data
                            if (dt.Rows[i][2].ToString() == "1" && d.Rows[j][i] == null)
                                sql += "null";
                            else
                            {
                                data =DateTime.Parse( d.Rows[j][i].ToString());
                                sql += "convert(datetime,'" + data.Day + "/" + data.Month + "/" + data.Year + " " + data.Hour + ":" + data.Minute + ":" + data.Second + ":" + data.Millisecond + "',103)";
                            }
                            break;
                    }
                    if (i < d.Columns.Count - 1)
                        sql += ",";
                }
                sql += ")\r\nend else begin\r\n";
                sql += "update " + tabela + " set ";
                for (i = 1; i < d.Columns.Count; i++)
                {
                    sql += dt.Rows[i][3].ToString()  + "=";
                    switch (dt.Rows[i][0].ToString())
                    {
                        case "35":
                        case "36":
                        case "167":
                        case "175": // Campos do tipo texto
                            if (dt.Rows[i][2].ToString() == "1" && d.Rows[j][i] == null)
                                sql += "null";
                            else
                                sql += "'" + d.Rows[j][i].ToString().Replace("'", "''") + "'";
                            break;
                        case "108": // campos do tipo numérico
                            if (dt.Rows[i][2].ToString() == "1" && d.Rows[j][i] == null)
                                sql += "null";
                            else
                                sql += d.Rows[j][i].ToString();
                            break;
                        case "61": //campo do tipo data
                            if (dt.Rows[i][2].ToString() == "1" && d.Rows[j][i] == null)
                                sql += "null";
                            else
                            {
                                data = DateTime.Parse( d.Rows[j][i].ToString());
                                sql += "convert(datetime,'" + data.Day + "/" + data.Month + "/" + data.Year + " " + data.Hour + ":" + data.Minute + ":" + data.Second + ":" + data.Millisecond + "',103)";
                            }
                            break;
                    }
                    if (i < d.Columns.Count - 1)
                        sql += ",";
                }
                sql += " where " + dt.Rows[0][3].ToString() + "='" + d.Rows[j][0].ToString() + "'";
                sql += "\r\nend\r\nGO\r\n\r\n";
                res1 += sql;
                if ((j - 15 * (j / 15)) == 0)
                {
                    res2 += res1;
                    res1 = "";
                }
            }
            res2 += res1;
            return res2;
        }

terça-feira, 23 de abril de 2013

Formulário de Login - Básico


Hoje postaram uma dúvida no forúm da MSDN sobre controle de Login. E eu achei interessante postar aqui uma forma simples de se criar uma tela de login.

Esse exemplo é em WindowsForms.

Primei eu adicionei os seguintes controles:
  • Label – Usuário e Senha
  • TextBox – Usuário e Senha
  • Button – Login


Os nomes dos controles ficaram:


  • TxtUsuario
  • TxtSenha
  • BtnLogin

O form ficou dessa maneira:



No evento Click do botão Login entrei com o seguinte código:
private void BtnLogin_Click(object sender, EventArgs e)
{
    if (txtUsuario.Text != string.Empty && txtSenha.Text != string.Empty)
    {

if (ExecutaLogin(txtUsuario.Text, txtSenha.Text))
{
    MessageBox.Show("Bem Vindo");
}
else
{
    MessageBox.Show("Usuário ou senha inválida");
}
    }
}

Acima eu estou verificando se o usuário preencheu os campos, se sim, eu executo a função: ExecutaLogin(string, string), veja o código:
private bool ExecutaLogin(string usuario, string senha)
{

    bool ok = false;

    SqlConnection cnnBase = new SqlConnection(ControleLogin.Properties.Settings.Default.Conexao);
    SqlCommand cmd = new SqlCommand("select nome from usuario where login=@usuario and senha=@senha", cnnBase);
    cmd.CommandType = CommandType.Text;

    cmd.Parameters.Add("@usuario", SqlDbType.VarChar).Value = usuario;
    cmd.Parameters.Add("@senha", SqlDbType.VarChar).Value = senha;

    SqlDataAdapter da = new SqlDataAdapter(cmd);

    DataTable dt = new DataTable();

    da.Fill(dt);

    da.Dispose();
    cmd.Dispose();
    cnnBase.Close();

    if (dt.Rows.Count == 1)
    {
return true;
    }
    else
    {
return false;
    }
    return ok;

}
O que esta sendo feito nessa função, nessa função eu utilizo 4 variáveis diferentes, são elas:
  • cnnBase -  é a conexão com o meu banco de dados, a connectionString  eu criei no App.Config. assim eu posso centralizar e acessar de qualquer ponto do sistema.
  • cmd – é o comando que será executado pelo SQL, no meu caso uma consulta.
  • da – é o retorno da minha consulta
  • dt – é o resultado transformado da minha consulta em uma tabela.

Repare que eu não estou concatenando os valores que o usuário passou  ao comando SQL que será executado. Isso porque o usuário pode inserir alguns códigos e quebrar o resultado do SQL, isso é chamado de SqlInjection. Por isso eu estou adicionado como parâmetro e informando qual é o tipo de dado que estou passando.

Eu coloquei um IF retornando como ok somente se o retorno for igual a um, pois se o resultado contiver mais de um registro ou não retornar nada, o retorno tem que ser falso.

Ao executar e digitar o usuário correto, o resultado será esse:


Digitando o usuário errado e a senha correta:



segunda-feira, 15 de abril de 2013

Upload e Download de arquivo com LINQ


Fazer um upload de um arquivo qualquer para o banco de dados através do LINQ é muito fácil.


Criei em meu banco de dados uma tabela chamada documento, com os seguintes campos:
Tipo de dados:
Id – Uniqueidentifier
Nome – Varchar(max)
Arquivo – Image

Adicionei ao projeto um arquivo do tipo LINQ to SQL  com o nome de Banco.dbml  e adicionei a tabela documento.

Feito isso, precisamos criar a página que irá enviar o arquivo. No meu caso é a Default.aspx. veja como ficou o código:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="ExemploWeb._default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:FileUpload ID="UpArquivo" runat="server" />

        <br />

        <asp:Button ID="BtnEnviar" Text="Enviar" runat="server"
            onclick="BtnEnviar_Click"  />
    </div>
    </form>
</body>
</html>


O controle “asp:FileUpload” é necessário para fazer o upload e o controle do tipo Button que irá realizar toda mágica.  Repare que eu adicionei um evento chamado onClick e apontei para a função “BtnEnviar_Click”.  Essa função deverá ser criada no arquivo Default.aspx.cs. Veja abaixo:

       protected void BtnEnviar_Click(object sender, EventArgs e)
        {
            if (UpArquivo.HasFile && UpArquivo.PostedFile.ContentLength > 0)
            {

                byte[] _arquivo = UpArquivo.FileBytes;

                BancoDataContext bd = new BancoDataContext();
                documento doc = new documento();
                doc.id = Guid.NewGuid();
                doc.nome = UpArquivo.FileName;
                doc.arquivo = _arquivo;
                bd.documentos.InsertOnSubmit(doc);
                bd.SubmitChanges();

            }
        }

No exemplo acima eu armazenei o  arquivo, em formato de bytes, na variável _arquivo. Após armazenar o arquivo  foi criado um Contexto do meu banco de dados, dei o nome de bd. Esse contexto vem do LINQ e é responsável pela ligação do C# com o SQL.

Criei uma nova instancia do objeto documento e atribuir os valores, id, nome e arquivo.
O método InsertOnSubmit é responsável por guardar o objeto em cache até executar o submit, que é o método SubmitChanges, Até esse momento o registro ainda não existe no banco de dados.

Veja como ficou:
Clicando no botão “Escolher arquivo” a seguinte janela será exibida:

Vou escolher esse arquivo PDF e clicar em open.


Feito isso é só clicar em enviar.  O resultado já pode ser visto no banco de dados. 


Para realizar o Download do arquivo basta colocar esse trecho de código no evento do botão download, que pode ser criado exatamente como o botão enviar.
protected void BtnDownload_Click(object sender, EventArgs e)
        {
            BancoDataContext bd = new BancoDataContext();
            var arquivos = from c in bd.documentos select c;
            foreach (documento arquivo in arquivos)
            {
                Response.AddHeader("Content-Disposition", "attachment; filename=" + arquivo.nome);
                Response.ContentType = "application/x-zip-compressed";

                if (arquivo.arquivo != null)
                    Response.BinaryWrite(arquivo.arquivo.ToArray());
            }

        }







terça-feira, 9 de abril de 2013

DropDownList e Grid com LINQ


Recebi alguns emails questionando como trabalhar com DropDownList e GridView utilizando o Linq como fonte de dados.

Não tem muito segredo.

Veja o exemplo abaixo. 
Criei uma tabela em meu banco de dados com alguns campos.

Criei um arquivo no Visual Studio do tipo Linq to SQL, chamado de Banco.dbml e adicionei a tabela aluno.  Tenho um artigo escrito com maiores detalhes sobre o linq.

No arquivo Default.aspx adicionei o DropDownList:

<form id="form1" runat="server">
    <div>
        <asp:DropDownList ID="DDLalunos" runat="server" />
    </div>
</form>

Já no arquivo Default.aspx.cs eu indiquei como o controle será carregado:

BancoDataContext bd = new BancoDataContext();
DDLalunos.DataSource = (from c in bd.Alunos orderby c.nome select c).ToList();

DDLalunos.DataValueField = "id";
DDLalunos.DataTextField = "nome";

DDLalunos.DataBind();

Nesse exemplo eu estou listando os alunos ordenando por nome e atribuindo ao DataSource.
Feito isso será necessário indicar qual é apresentado ao usuário final e o campo que conterá o valor a ser enviado quando ocorrer o submit.

Neste caso eu estou dizendo que o valor a ser passado é a coluna ID e o valor apresentado para o usuário final é a coluna NOME.  

O DataBind é responsável por carregar essa informações indicadas anteriormente.
Ao executar, o resultado será como abaixo:


Eu posso indicar outra coluna para ser o valor apresentado ao usuário final:
BancoDataContext bd = new BancoDataContext();
DDLalunos.DataSource = (from c in bd.Alunos orderby c.nome select c).ToList();

DDLalunos.DataValueField = "id";
DDLalunos.DataTextField = "email";

DDLalunos.DataBind();


Veja o resultado:

No caso do GridView é a mesma coisa.

No arquivo Default.aspx eu adicionei a chamada o Grid

<form id="form1" runat="server">
    <div>
<asp:GridView ID="GDVAlunos" runat="server" AutoGenerateColumns="true" />
    </div>
</form>

No arquivo Default.aspx.cs indiquei qual é a fonte de dados e chamei o método DataBind();

GDVAlunos.DataSource = (from c in bd.Alunos orderby c.nome select c).ToList();
GDVAlunos.DataBind();

Veja o Resultado: