Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/gnobroga/dapper
Nesse repositório, eu testo o micro ORM Dapper.
https://github.com/gnobroga/dapper
Last synced: 14 days ago
JSON representation
Nesse repositório, eu testo o micro ORM Dapper.
- Host: GitHub
- URL: https://github.com/gnobroga/dapper
- Owner: GNobroga
- Created: 2024-02-01T17:58:49.000Z (11 months ago)
- Default Branch: master
- Last Pushed: 2024-02-02T13:03:22.000Z (11 months ago)
- Last Synced: 2024-04-09T15:11:51.946Z (9 months ago)
- Language: C#
- Homepage:
- Size: 36.1 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Testando o Dapper
Neste projeto, desenvolvo uma pequena API com a abordagem minimalista, utilizando o Dapper como ORM para mapear as colunas para um objeto de destino. No contexto dessa implementação, faço uso de diferentes formas de relacionamento, como One-to-One, One-to-Many e Many-to-Many.
## Tour pelo código
No código abaixo, crio uma classe base para que as classes que a implementam possam utilizar o método **AtomicOperation**. Este método recebe como parâmetro uma callback contendo a operação que será realizada e envolve a operação dentro de um bloco Try-Catch. O método, por sua vez, já utiliza os comandos commit ou rollback para garantir a integridade dos dados.
```cs
public abstract class ConnectionFactoryBase : IConnectionFactory
{
protected readonly IDbConnection _connection;public IDbConnection Connection => _connection;
private IDbTransaction? _transaction;
public ConnectionFactoryBase(IDbConnection dbConnection)
{
_connection = dbConnection;
_connection.Open();
}public async Task AtomicOperation(Func> callback)
{
_transaction = _connection.BeginTransaction();
try
{
var result = callback(_transaction!);
_transaction!.Commit();
return await result;
}
catch
{
_transaction!.Rollback();
throw;
}
finally
{
_connection.Close();
}
}
}
```Classe que irá implementa a classe abstrata acima
```cs
public class SqliteConnectionFactory : ConnectionFactoryBase
{
public SqliteConnectionFactory() : base(new SqliteConnection("Data Source=app.db"))
{}
}
```## Relacionamentos
No código abaixo eu faço um SQL que faz vários JUNÇÃO de algumas tabelas e o Dapper através de uma função callback mapeia os objetos para dentro da minha lista de usuarios. O Dapper faz o SplitOn no Id como padrão, ou seja, se o Id das tabelas forem diferentes no banco isso pode me gerar uma exception caso eu não especifique esse parâmetro para o método Query. Além disso, a ordem como é trazido os dados importam no genéric do **QueryAsync**.
```cs
public async Task FindByIdAsync(int id, CancellationToken cancellationToken = default)
{
var sql = """
SELECT u.*, c.*, ee.*, d.* FROM
Usuarios u
LEFT JOIN Contatos c ON C.UsuarioId = u.Id
LEFT JOIN EnderecosEntrega ee ON ee.UsuarioId = u.Id
INNER JOIN UsuariosDepartamentos ud ON ud.UsuarioId = u.Id
INNER JOIN Departamentos d ON d.Id = ud.DepartamentoId
WHERE u.Id = @id;
""";List usuarios = [];
await _connection.QueryAsync(sql, (usuario, contato, enderecoEntrega, departamento) => {
if (!usuarios.Any(x => x.Id == usuario.Id))
{
usuario.EnderecoEntregas ??= [];
usuario.Contato = contato;
usuarios.Add(usuario);
}
else
{
usuario = usuarios.Find(x => x.Id == usuario.Id)!;
}usuario.EnderecoEntregas.Add(enderecoEntrega);
if (!usuario.Departamentos.Any(x => x.Id == departamento.Id))
{
usuario.Departamentos.Add(departamento);
}
return usuario;
}, new { id });return usuarios.FirstOrDefault();
}```
## Multiplo ResultSets
É possível fazer múltiplas consultas no Dapper usando o **QueryMultiple**. Muito útil pra criar relatórios.
```sql
SELECT * FROM Usuarios WHERE Id = @Id;
SELECT * FROM Contatos WHERE UsuarioId = @Id;
SELECT * FROM EnderecosEntrega WHERE UsuarioId = @Id;
SELECT D.* FROM UsuariosDepartamentos UD INNER JOIN Departamentos D ON UD.Departamento.Id = D.Id WHERE UD.UsuarioId = @Id;
``````cs
var resultSets = await _connection.QueryMultipleAsync(sql, new { Id = 1 });
var usuario = resultSets.Read().SingleOrDefault();
var contato = resultSets.Read().SingleOrDefault();
var enderecosEntrega = resultSets.Read().ToList();
var departamentos = resultSets.Read().ToList();
```## Utilizando Stored Procedure
É possível executar Store Procedure, é possível passar parâmetros também.
```cs
_connection.Query("StoreProcedureName", commandType: CommandType.StoredProcedure);
```
## Biblioteca FluentMapPermite mapear colunas com nomes diferentes das propriedades, pois o Dapper ele mapeia as colunas se baseando no nome da Propriedade, independente se estiver LowerCase, UpperCase, etc.
```cs
var usuarios = _connection.Query("SELECT * FROM Usuarios;");
``````cs
public class UsuarioMap : EntityMap
{
public UsuarioMap()
{
Map(x => x.Property).ToColumn("ColumnName");
}
}FluentMapper.Initialize(config => config.AddMap(new UsuarioMap()));
```
## Helpful Packages
. Dapper.Contrib - Pacote que extende o Dapper com operações de um CRUD básico.