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, 22 de abril de 2013

Snippet

Snippet ou Fragmento de Código é a forma de invocar códigos pré-estabelecidos pelo desenvolvedor em qualquer parte do sistema.

O Visual Studio já vem com diversos snippet  e um bom exemplo de um snippet que já existe no Visual Studio é o for.

Qualquer palavra que se digita no Visual Studio ele te mostra as possibilidades, algumas delas contém uma descrição dizendo que pode se invocar um snippet. Como no exemplo abaixo: 


É só pressionar duas vezes a tecla TAB que o snippet será invocado. O resultado é o seguinte:

No exemplo acima o Visual Studio adicionou a estrutura do for ao código.
O mesmo acontece com outras palavras, como  foreach, if, switch, etc.

Você pode criar o seu próprio snippet. O Snippet é um arquivo Xml e tem a seguinte estrutura:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
       <CodeSnippet Format="1.0.0">
             <Header>
                    <Title>Exemplo snippet</Title>
                    <Shortcut>exemplo</Shortcut>
                    <Description>Esse código adiciona for, if, while e foreach</Description>
                    <Author>Celso Zequim</Author>
                    <SnippetTypes>
                           <SnippetType>Expansion</SnippetType>
                           <SnippetType>SurroundsWith</SnippetType>
                    </SnippetTypes>
             </Header>
             <Snippet>
              <Declarations>
                     <Literal>
                           <ID>indice</ID>
                           <Default>i</Default>
                           <ToolTip>Indice</ToolTip>
                    </Literal>
                    <Literal>
                           <ID>maximo</ID>
                           <Default>Max</Default>
                            <ToolTip>Máximo Permitido</ToolTip>
                     </Literal>
        <Literal>
        <ID>valor</ID>
                            <Default>valor</Default>
        <ToolTip>Valor para comparação</ToolTip>
        </Literal>
        <Literal>
          <ID>Condicao</ID>
          <Default>condicao</Default>
          <ToolTip>Valor do switch</ToolTip>
        </Literal>
             </Declarations>
             <Code Language="csharp">
        <![CDATA[for (int $indice$ = 0; $indice$ < $maximo$; $indice$++)
                    {
                    $selected$ $end$
                    }
     
      if($valor$ == "")
                    {
                   
                    }
     
        switch ($Condicao$)
            {
                default:
            }
      ]]>
                    </Code>
             </Snippet>
       </CodeSnippet>
</CodeSnippets>

  • Header – Representa as informações exibidas no memento que se posicionar sobre a palavra de atalho,
  • Declarations – Local onde as variáveis que serão utilizadas no código deverão ser declaradas.
  • Code – Qual é o código que será impresso no momento em que o desenvolvedor invocar o snippet.

Repare que existe um código dentro do for, “$selected$ $end$”, esse código indica ao Visual Studio o local que o cursor deverá ficar assim que o desenvolvedor terminar de preencher as variáveis solicitadas.

Salve esse arquivo com a extensão “snippet”, no meu caso eu estou salvando como “exemplo.snippet”.  vá até o menu Tools e clique na opção “Code Snippets Manager”.

A seguinte janela será exibida:

Clique no botão Import e localize o arquivo que deseja importar. No meu caso é o “exemplo.snippet”.
Feito isso é só digitar em algum trecho de código o comando que você colocou em “Shortcut”, no meu caso é a palavra “exemplo”

 Note que quando posicionar sobre a palavra do seu Snippet, o Visual Studio irá lhe exibir as informações que você inseriu no Header e ao pressionar duas vezes a tecla TAB, o resultado será a seguinte:

        static void Main(string[] args)
        {

            for (int i = 0; i < Max; i++)
            {
               
            }

            if (valor == "")
            {

            }

            switch (condicao)
            {
                default:
            }
     
     
        }



Você pode usar o Snippet para adicionar qualquer código de forma rápida.