Fala filhotes! Aproveitando que todo mundo esta falando sobre o Windows 8, hoje iremos falar sobre algo completamente nada a ver, é o Simple.Data.

Uma camada de acesso a dados diferente

O Simple.Data é uma camada de acesso a dados criado pelo Mark Rendle usando o novo tipo dinâmico do C#: o  dynamic.
“Camada de acesso a dados? mas então é só um clone do Nhibernate ou do Paulovich.data?”
Não, é totalmente diferente.
Antes de explicar o que a Simple.Data tem de especial, temos que entender alguns conceitos:

Dynamic

Se você já mexeu com Javascript e PHP devem ter reparado que as variáveis eram dinâmicas, ou seja podia pegar uma variável com um int e colocar uma string nela que ia funcionar normalmente. A idéia é basicamente essa, uma variável do tipo dynamic suporta qualquer operação em qualquer momento, independente do tipo do objeto. É claro que se o objeto não der suporte para a operação, uma exceção será gerada.

tipodinamico1ou a versão nerd aqui.

“Mas como assim? uma variável do tipo Object já não consegue instanciar qualquer tipo de classe?”
Sim, mas se você não souber o tipo você não consegue executar o método / propriedade do objeto (exceto usando Reflection). Vamos a um exemplo mais pratico:

image

A Dynamic dispensa conversões e abre uma nova gama de possibilidades ao .NET ( como a biblioteca que estamos vendo).
Para saber mais, recomendo o Macoratti e o site da MSDN.

O/RM

Um O/RM (Também conhecido como ORM ou Objeto-Relacional ou Mapeamento de objeto relacional) é uma técnica de desenvolvimento com o objetivo de fazer o intermediário entre o banco de dados e seu código. Um ORM controla suas conexões com o banco além de possibilitar acessar os dados do banco apenas referenciando objetos, ou alterar/inserir registros passando só o seu objeto, o ORM cuida das querys, você só chama os métodos.
No ORM você tem que ter uma classe que será vinculada com a respectiva tabela. No caso se tivermos uma tabela Empresa e quisermos acessar ela pelo código, precisamos de uma classe Empresa com os mesmos campos (propriedades) que as colunas da tabela:

diagrama_orm

Exemplo de uso de um ORM (Paulovich.Data):

// Instancio minha classe User que esta mapeada com a tabela Usuario
// do meu banco. Então o Paulovich ja pega o usuario de codigo (PK) 3
// E ja preenche o meu objeto. Isso tudo só por eu ter instanciado
// ele passando um paramêtro
User usuario = new User(3);
// Altero o nome do usuario
usuario.Name = "André Alterado";
// Salvo o camarada. Nem tive que fazer nada no método Save, o
// framework que se preocupa com as querys.
usuario.Save();

Para saber mais sobre ORM aconselho esse post: http://www.dicas-l.com.br/freedb/freedb_20100315.php

Ferramentas

tool Nesse exemplo usarei o Visual Studio e o Simple.Data (que baixarei pelo NuGet). Mas o Simple.Data pode ser usado em qualquer projeto .NET, se encaixando muito bem  projetos menores como os criados pelo WebMatrix.

 

 

Simple.Data

– “Então o Simple.Data é mais um ORM?“

Não.

Como dito antes o Simple.Data é uma camada de acesso a dados, mas NÃO É UM ORM. Ele parece um ORM mas não precisa de objetos nem de um banco de dados relacional e nem de nenhum mapeamento. Ou seja, não tem nem o O nem o R e nem o M do ORM.

“Certo…ORM que não é ORM…Mas então filho, me explica, como eu uso esse trem?”

Te explico agora meu caro.

Pegando o Simple.Data

O primeiro passo é pegar o Simple.Data no Nuget:

simple.data1

Modo visual do Nuget

É importante lembrar que você deve pegar a versão do Simple.Data que usa o seu provider de  banco de dados, no nosso exemplo estou usando o Simple.Data do SQL Server. Mas a cada dia que passa o Mark lança mais providers para todo tipo de Banco bizarro e diferente, ate mesmo bancos de dados já orientados a objeto.

