Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Capas de acceso a datos .NET escalables de verdad: el batido perfecto para el rendimiento de tus bases de datos

Detectar e implementar correctamente capas de acceso a datos .NET que escalen a las capacidades HW de la máquina

  • Login to see the comments

  • Be the first to like this

Capas de acceso a datos .NET escalables de verdad: el batido perfecto para el rendimiento de tus bases de datos

  1. 1. SOLIDQ SUMMIT MADRID 2017 #SQSummit17 Enrique Catalá | Mentor | ecatala@solidq.com | @enriquecatala Guillermo Perez | DEV | gperez@solidq.com | Capas de acceso a datos .NET escalables de verdad: el batido perfecto para el rendimiento de tus bases de datos
  2. 2. SOLIDQ SUMMIT MADRID 2017 Tipología de acceso Por conjuntos Por cursores Patrones de bajo nivel Dinámico Adhoc Parametrizable Estático Stored procedures Arquitecturas Modelo conectividad Conectada Desconectada Modelo de desarrollo Manual ORM
  3. 3. SOLIDQ SUMMIT MADRID 2017 Fundamentos • Tiempo de desarrollo • Diferencia de roles • Desarrollador vs. DBA • Independencia de la aplicación • Uso de modelo de datos • Abstracción de servidor de base de datos Másmotivos • Rechazo a T-SQL • Manejo de cadenas para acceso a datos • Errores en tiempo de ejecución vs. Compilación • Uso de lenguajes más familiares • Es más “cool”
  4. 4. SOLIDQ SUMMIT MADRID 2017
  5. 5. SOLIDQ SUMMIT MADRID 2017 Librería Método ¿Qué hace? Query.PlanCompiler .PlanCompiler Compile(cqt.DbCommandTree ctree, …….) Compila query hacia SQL Server. Coste de compilación. Aquí generalmente es donde debemos poner esfuerzos en optimizar linq Objects.Elinq.Compi ledELinqQueryState GetExecutionPlan(MergeOption? forMergeOption) Obtener plan de ejecución ya compilado previamente Objects.Elinq.ELinq QueryState GetExecutionPlan(MergeOption? forMergeOption) Obtener plan de ejecución todavía no compilado Objects.ObjectQuer y<T> GetResults(MergeOption? forMergeOption) Obtiene datos. Incluye datos GetExecutionPlan, Compile y el coste de materializar incluido. Es el coste total
  6. 6. SOLIDQ SUMMIT MADRID 2017 List<T> O(n) Dictionary<T,U> O(1)
  7. 7. SOLIDQ SUMMIT MADRID 2017 Generalmente es preferible hacer menos operaciones a la BBDD con mas conjuntos de filas
  8. 8. SOLIDQ SUMMIT MADRID 2017
  9. 9. SOLIDQ SUMMIT MADRID 2017
  10. 10. SOLIDQ SUMMIT MADRID 2017 public class MyDbContext : DbContext { //... public DbSet<Product> Products { get; set; } } var product = _dbContext.Products.Find(4); var product2 = _dbContext.Products .AsNoTracking() .Where(p => p.Id == 4) .FirstOrDefault();Implementación Dapper y EF Core
  11. 11. SOLIDQ SUMMIT MADRID 2017 using(var _dapper = new SqlConnection(config.ConnectionString)) { _dapper.Open(); var product = _dapper.Query<Product>(@" SELECT Id,Name,Col1,Col2 FROM [dbo].[Products] WHERE Id = @ProductId", new { ProductId = 4 }).FirstOrDefault(); } Implementación Dapper y EF Core
  12. 12. SOLIDQ SUMMIT MADRID 2017 var order = _dbContext.Orders .AsNoTracking() .Include(o => o.Details) .ThenInclude(d => d.Product) .Include(o => o.Customer) .Where(o => o.Id == 4); Implementación Dapper y EF Core Hierarchy Load
  13. 13. SOLIDQ SUMMIT MADRID 2017 var orders = _dapper.Query<Order, Customer, Order>( "/* Order join with customer */“ ,(order, customer) => { order.Customer = customer; return order; } , queryParam ); var details = _dapper.Query<OrderDetail, Product,OrderDetail>( "/* detail join with product */“ , (detail, product) => { detail.Product = product; return detail; } , queryParam , splitOn: "OrderId,Id“ ); foreach (var order in orders) { order.Details = detailResult .Where(d => d.OrderId == order.Id) .ToList(); } Implementación Dapper y EF Core Hierarchy Load
  14. 14. SOLIDQ SUMMIT MADRID 2017 var orders = _dapper.Query<Order, Customer, Order>( "/* Order join with customer */“ ,(order, customer) => { order.Customer = customer; return order; } , queryParam ); var details = _dapper.Query<OrderDetail, Product,OrderDetail>( "/* detail join with product */“ , (detail, product) => { detail.Product = product; return detail; } , queryParam , splitOn: "OrderId,Id“ ); //Potencialmente peligroso sin un "lock“. Si ponemos un lock, lo hacemos monothread Parallel.ForEach(orders, (order) => { order.Details = detailResult .Where(d => d.OrderId == order.Id) .ToList(); }); Implementación Dapper y EF Core Hierarchy Load
  15. 15. SOLIDQ SUMMIT MADRID 2017 var ordersList = _dapper.Query<Order, Customer, Order>( /* ... */ ); var orders = new ConcurrentDictionary<int, Order>( ordersList.ToDictionary(o => o.Id, o => o) ); var detailsList = _dapper.Query<OrderDetail, Product,OrderDetail>( /* ... */ ); var details = new ConcurrentDictionary<int, IEnumerable<OrderDetail>>( detailResult .GroupBy(d => d.OrderId) .ToDictionary( d => d.FirstOrDefault().OrderId, d => d.AsEnumerable() ) ); Parallel.ForEach(orders, (o) => { if (details.ContainsKey(o.Key)) o.Value.Details = details[o.Key].ToList(); } ); Implementación Dapper y EF Core Hierarchy Load
  16. 16. SOLIDQ SUMMIT MADRID 2017
  17. 17. SOLIDQ SUMMIT MADRID 2017
  18. 18. SOLIDQ SUMMIT MADRID 2017 • Evita dependencia entre clases con el uso de Interfaces Arquitectura de aplicación • Evita procesados fila a fila Capas de acceso a datos • La estructura de datos importa, no es todo BBDD Complejidad algorítmica • Ya no estamos en los 90. Hasta tu móvil tiene 8 núcleos ☺ Consideraciones de concurrencia • Elige con criterio y úsalo bienORMs
  19. 19. SOLIDQ SUMMIT MADRID 2017 GRACIAS!

×