patterncsharpMinor
EF6-Lambda Expressions deep big-tree query
Viewed 0 times
ef6queryexpressionsbigdeeplambdatree
Problem
I am looking to improve the following query.
We are using EF6 (CodeFirst) and C# Lambda Expressions, and Repository/Unit of Work patterns. Also, we needed to restrict the query in a way that we could inner-query the entities so that the query will only retrieve a subset of the joined data, and found this DynamicSelectExtensions library that extends
Query:
```
namespace Repositorios
{
public class CanalDeComunicacionRepositorio: EFRepositorioDesactivable, ICanalDeComunicacionRepositorio
{
public CanalDeComunicacionRepositorio(DbContext context) : base(context) { }
public IQueryable ConsultaParaLibreria()
{
return
dbSet.Where(canalComunicacion=> canalComunicacion.FechaDesactivacion==null)
.SelectIncluding(new List>>()
{
canalComunicacion => canalComunicacion.ListaControladores2.Where(controlador=>controlador.FechaDesactivacion==null),
canalComunicacion => canalComunicacion.ListaControladores2.Select(controlador=>controlador.ListaPuertas.Where(puerta=>puerta.FechaDesactivacion==null)),
canalComunicacion => canalComunicacion.ListaControladores2.Select(controlador=>controlador.ListaPuertas.Select( puerta=>puerta.ListaLectoras.Where(lectora=>lectora.FechaDesactivacion==null))),
canalComunicacion => canalComunicacion.ListaControladores2.Select(controlador=>controlador.ListaLectoras.Where(lectora=>lectora.FechaDesactivacion==null)),
canalComunicacion => canalComunicacion.ListaControladores2.Select(controlador=>controlador.ListaEventosExcluidos.Where(eventos=> eventos.FechaDesactivacion==null)),
canalComunicacion => canalComunicacion.ListaControladores2.Select(controlador=>controlador.ListaLectoras.Select(lectoras=>lectoras.ListaDeGruposAccesoLectora.Where(grupoLectora=>grupoLector
We are using EF6 (CodeFirst) and C# Lambda Expressions, and Repository/Unit of Work patterns. Also, we needed to restrict the query in a way that we could inner-query the entities so that the query will only retrieve a subset of the joined data, and found this DynamicSelectExtensions library that extends
IQueryable and gives us a SelectIncluding statement so that we could do this.Query:
```
namespace Repositorios
{
public class CanalDeComunicacionRepositorio: EFRepositorioDesactivable, ICanalDeComunicacionRepositorio
{
public CanalDeComunicacionRepositorio(DbContext context) : base(context) { }
public IQueryable ConsultaParaLibreria()
{
return
dbSet.Where(canalComunicacion=> canalComunicacion.FechaDesactivacion==null)
.SelectIncluding(new List>>()
{
canalComunicacion => canalComunicacion.ListaControladores2.Where(controlador=>controlador.FechaDesactivacion==null),
canalComunicacion => canalComunicacion.ListaControladores2.Select(controlador=>controlador.ListaPuertas.Where(puerta=>puerta.FechaDesactivacion==null)),
canalComunicacion => canalComunicacion.ListaControladores2.Select(controlador=>controlador.ListaPuertas.Select( puerta=>puerta.ListaLectoras.Where(lectora=>lectora.FechaDesactivacion==null))),
canalComunicacion => canalComunicacion.ListaControladores2.Select(controlador=>controlador.ListaLectoras.Where(lectora=>lectora.FechaDesactivacion==null)),
canalComunicacion => canalComunicacion.ListaControladores2.Select(controlador=>controlador.ListaEventosExcluidos.Where(eventos=> eventos.FechaDesactivacion==null)),
canalComunicacion => canalComunicacion.ListaControladores2.Select(controlador=>controlador.ListaLectoras.Select(lectoras=>lectoras.ListaDeGruposAccesoLectora.Where(grupoLectora=>grupoLector
Solution
You should replace some of your
This is also a query that is repeated way too much and that's why I placed it in a method, now let just use it:
You should also apply this concept for all other nested queries that you have. Having your queries written in this way makes your code way more readable and natural.
Selects for SelectMany. Normally IEnumerable extensions can be coded without nesting them, in your case if you replace your "grupoAcesso" selction by chaining SelectManys you could write this:private IEnumerable GetGrupoAcessoFromCanal(CanalDeComunicacion canal){
return canal.ListaControladores2
.SelectMany(controlador=>controlador.ListaLectoras)
.SelectMany(lectoras=>lectoras.ListaDeGruposAccesoLectora)
.SelectMany(grupoAcceso=>grupoAcceso.GrupoAcceso);
}This is also a query that is repeated way too much and that's why I placed it in a method, now let just use it:
dbSet.Where(canalComunicacion=> canalComunicacion.FechaDesactivacion==null)
.SelectIncluding(new List>>()
{
//all queries that don't need our method.
canalComunication => GetGrupoAcessoFromCanal(canalComunication),
canalComunication => GetGrupoAcessoFromCanal(canalComunication).Select(grupo=>grupo.ListaDeGpoPadre.Where(gpoPadre => gpoPadre.FechaDesactivacion==null)),
//so on so forth...
}You should also apply this concept for all other nested queries that you have. Having your queries written in this way makes your code way more readable and natural.
Code Snippets
private IEnumerable<?> GetGrupoAcessoFromCanal(CanalDeComunicacion canal){
return canal.ListaControladores2
.SelectMany(controlador=>controlador.ListaLectoras)
.SelectMany(lectoras=>lectoras.ListaDeGruposAccesoLectora)
.SelectMany(grupoAcceso=>grupoAcceso.GrupoAcceso);
}dbSet.Where(canalComunicacion=> canalComunicacion.FechaDesactivacion==null)
.SelectIncluding(new List<Expression<Func<CanalDeComunicacion, object>>>()
{
//all queries that don't need our method.
canalComunication => GetGrupoAcessoFromCanal(canalComunication),
canalComunication => GetGrupoAcessoFromCanal(canalComunication).Select(grupo=>grupo.ListaDeGpoPadre.Where(gpoPadre => gpoPadre.FechaDesactivacion==null)),
//so on so forth...
}Context
StackExchange Code Review Q#55241, answer score: 4
Revisions (0)
No revisions yet.