A Classe Database

Antes de fazer qualquer coisa no Simple.Data você precisará de um objeto do tipo Database. Ele que controla as conexões e executa as querys. É o pilar do Simple.Data.

Há varias maneira de instancia-lo:

// Cria uma database usando a conexão padrão no webconfig
var db = Database.Open(); 

// Abre uma conexão com um banco do sql compact
var db = Database.OpenFile("banco.sdf"); 

// Abre uma conexão com uma connectino string especifica
var db = Database.OpenConnection("data source=.\SQLEXPRESS;initial catalog=dbLoop2;integrated security=true");

No caso da conexão padrão, você irá precisar de uma Connection String com o nome de Simple.Data.Properties.Settings.DefaultConnectionString:

<connectionStrings>
    <add name="Simple.Data.Properties.Settings.DefaultConnectionString" connectionString="data source=.\SQLEXPRESS;initial catalog=dbLoop;integrated security=true" providerName="System.Data.SqlClient"/>
</connectionStrings>

Ao contrario do nosso Connection do .NET, não precisamos abrir/fechar o nosso Database, ele controla tudo automático. Por isso você pode deixar o objeto instanciado sem problemas.

Agora estamos prontos para o nosso exemplo:

Tabelas

No nosso exemplo teremos 3 tabelas:

diagrama

Então como acessaríamos isso? Nos ORMs mais utilizados nós costumávamos criar uma classe POCO com as mesmas propriedades e associávamos ela a tabela com um arquivo de configuração ou atributos. Dessa vez não.

Fazendo o Select

Agora que já temos um objeto Database podemos ter acesso ao banco de uma maneira muito simples, basta seguir a sintaxe:

[Objeto Database].[Tabela].[Comando com os parâmetros]

Por exemplo, para selecionar o usuário de código 1 usaríamos o comando FindBy mais o nome do campo e o parâmetro a ser usado, assim:

// Sendo que db é o nosso Database
var user = db.Usuario.FindByCodUsuario(1);

Em tempo de execução o Simple.Data procurará o registro com o campo CodUsuario de valor 1 na tabela Usuario. O retorno será um dynamic preenchido com os dados do Usuário, basta chamar as propriedades do objeto para ver que esta devidamente preenchido:

if (string.IsNullOrEmpty(user.Blog))
// Retorna o nome do usuario
return user.NomeUsuario;

// Ou retorna o Blog se existir
return user.Blog;

Entendeu o esquema? Graças a variável dinâmica conseguimos invocar esses métodos “inexistentes”, deixando assim, o Simple.Data bem fácil de ser compreendido. Vamos a mais exemplos:

// Procurando por mais de um campo (basta adicionar um "And")
var user = db.Usuario.FindByDataNascimentoAndBlog(Convert.ToDateTime("16/06/1988"), "https://100loop.com");

O Find retorna apenas um objeto, então se você quiser uma consulta que retorna mais de um registro você pode usar o FindAll (que funciona da mesma maneira) e retorna um IEnumerable<dynamic>.

Vamos a mais vários exemplos do simple.data:

// Usando o Like
var users = db.Usuario.FindAll(db.Usuario.NomeUsuario.Like("Andre%"));// Select * from Usuario where NomeUsuario like ‘Andre%’

Usando Operadores:

// Usando operadores
var users = db.Usuario.FindAll(db.Usuario.NomeUsuario.Like("Gil%") || db.Usuario.Blog = "https://100loop.com");// Select * from Usuario where NomeUsuario like ‘Andre%’ or Blog = 'https://100loop.com'
// Pode-se usar o &&, || alem de agrupar as expressões usando parênteses
foreach (var item in users)
{
Console.WriteLine(item.NomeUsuario);
}

Pesquisa usando relacionamento:

// Pego o endereço do usuario de codigo 1
var address = db.Endereco.Find(db.Endereco.Usuario.CodUsuario == 1);
// Dados da rua
string ruaUsuario = address.Rua;
// Graças a chave estrangeira tenho acesso tb aos dados dos usuarios
string nomeUsuario = address.Usuario.NomeUsuario;

