Object Relational Mapping

Nesta aula iremos iniciar a criação de um ORM no C#, utilizando a classe reflection iremos varrer todas as propriedades de nossa classe criando então modelos inteligentes e ganhando agilidade no desenvolvimento.

assinaturaAssine nossa Comunidade

Object Relational Mapping - ORM

Object Relational Mapping é um framework que utilizamos para gerenciar o Banco de Dados.

São criadas as tabelas, comandos do Sql como insert, select, etc.

Na aula anterior, criamos a classe Usuario na camada Business, outra na camada Database, tornando o processo redundante. Com o ORM , podemos fazer de forma genérica, criando somente uma única classe Usuario em Business que "conversa" com o Database e o Database entende que essa classe é uma tabela no Banco de Dados e busca diretamente no Sql , tudo de forma dinâmica.

Então, como criamos um ORM?

Primeiro, para criar ORM precisamos entender o conceito de Reflexion.

Reflexion

Reflexion é uma classe no C# que consegue descobrir qual o nome, as propriedades e os métodos da sua classe e consegue chamar tantos os métodos quanto as propriedades. Também define atributos e, com todos esses recursos, conseguimos criar algo genérico.

No projeto ORM:

  • Em Business, criaremos a classe Usuario;
  • Em Database, criaremos:
    • A classe OpcoesBase - que são configurações dos atributos
    • A Interface IBase
    • A classe Base (que implementa IBase)
  1. Criar atributos para definir onde queremos salvar os dados

  2. Criamos uma classe OpcoesBase que herda de Attribute para criar assinaturas nas propriedades das classes, por exemplo, da classe Usuario que vamos criar mais adiante.

            
              namespace Database
              {
                public class OpcoesBase : Attribute
                  {
                    public bool UsarNoBancoDeDados {get; set;}
                    public bool UsarParaBuscar {get; set;}
                    public bool ChavePrimaria {get; set;}
                }
              }
             
           
  3. Criar uma Interface que passará por todas as camadas.É o mais genérico possível.

  4. Todas as classe que herdarem de IBase, devem implementar os métodos

            
              namespace Database
              {
                public Interface IBase
                  {
                    string Key {get;}
                    void Salvar();
                    List< IBase> Todos();
                    List< IBase> Busca();
                }
              }
             
           
  5. Criar a classe Base que implementará toda a interface.

    1. Teremos uma propriedade privada para obter a conexão.
    2. Implementar a propriedade Key, somente com get.
    3. Referenciar using System.Refletion, que dará a possibilidade de termos a informação das propriedades através da classe PropertyInfo e será utilizada na propriedade Key.
    4. Utilizamos this e o GetType() para obter o nome da classe que herda de Base, no nosso exemplo é a classe Usuario.Dessa forma obteremos todas as propriedades de usuários pelo método GetProperties, passando como parâmetro somente propriedades Públicas e de Instância (BindingFlags.Public e BindingFlags.Instance)
    5. Obtemos o valor da ChavePrimaria através da propriedade Key, de acordo como foi configurado na classe Usuario .
    6. No método Salvar , abriremos a conexão, implementando a classe PropertyInfo do Refletion para obter as propriedades da classe Usuario.
    7. Logo após, iremos obter somente as propriedades configuradas como UsarNoBancoDeDados na classe Usuario.
            
              using System.Reflexion;
    
              namespace Database
              {
                public class Base : IBase
                  {
              
                    private string connectionString = ConfigurationManager,AppSettings["SqlConnection"];
    
                    public string Key 
                    {
                      get 
                      {
                        foreach(PropertyInfo pi in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
                        {
                          OpcoesBase pOpcoesBase = (OpcoesBase)pi.GetCustomAttribute(typeof(OpcoesBase))
                          if (pOpcoesBase != null && pOpcoesBase.ChavePrimaria)
                          {
                            return Convert.ToString(pi.GetValue(this));
                          }
                        }
                        return null;
                      }
                    }
    
    
                    public virtual void Salvar()
                    {
                      using (SqlConnection connection = new SqlConnection(connectionstring))
                      {
                        List< string > campos = new List< string >();
                        List< string > valores = new List< string >();
    
                        foreach(PropertyInfo pi in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
                        {
                          OpcoesBase pOpcoesBase = (OpcoesBase)pi.GetCustomAttribute(typeof(OpcoesBase))
                          if (pOpcoesBase != null && pOpcoesBase.UsarNoBancoDeDados)
                          {
                            campos.Add(pi.Nome);
                            valores.Add("'" + pi.GetValue(this) + "'");
                          }
                        }
    
                        string queryString = "insert into " + this.GetType().Name + "s (" + string.Join(", ",campos.ToArray())+ ")
                                  values(" + string.Join(", ",valores.ToArray())
                                  
                        SqlCommand command = new SqlCommand(queryString, connection);
                        command.Connection.Open();
                        command.ExecuteNonQuery();
    
                      }
    
                    }
                  }
              }
             
           
  6. Criar a classe Usuario que herda de Base.

    1. Criamos uma assinatura em cima de cada propriedade de Usuario, através da classe OpcoesBase, definindo , por exemplo, se o campo é uma Chave Primaria, etc..
            
    
              namespace Database
              {
                public class Usuario : Base
                  {
                    [OpcoesBase (UsarNoBancoDeDados = true)]
                    public string Nome {get;set}
    
                    [OpcoesBase (UsarNoBancoDeDados = true)]
                    public string Telefone {get;set}
    
                    [OpcoesBase (UsarNoBancoDeDados = true, chavePrimaria = true, UsarParaBuscar = true)]
                    public string CPF {get;set;}
    
                  }
              }
             
           

Object Relational Mapping

Nesta aula iremos iniciar a criação de um ORM no C#, utilizando a classe reflection iremos varrer todas as propriedades de nossa classe criando então modelos inteligentes e ganhando agilidade no desenvolvimento.

Próximas Aulas:
assinaturaAssine nossa Comunidade

Object Relational Mapping - ORM

Object Relational Mapping é um framework que utilizamos para gerenciar o Banco de Dados.

São criadas as tabelas, comandos do Sql como insert, select, etc.

Na aula anterior, criamos a classe Usuario na camada Business, outra na camada Database, tornando o processo redundante. Com o ORM , podemos fazer de forma genérica, criando somente uma única classe Usuario em Business que "conversa" com o Database e o Database entende que essa classe é uma tabela no Banco de Dados e busca diretamente no Sql , tudo de forma dinâmica.

Então, como criamos um ORM?

Primeiro, para criar ORM precisamos entender o conceito de Reflexion.

Reflexion

Reflexion é uma classe no C# que consegue descobrir qual o nome, as propriedades e os métodos da sua classe e consegue chamar tantos os métodos quanto as propriedades. Também define atributos e, com todos esses recursos, conseguimos criar algo genérico.

No projeto ORM:

  • Em Business, criaremos a classe Usuario;
  • Em Database, criaremos:
    • A classe OpcoesBase - que são configurações dos atributos
    • A Interface IBase
    • A classe Base (que implementa IBase)
  1. Criar atributos para definir onde queremos salvar os dados

  2. Criamos uma classe OpcoesBase que herda de Attribute para criar assinaturas nas propriedades das classes, por exemplo, da classe Usuario que vamos criar mais adiante.

            
              namespace Database
              {
                public class OpcoesBase : Attribute
                  {
                    public bool UsarNoBancoDeDados {get; set;}
                    public bool UsarParaBuscar {get; set;}
                    public bool ChavePrimaria {get; set;}
                }
              }
             
           
  3. Criar uma Interface que passará por todas as camadas.É o mais genérico possível.

  4. Todas as classe que herdarem de IBase, devem implementar os métodos

            
              namespace Database
              {
                public Interface IBase
                  {
                    string Key {get;}
                    void Salvar();
                    List< IBase> Todos();
                    List< IBase> Busca();
                }
              }
             
           
  5. Criar a classe Base que implementará toda a interface.

    1. Teremos uma propriedade privada para obter a conexão.
    2. Implementar a propriedade Key, somente com get.
    3. Referenciar using System.Refletion, que dará a possibilidade de termos a informação das propriedades através da classe PropertyInfo e será utilizada na propriedade Key.
    4. Utilizamos this e o GetType() para obter o nome da classe que herda de Base, no nosso exemplo é a classe Usuario.Dessa forma obteremos todas as propriedades de usuários pelo método GetProperties, passando como parâmetro somente propriedades Públicas e de Instância (BindingFlags.Public e BindingFlags.Instance)
    5. Obtemos o valor da ChavePrimaria através da propriedade Key, de acordo como foi configurado na classe Usuario .
    6. No método Salvar , abriremos a conexão, implementando a classe PropertyInfo do Refletion para obter as propriedades da classe Usuario.
    7. Logo após, iremos obter somente as propriedades configuradas como UsarNoBancoDeDados na classe Usuario.
            
              using System.Reflexion;
    
              namespace Database
              {
                public class Base : IBase
                  {
              
                    private string connectionString = ConfigurationManager,AppSettings["SqlConnection"];
    
                    public string Key 
                    {
                      get 
                      {
                        foreach(PropertyInfo pi in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
                        {
                          OpcoesBase pOpcoesBase = (OpcoesBase)pi.GetCustomAttribute(typeof(OpcoesBase))
                          if (pOpcoesBase != null && pOpcoesBase.ChavePrimaria)
                          {
                            return Convert.ToString(pi.GetValue(this));
                          }
                        }
                        return null;
                      }
                    }
    
    
                    public virtual void Salvar()
                    {
                      using (SqlConnection connection = new SqlConnection(connectionstring))
                      {
                        List< string > campos = new List< string >();
                        List< string > valores = new List< string >();
    
                        foreach(PropertyInfo pi in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
                        {
                          OpcoesBase pOpcoesBase = (OpcoesBase)pi.GetCustomAttribute(typeof(OpcoesBase))
                          if (pOpcoesBase != null && pOpcoesBase.UsarNoBancoDeDados)
                          {
                            campos.Add(pi.Nome);
                            valores.Add("'" + pi.GetValue(this) + "'");
                          }
                        }
    
                        string queryString = "insert into " + this.GetType().Name + "s (" + string.Join(", ",campos.ToArray())+ ")
                                  values(" + string.Join(", ",valores.ToArray())
                                  
                        SqlCommand command = new SqlCommand(queryString, connection);
                        command.Connection.Open();
                        command.ExecuteNonQuery();
    
                      }
    
                    }
                  }
              }
             
           
  6. Criar a classe Usuario que herda de Base.

    1. Criamos uma assinatura em cima de cada propriedade de Usuario, através da classe OpcoesBase, definindo , por exemplo, se o campo é uma Chave Primaria, etc..
            
    
              namespace Database
              {
                public class Usuario : Base
                  {
                    [OpcoesBase (UsarNoBancoDeDados = true)]
                    public string Nome {get;set}
    
                    [OpcoesBase (UsarNoBancoDeDados = true)]
                    public string Telefone {get;set}
    
                    [OpcoesBase (UsarNoBancoDeDados = true, chavePrimaria = true, UsarParaBuscar = true)]
                    public string CPF {get;set;}
    
                  }
              }