DataAccess
El componente DataAccess
contienen una lista de métodos que nos permiten relacionarnos con la base de datos.
Para su utilización se recomienda agregar el siguiente método en el componente que ya utiliza DataAccessRegistry
, lo cual nos facilitara el uso del mismo.
/// <summary>
/// Convenience method
/// </summary>
private IDataAccess DataAccess => _dataAccessRegistry.GetDataAccess();
CRUD (Create, Read, Update and Delete)¶
Como se menciono anteriormente, el micro-orm esta basado en Dapper, el cual no contienen de forma nativa toda la parte de Mapping que necesitamos para utilizar métodos CRUD, el componente DataAccess
incorpora estos métodos utilizando la libreria Dapper-Extensions. A continuación se detallan los métodos CRUD que ofrece este componente:
dynamic Insert<T>(T entity) where T : class;
bool Update<T>(T entity) where T : class;
bool Delete<T>(T entity) where T : class;
T Get<T>(object id) where T : class;
IList<T> GetAll<T>() where T : class;
IList<T> Select<T>(object predicate) where T : class;
IList<T> GetSet(object predicate, IList<ISort> sort, int firstResult, int maxResults, int? commandTimeout = null, bool buffered = false) where T : class;
IList<T> GetPage<T>(object predicate, IList<ISort> sort, int page, int resultsPerPage, int? commandTimeout = null, bool buffered = false) where T : class;
int Count<T>(object predicate, int? commandTimeout = null) where T : class;
Mapping¶
Para hacer uso de los mismos, deberemos agregar una clase de Mapping por cada entidad, ejemplo:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateCreated { get; set; }
public bool Active { get; set; }
public IEnumerable<Phone> Phones { get; private set; }
}
public class Phone
{
public int Id { get; set; }
public string Value { get; set; }
}
public class PersonMapper : ClassMapper<Person>
{
public PersonMapper()
{
Table("Person");
Map(c => c.Id).Key(KeyType.Assigned);
Map(m => m.Phones).Ignore();
Map(m => m.DateCreated).Column("Created_Date");
AutoMap();
}
}
DataAccessRegistry
en la opción MappersAssemblies.
Query Methods¶
Tambien contamos con métodos para la ejecución de queries, los cuales son extensiones de los métodos nativos de Dapper y la documentacion aplica para estos metodos.
void QueryMultiple(string sql, Action<GridReader> map, object param = null);
IEnumerable<TReturn> Query<TReturn>(string sql, object param = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null);
void ExecuteNonQuery(string sql, object param = null, CommandType? commandType = null);
TResult ExecuteScalar<TResult>(string sql, object param = null, int? commandTimeout = null, CommandType? commandType = null);
Many-To-Many¶
Imaginemos el siguiente escenario en donde tenemos una entidad Tracking que a su vez tiene una lista de la entidad Novedad:
public class Tracking
{
public int Id { get; set; }
public string Estado { get; set; }
public IList<Novedad> Novedades { get; set; }
}
public class Novedad
{
public int Id { get; set; }
public string Evento { get; set; }
public int Tracking_Id { get; set; }
}
QueryMultiple
y dentro del mismo podemos hacer uso del metodo extendido Lookup
(namespace Infrastructure.Data
) de la siguiente manera:
string sql = @"SELECT t.*, n.* FROM tracking t LEFT JOIN novedad n on n.tracking_id = t.id where t.id < 2319960";
IEnumerable<Tracking> trackings = default(IEnumerable<Tracking>);
DataAccess.QueryMultiple(sql, reader =>
{
trackings = reader.Lookup<Tracking, Novedad, int>(t => t.Id, t =>
{
t.Novedades = t.Novedades ?? new List<Novedad>();
return t.Novedades;
});
});
QueryMultiple
tiene 2 argumentos, el primero es la query en donde obtendremos la lista de trackings y las novedades para cada tracking, y el segundo argumento es un Action<GridReader>
en donde podremos implementar una lógica para mapear el resultado. En esta función es donde podemos utilizar el metodo Lookup<TMain, TSecond, TKey>
, en donde deberemos especificar el tipo de la entidad principal, el tipo de la colleccion de la entidad principal, y el tipo del identificador de la entidad principal, luego como parametro tenemos 2 funciones:
* En la primera Func<TMain, TKey> lookupId
recibiremos como parámetro la entidad principal y deberemos devolver el identificador unico de esta entidad. En nuestro caso es la propiedad id del tracking.
* La segunda Func<TMain, IList<TSecond>> lookupSecond
es una función en donde recibiremos como parámetro la entidad principal y deberemos devolver la lista destino en donde almacenaremos cada una de las novedades. (En en ejemplo a no poder asegurar que la lista no sea nula al momento de crear el tracking, realizamos una inicializacion de la misma en caso de ser necesario)
Luego de la ejecución el método Lookup
nos retornara la lista de tracking con sus respectivas novedades.