Se quiser você ainda tem a opção de usar o POCO, basta criar uma classe com as mesmas propriedades da tabela do banco:

NossaClasse:

 public class User
    {
        public int CodUsuario { get; set; }

        public string NomeUsuario { get; set; }

        public DateTime DataNascimento { get; set; }

        public string Blog { get; set; }

        // Não sera preenchida pois não existe no banco
        public int Idade { get; set; }
    }

E para usar ela:

// As propriedades são auto-mapeadas
User usuario = (User)db.Usuario.FindByCodUsuario(1);

O resto do CRUD

Há varias maneiras de inserir/atualizar um registro:

// Criamos um ExpandoObject, que é um objeto dinâmico sem nada, que podemos adicionar métodos/propriedades
// Para mais detalhes: http://msdn.microsoft.com/pt-br/library/system.dynamic.expandoobject.aspx
dynamic user = new ExpandoObject();
// Adicionamos o Nome
user.NomeUsuario = "Ivan P";
user.Blog = "100loop.com";
// Insere o usuario
db.Usuario.Insert(user);

Atualizando com o ExpandoObject:

// Criamos um ExpandoObject, que é um objeto dinâmico sem nada, que podemos adicionar métodos/propriedades
// Para mais detalhes: http://msdn.microsoft.com/pt-br/library/system.dynamic.expandoobject.aspx
dynamic user = new ExpandoObject();
// Adicionamos o Nome
user.NomeUsuario = "Gil Atualizado";
user.CodUsuario = 3;
// Damos um UpdateBy nome da coluna
// Ele SÓ atualizará os campos que você especificou no objeto, ou seja,
// nesse caso ele só irá alterar o nome do sujeito, deixando os outros campos com os valores
// que já estavam lá
db.Usuario.UpdateByCodUsuario(user);

Você pode usar o seu objeto POCO:

User usuario = new User();
usuario.NomeUsuario = "André P";
usuario.DataNascimento = DateTime.Now;
usuario.Blog = "100loop.com";
db.Usuario.Insert(usuario);

Atualizando:

// Quando você usa um POCO para atualizar, ele ira atualizar todos os campos
// que a classe possui, por isso vamos dar um find primeiro, e só alterar
// o campo que queremos
User usuario = (User)db.Usuario.FindByCodUsuario(3);
usuario.NomeUsuario = "Jose";
// Quando a tabela tem chave primária, o update por padrão procura o registro
// com o mesmo valor na coluna primaria (CodUsuario).
db.Usuario.Update(usuario);

Ou ainda pode usar só os parâmetros nomeados:

// Insere sem a necessidade de usar um objeto
db.Usuario.Insert(NomeUsuario: "Novo usuario", Blog: "semblog.com");
// Atualiza sem precisar usar um objeto
db.Usuario.UpdateByCodUsuario(NomeUsuario: "Jose Atualizado", CodUsuario: 3);

Pronto! Mas e para excluir? Funciona exatamente do mesmo jeito:

// Deleto pelo CodUsuario
db.Usuario.DeleteByCodUsuario(3);

Conclusão

O Simple.Data é excelente para projetos pequenos (típico dos projetos criados pelo WebMatrix), já que você não irá precisar de uma camada a mais no seu projeto nem ficar preocupando com o mapeamento das classes.

Considerações Finais

O Simple.Data é bastante extenso e se você quiser se aprofundar nele visite os links abaixo. Espero que tenham gostado do artigo, até mais!

Atualizado[19/10/2011]: Uma detalhe que o Mark falou: muitos dos providers do Simple.Data (tirando o SQL Server e o SQL Server Compact) foram contribuições da própria comunidade (criados por desenvolvedores diferentes).

Referências

Documentação – http://simplefx.org/simpledata/docs/

Wiki – https://github.com/markrendle/Simple.Data/wiki

Blog do Mark Rendle – http://blog.markrendle.net/