EF Core How to filter a nested many-to-many list by another list










3















Using .Net Core 2.1 and EF Core 2.1.4



I'm trying to grab all the nested records of an object if any of those records contains a name that I have in a list, and only objects that have matching nested records.



I have a query that is producing the right results, but it's performing a query for every single record in the database table.



I'm hoping to reduce it further, if possible.



My ViewModels (actual models are nearly identical):



EventViewModel



using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace MyProject.Models.ViewModels

public class EventViewModel

private string _name;

public Guid Id get; set;

[Required, StringLength(100)]
public string Name

get => _name?.Trim();
set => _name = value?.Trim();


[DataType(DataType.Date)]
public DateTime Date get; set;

[Display(Name = "Programs")]
public IEnumerable<EventProgramViewModel> EventProgramViewModels get; set;

public string AllProgramNames

get

string result = EventProgramViewModels.Aggregate(string.Empty,
(current, program) => current + $"program?.ProgramViewModel?.Name, ");
return result.TrimEnd(',', ' ');



public EventViewModel()

Id = Guid.NewGuid();
Date = DateTime.Now;
EventProgramViewModels = new List<EventProgramViewModel>();





EventProgramViewModel



using System;

namespace MyProject.Models.ViewModels

public class EventProgramViewModel

public Guid EventViewModelId get; set;
public EventViewModel EventViewModel get; set;

public Guid ProgramViewModelId get; set;
public ProgramViewModel ProgramViewModel get; set;




ProgramViewModel



using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace MyProject.Models.ViewModels

public class ProgramViewModel

private string _name;

public Guid Id get; set;

[Required, StringLength(100)]
[Display(Name = "Program Name")]
public string Name

get => _name?.Trim();
set => _name = value?.Trim();





In my ApplicationDbContext.cs file I have this mapped like so:



modelBuilder.Entity<EventProgram>()
.HasKey(eventProgram => new eventProgram.EventId, eventProgram.ProgramId);


Finally, here is my query:



var testQuery = context.Events
.AsNoTracking()
.Select(e => new EventViewModel

Id = e.Id,
Name = e.Name,
Date = e.Date,
EventProgramViewModels = e.EventPrograms.Select(eventProgram =>
new EventProgramViewModel

ProgramViewModel = new ProgramViewModel

Name = eventProgram.Program.Name

)
)
.OrderByDescending(eventViewModel => eventViewModel.Date)
.ThenBy(eventViewModel => eventViewModel.Name)
.Where(eventViewModel =>
!search.ProgramsChosen.Any() || eventViewModel.EventProgramViewModels.Any(
eventProgramViewModel =>
search.ProgramsChosen.Contains(eventProgramViewModel.ProgramViewModel
.Name)))
.ToList()
;

foreach (var item in testQuery)

// Mock usage to show where queries are generated
_loggingServices.LogInformation(JsonConvert.SerializeObject(item));



This produces one EF query for the main Event properties:



SELECT [e].[Id], [e].[Name], [e].[Date]
FROM [Events] AS [e]
ORDER BY [e].[Date] DESC, [e].[Name]


And 1 for each result (in this case, in the above foreach loop)



SELECT [eventProgram.Program].[Name]
FROM [EventPrograms] AS [eventProgram]
INNER JOIN [Programs] AS [eventProgram.Program] ON [eventProgram].[ProgramId] = [eventProgram.Program].[Id]
WHERE @_outer_Id = [eventProgram].[EventId]


Is there any way I can improve this performance?




Update 1:



Based on TyCobb's comment I changed the query structure to:



var testQuery =
context.Events
.AsNoTracking()
.OrderByDescending(@event => @event.Date)
.ThenBy(@event => @event.Name)
.Where(@event =>
!search.ProgramsChosen.Any() || @event.EventPrograms.Any(
eventProgramViewModel =>
search.ProgramsChosen.Contains(eventProgramViewModel.Program
.Name)))
.Select(e => new EventViewModel

Id = e.Id,
Name = e.Name,
Date = e.Date,
EventProgramViewModels = e.EventPrograms.Select(eventProgram =>
new EventProgramViewModel

ProgramViewModel = new ProgramViewModel

Name = eventProgram.Program.Name

)
)
;


Which is better, as it only produces a query for each valid record, where before it would do every record regardless.



This now produces this one query:



SELECT [event].[Id], [event].[Name], [event].[Date]
FROM [Events] AS [event]
WHERE EXISTS (
SELECT 1
FROM [EventPrograms] AS [eventProgramViewModel]
INNER JOIN [Programs] AS [eventProgramViewModel.Program] ON [eventProgramViewModel].[ProgramId] = [eventProgramViewModel.Program].[Id]
WHERE [eventProgramViewModel.Program].[Name] IN (N'A SEARCHED PROGRAM NAME') AND ([event].[Id] = [eventProgramViewModel].[EventId]))
ORDER BY [event].[Date] DESC, [event].[Name]


And one for each valid record:



SELECT [eventProgram.Program].[Name]
FROM [EventPrograms] AS [eventProgram]
INNER JOIN [Programs] AS [eventProgram.Program] ON [eventProgram].[ProgramId] = [eventProgram.Program].[Id]
WHERE @_outer_Id = [eventProgram].[EventId]









share|improve this question



















  • 1





    Try to do all filtering/ordering before your Select. The way it currently is written, it needs to get everything and map it to your view model and then it will filter based on your view model's properties.You want to try and have your select be the last thing it does.

    – TyCobb
    Nov 14 '18 at 18:53











  • @TyCobb I've updated my question to reflect your suggested changes, it is definitely better, but I'm still producing a query for each valid record. I'll build my other queries with this tip in mind though, thank you!

    – Ryan Taite
    Nov 14 '18 at 19:17












  • Not too sure. It's being treated as lazy loaded even though you mapped to a non-entity. You could try turning lazy loading off if you have it on and also try to do an Include(...) for your events children that you are using.

    – TyCobb
    Nov 14 '18 at 19:26











  • Don't have Lazy Loading turned on, and the Include is unnecessary and was ignored because the navigation is not reachable in the final query results

    – Ryan Taite
    Nov 14 '18 at 19:41











  • @TyCobb I was able to figure it out. Adding .ToList() to EventProgramsViewModels = ....Select(... => new EventProgramViewModel ... ) did the trick. I had tried it before, but got errors every time, but no longer after moving my OrderyBy() and Where() to the top of my query.

    – Ryan Taite
    Nov 14 '18 at 19:54















3















Using .Net Core 2.1 and EF Core 2.1.4



I'm trying to grab all the nested records of an object if any of those records contains a name that I have in a list, and only objects that have matching nested records.



I have a query that is producing the right results, but it's performing a query for every single record in the database table.



I'm hoping to reduce it further, if possible.



My ViewModels (actual models are nearly identical):



EventViewModel



using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace MyProject.Models.ViewModels

public class EventViewModel

private string _name;

public Guid Id get; set;

[Required, StringLength(100)]
public string Name

get => _name?.Trim();
set => _name = value?.Trim();


[DataType(DataType.Date)]
public DateTime Date get; set;

[Display(Name = "Programs")]
public IEnumerable<EventProgramViewModel> EventProgramViewModels get; set;

public string AllProgramNames

get

string result = EventProgramViewModels.Aggregate(string.Empty,
(current, program) => current + $"program?.ProgramViewModel?.Name, ");
return result.TrimEnd(',', ' ');



public EventViewModel()

Id = Guid.NewGuid();
Date = DateTime.Now;
EventProgramViewModels = new List<EventProgramViewModel>();





EventProgramViewModel



using System;

namespace MyProject.Models.ViewModels

public class EventProgramViewModel

public Guid EventViewModelId get; set;
public EventViewModel EventViewModel get; set;

public Guid ProgramViewModelId get; set;
public ProgramViewModel ProgramViewModel get; set;




ProgramViewModel



using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace MyProject.Models.ViewModels

public class ProgramViewModel

private string _name;

public Guid Id get; set;

[Required, StringLength(100)]
[Display(Name = "Program Name")]
public string Name

get => _name?.Trim();
set => _name = value?.Trim();





In my ApplicationDbContext.cs file I have this mapped like so:



modelBuilder.Entity<EventProgram>()
.HasKey(eventProgram => new eventProgram.EventId, eventProgram.ProgramId);


Finally, here is my query:



var testQuery = context.Events
.AsNoTracking()
.Select(e => new EventViewModel

Id = e.Id,
Name = e.Name,
Date = e.Date,
EventProgramViewModels = e.EventPrograms.Select(eventProgram =>
new EventProgramViewModel

ProgramViewModel = new ProgramViewModel

Name = eventProgram.Program.Name

)
)
.OrderByDescending(eventViewModel => eventViewModel.Date)
.ThenBy(eventViewModel => eventViewModel.Name)
.Where(eventViewModel =>
!search.ProgramsChosen.Any() || eventViewModel.EventProgramViewModels.Any(
eventProgramViewModel =>
search.ProgramsChosen.Contains(eventProgramViewModel.ProgramViewModel
.Name)))
.ToList()
;

foreach (var item in testQuery)

// Mock usage to show where queries are generated
_loggingServices.LogInformation(JsonConvert.SerializeObject(item));



This produces one EF query for the main Event properties:



SELECT [e].[Id], [e].[Name], [e].[Date]
FROM [Events] AS [e]
ORDER BY [e].[Date] DESC, [e].[Name]


And 1 for each result (in this case, in the above foreach loop)



SELECT [eventProgram.Program].[Name]
FROM [EventPrograms] AS [eventProgram]
INNER JOIN [Programs] AS [eventProgram.Program] ON [eventProgram].[ProgramId] = [eventProgram.Program].[Id]
WHERE @_outer_Id = [eventProgram].[EventId]


Is there any way I can improve this performance?




Update 1:



Based on TyCobb's comment I changed the query structure to:



var testQuery =
context.Events
.AsNoTracking()
.OrderByDescending(@event => @event.Date)
.ThenBy(@event => @event.Name)
.Where(@event =>
!search.ProgramsChosen.Any() || @event.EventPrograms.Any(
eventProgramViewModel =>
search.ProgramsChosen.Contains(eventProgramViewModel.Program
.Name)))
.Select(e => new EventViewModel

Id = e.Id,
Name = e.Name,
Date = e.Date,
EventProgramViewModels = e.EventPrograms.Select(eventProgram =>
new EventProgramViewModel

ProgramViewModel = new ProgramViewModel

Name = eventProgram.Program.Name

)
)
;


Which is better, as it only produces a query for each valid record, where before it would do every record regardless.



This now produces this one query:



SELECT [event].[Id], [event].[Name], [event].[Date]
FROM [Events] AS [event]
WHERE EXISTS (
SELECT 1
FROM [EventPrograms] AS [eventProgramViewModel]
INNER JOIN [Programs] AS [eventProgramViewModel.Program] ON [eventProgramViewModel].[ProgramId] = [eventProgramViewModel.Program].[Id]
WHERE [eventProgramViewModel.Program].[Name] IN (N'A SEARCHED PROGRAM NAME') AND ([event].[Id] = [eventProgramViewModel].[EventId]))
ORDER BY [event].[Date] DESC, [event].[Name]


And one for each valid record:



SELECT [eventProgram.Program].[Name]
FROM [EventPrograms] AS [eventProgram]
INNER JOIN [Programs] AS [eventProgram.Program] ON [eventProgram].[ProgramId] = [eventProgram.Program].[Id]
WHERE @_outer_Id = [eventProgram].[EventId]









share|improve this question



















  • 1





    Try to do all filtering/ordering before your Select. The way it currently is written, it needs to get everything and map it to your view model and then it will filter based on your view model's properties.You want to try and have your select be the last thing it does.

    – TyCobb
    Nov 14 '18 at 18:53











  • @TyCobb I've updated my question to reflect your suggested changes, it is definitely better, but I'm still producing a query for each valid record. I'll build my other queries with this tip in mind though, thank you!

    – Ryan Taite
    Nov 14 '18 at 19:17












  • Not too sure. It's being treated as lazy loaded even though you mapped to a non-entity. You could try turning lazy loading off if you have it on and also try to do an Include(...) for your events children that you are using.

    – TyCobb
    Nov 14 '18 at 19:26











  • Don't have Lazy Loading turned on, and the Include is unnecessary and was ignored because the navigation is not reachable in the final query results

    – Ryan Taite
    Nov 14 '18 at 19:41











  • @TyCobb I was able to figure it out. Adding .ToList() to EventProgramsViewModels = ....Select(... => new EventProgramViewModel ... ) did the trick. I had tried it before, but got errors every time, but no longer after moving my OrderyBy() and Where() to the top of my query.

    – Ryan Taite
    Nov 14 '18 at 19:54













3












3








3








Using .Net Core 2.1 and EF Core 2.1.4



I'm trying to grab all the nested records of an object if any of those records contains a name that I have in a list, and only objects that have matching nested records.



I have a query that is producing the right results, but it's performing a query for every single record in the database table.



I'm hoping to reduce it further, if possible.



My ViewModels (actual models are nearly identical):



EventViewModel



using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace MyProject.Models.ViewModels

public class EventViewModel

private string _name;

public Guid Id get; set;

[Required, StringLength(100)]
public string Name

get => _name?.Trim();
set => _name = value?.Trim();


[DataType(DataType.Date)]
public DateTime Date get; set;

[Display(Name = "Programs")]
public IEnumerable<EventProgramViewModel> EventProgramViewModels get; set;

public string AllProgramNames

get

string result = EventProgramViewModels.Aggregate(string.Empty,
(current, program) => current + $"program?.ProgramViewModel?.Name, ");
return result.TrimEnd(',', ' ');



public EventViewModel()

Id = Guid.NewGuid();
Date = DateTime.Now;
EventProgramViewModels = new List<EventProgramViewModel>();





EventProgramViewModel



using System;

namespace MyProject.Models.ViewModels

public class EventProgramViewModel

public Guid EventViewModelId get; set;
public EventViewModel EventViewModel get; set;

public Guid ProgramViewModelId get; set;
public ProgramViewModel ProgramViewModel get; set;




ProgramViewModel



using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace MyProject.Models.ViewModels

public class ProgramViewModel

private string _name;

public Guid Id get; set;

[Required, StringLength(100)]
[Display(Name = "Program Name")]
public string Name

get => _name?.Trim();
set => _name = value?.Trim();





In my ApplicationDbContext.cs file I have this mapped like so:



modelBuilder.Entity<EventProgram>()
.HasKey(eventProgram => new eventProgram.EventId, eventProgram.ProgramId);


Finally, here is my query:



var testQuery = context.Events
.AsNoTracking()
.Select(e => new EventViewModel

Id = e.Id,
Name = e.Name,
Date = e.Date,
EventProgramViewModels = e.EventPrograms.Select(eventProgram =>
new EventProgramViewModel

ProgramViewModel = new ProgramViewModel

Name = eventProgram.Program.Name

)
)
.OrderByDescending(eventViewModel => eventViewModel.Date)
.ThenBy(eventViewModel => eventViewModel.Name)
.Where(eventViewModel =>
!search.ProgramsChosen.Any() || eventViewModel.EventProgramViewModels.Any(
eventProgramViewModel =>
search.ProgramsChosen.Contains(eventProgramViewModel.ProgramViewModel
.Name)))
.ToList()
;

foreach (var item in testQuery)

// Mock usage to show where queries are generated
_loggingServices.LogInformation(JsonConvert.SerializeObject(item));



This produces one EF query for the main Event properties:



SELECT [e].[Id], [e].[Name], [e].[Date]
FROM [Events] AS [e]
ORDER BY [e].[Date] DESC, [e].[Name]


And 1 for each result (in this case, in the above foreach loop)



SELECT [eventProgram.Program].[Name]
FROM [EventPrograms] AS [eventProgram]
INNER JOIN [Programs] AS [eventProgram.Program] ON [eventProgram].[ProgramId] = [eventProgram.Program].[Id]
WHERE @_outer_Id = [eventProgram].[EventId]


Is there any way I can improve this performance?




Update 1:



Based on TyCobb's comment I changed the query structure to:



var testQuery =
context.Events
.AsNoTracking()
.OrderByDescending(@event => @event.Date)
.ThenBy(@event => @event.Name)
.Where(@event =>
!search.ProgramsChosen.Any() || @event.EventPrograms.Any(
eventProgramViewModel =>
search.ProgramsChosen.Contains(eventProgramViewModel.Program
.Name)))
.Select(e => new EventViewModel

Id = e.Id,
Name = e.Name,
Date = e.Date,
EventProgramViewModels = e.EventPrograms.Select(eventProgram =>
new EventProgramViewModel

ProgramViewModel = new ProgramViewModel

Name = eventProgram.Program.Name

)
)
;


Which is better, as it only produces a query for each valid record, where before it would do every record regardless.



This now produces this one query:



SELECT [event].[Id], [event].[Name], [event].[Date]
FROM [Events] AS [event]
WHERE EXISTS (
SELECT 1
FROM [EventPrograms] AS [eventProgramViewModel]
INNER JOIN [Programs] AS [eventProgramViewModel.Program] ON [eventProgramViewModel].[ProgramId] = [eventProgramViewModel.Program].[Id]
WHERE [eventProgramViewModel.Program].[Name] IN (N'A SEARCHED PROGRAM NAME') AND ([event].[Id] = [eventProgramViewModel].[EventId]))
ORDER BY [event].[Date] DESC, [event].[Name]


And one for each valid record:



SELECT [eventProgram.Program].[Name]
FROM [EventPrograms] AS [eventProgram]
INNER JOIN [Programs] AS [eventProgram.Program] ON [eventProgram].[ProgramId] = [eventProgram.Program].[Id]
WHERE @_outer_Id = [eventProgram].[EventId]









share|improve this question
















Using .Net Core 2.1 and EF Core 2.1.4



I'm trying to grab all the nested records of an object if any of those records contains a name that I have in a list, and only objects that have matching nested records.



I have a query that is producing the right results, but it's performing a query for every single record in the database table.



I'm hoping to reduce it further, if possible.



My ViewModels (actual models are nearly identical):



EventViewModel



using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace MyProject.Models.ViewModels

public class EventViewModel

private string _name;

public Guid Id get; set;

[Required, StringLength(100)]
public string Name

get => _name?.Trim();
set => _name = value?.Trim();


[DataType(DataType.Date)]
public DateTime Date get; set;

[Display(Name = "Programs")]
public IEnumerable<EventProgramViewModel> EventProgramViewModels get; set;

public string AllProgramNames

get

string result = EventProgramViewModels.Aggregate(string.Empty,
(current, program) => current + $"program?.ProgramViewModel?.Name, ");
return result.TrimEnd(',', ' ');



public EventViewModel()

Id = Guid.NewGuid();
Date = DateTime.Now;
EventProgramViewModels = new List<EventProgramViewModel>();





EventProgramViewModel



using System;

namespace MyProject.Models.ViewModels

public class EventProgramViewModel

public Guid EventViewModelId get; set;
public EventViewModel EventViewModel get; set;

public Guid ProgramViewModelId get; set;
public ProgramViewModel ProgramViewModel get; set;




ProgramViewModel



using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace MyProject.Models.ViewModels

public class ProgramViewModel

private string _name;

public Guid Id get; set;

[Required, StringLength(100)]
[Display(Name = "Program Name")]
public string Name

get => _name?.Trim();
set => _name = value?.Trim();





In my ApplicationDbContext.cs file I have this mapped like so:



modelBuilder.Entity<EventProgram>()
.HasKey(eventProgram => new eventProgram.EventId, eventProgram.ProgramId);


Finally, here is my query:



var testQuery = context.Events
.AsNoTracking()
.Select(e => new EventViewModel

Id = e.Id,
Name = e.Name,
Date = e.Date,
EventProgramViewModels = e.EventPrograms.Select(eventProgram =>
new EventProgramViewModel

ProgramViewModel = new ProgramViewModel

Name = eventProgram.Program.Name

)
)
.OrderByDescending(eventViewModel => eventViewModel.Date)
.ThenBy(eventViewModel => eventViewModel.Name)
.Where(eventViewModel =>
!search.ProgramsChosen.Any() || eventViewModel.EventProgramViewModels.Any(
eventProgramViewModel =>
search.ProgramsChosen.Contains(eventProgramViewModel.ProgramViewModel
.Name)))
.ToList()
;

foreach (var item in testQuery)

// Mock usage to show where queries are generated
_loggingServices.LogInformation(JsonConvert.SerializeObject(item));



This produces one EF query for the main Event properties:



SELECT [e].[Id], [e].[Name], [e].[Date]
FROM [Events] AS [e]
ORDER BY [e].[Date] DESC, [e].[Name]


And 1 for each result (in this case, in the above foreach loop)



SELECT [eventProgram.Program].[Name]
FROM [EventPrograms] AS [eventProgram]
INNER JOIN [Programs] AS [eventProgram.Program] ON [eventProgram].[ProgramId] = [eventProgram.Program].[Id]
WHERE @_outer_Id = [eventProgram].[EventId]


Is there any way I can improve this performance?




Update 1:



Based on TyCobb's comment I changed the query structure to:



var testQuery =
context.Events
.AsNoTracking()
.OrderByDescending(@event => @event.Date)
.ThenBy(@event => @event.Name)
.Where(@event =>
!search.ProgramsChosen.Any() || @event.EventPrograms.Any(
eventProgramViewModel =>
search.ProgramsChosen.Contains(eventProgramViewModel.Program
.Name)))
.Select(e => new EventViewModel

Id = e.Id,
Name = e.Name,
Date = e.Date,
EventProgramViewModels = e.EventPrograms.Select(eventProgram =>
new EventProgramViewModel

ProgramViewModel = new ProgramViewModel

Name = eventProgram.Program.Name

)
)
;


Which is better, as it only produces a query for each valid record, where before it would do every record regardless.



This now produces this one query:



SELECT [event].[Id], [event].[Name], [event].[Date]
FROM [Events] AS [event]
WHERE EXISTS (
SELECT 1
FROM [EventPrograms] AS [eventProgramViewModel]
INNER JOIN [Programs] AS [eventProgramViewModel.Program] ON [eventProgramViewModel].[ProgramId] = [eventProgramViewModel.Program].[Id]
WHERE [eventProgramViewModel.Program].[Name] IN (N'A SEARCHED PROGRAM NAME') AND ([event].[Id] = [eventProgramViewModel].[EventId]))
ORDER BY [event].[Date] DESC, [event].[Name]


And one for each valid record:



SELECT [eventProgram.Program].[Name]
FROM [EventPrograms] AS [eventProgram]
INNER JOIN [Programs] AS [eventProgram.Program] ON [eventProgram].[ProgramId] = [eventProgram.Program].[Id]
WHERE @_outer_Id = [eventProgram].[EventId]






c# entity-framework-core






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 19:16







Ryan Taite

















asked Nov 14 '18 at 18:38









Ryan TaiteRyan Taite

370514




370514







  • 1





    Try to do all filtering/ordering before your Select. The way it currently is written, it needs to get everything and map it to your view model and then it will filter based on your view model's properties.You want to try and have your select be the last thing it does.

    – TyCobb
    Nov 14 '18 at 18:53











  • @TyCobb I've updated my question to reflect your suggested changes, it is definitely better, but I'm still producing a query for each valid record. I'll build my other queries with this tip in mind though, thank you!

    – Ryan Taite
    Nov 14 '18 at 19:17












  • Not too sure. It's being treated as lazy loaded even though you mapped to a non-entity. You could try turning lazy loading off if you have it on and also try to do an Include(...) for your events children that you are using.

    – TyCobb
    Nov 14 '18 at 19:26











  • Don't have Lazy Loading turned on, and the Include is unnecessary and was ignored because the navigation is not reachable in the final query results

    – Ryan Taite
    Nov 14 '18 at 19:41











  • @TyCobb I was able to figure it out. Adding .ToList() to EventProgramsViewModels = ....Select(... => new EventProgramViewModel ... ) did the trick. I had tried it before, but got errors every time, but no longer after moving my OrderyBy() and Where() to the top of my query.

    – Ryan Taite
    Nov 14 '18 at 19:54












  • 1





    Try to do all filtering/ordering before your Select. The way it currently is written, it needs to get everything and map it to your view model and then it will filter based on your view model's properties.You want to try and have your select be the last thing it does.

    – TyCobb
    Nov 14 '18 at 18:53











  • @TyCobb I've updated my question to reflect your suggested changes, it is definitely better, but I'm still producing a query for each valid record. I'll build my other queries with this tip in mind though, thank you!

    – Ryan Taite
    Nov 14 '18 at 19:17












  • Not too sure. It's being treated as lazy loaded even though you mapped to a non-entity. You could try turning lazy loading off if you have it on and also try to do an Include(...) for your events children that you are using.

    – TyCobb
    Nov 14 '18 at 19:26











  • Don't have Lazy Loading turned on, and the Include is unnecessary and was ignored because the navigation is not reachable in the final query results

    – Ryan Taite
    Nov 14 '18 at 19:41











  • @TyCobb I was able to figure it out. Adding .ToList() to EventProgramsViewModels = ....Select(... => new EventProgramViewModel ... ) did the trick. I had tried it before, but got errors every time, but no longer after moving my OrderyBy() and Where() to the top of my query.

    – Ryan Taite
    Nov 14 '18 at 19:54







1




1





Try to do all filtering/ordering before your Select. The way it currently is written, it needs to get everything and map it to your view model and then it will filter based on your view model's properties.You want to try and have your select be the last thing it does.

– TyCobb
Nov 14 '18 at 18:53





Try to do all filtering/ordering before your Select. The way it currently is written, it needs to get everything and map it to your view model and then it will filter based on your view model's properties.You want to try and have your select be the last thing it does.

– TyCobb
Nov 14 '18 at 18:53













@TyCobb I've updated my question to reflect your suggested changes, it is definitely better, but I'm still producing a query for each valid record. I'll build my other queries with this tip in mind though, thank you!

– Ryan Taite
Nov 14 '18 at 19:17






@TyCobb I've updated my question to reflect your suggested changes, it is definitely better, but I'm still producing a query for each valid record. I'll build my other queries with this tip in mind though, thank you!

– Ryan Taite
Nov 14 '18 at 19:17














Not too sure. It's being treated as lazy loaded even though you mapped to a non-entity. You could try turning lazy loading off if you have it on and also try to do an Include(...) for your events children that you are using.

– TyCobb
Nov 14 '18 at 19:26





Not too sure. It's being treated as lazy loaded even though you mapped to a non-entity. You could try turning lazy loading off if you have it on and also try to do an Include(...) for your events children that you are using.

– TyCobb
Nov 14 '18 at 19:26













Don't have Lazy Loading turned on, and the Include is unnecessary and was ignored because the navigation is not reachable in the final query results

– Ryan Taite
Nov 14 '18 at 19:41





Don't have Lazy Loading turned on, and the Include is unnecessary and was ignored because the navigation is not reachable in the final query results

– Ryan Taite
Nov 14 '18 at 19:41













@TyCobb I was able to figure it out. Adding .ToList() to EventProgramsViewModels = ....Select(... => new EventProgramViewModel ... ) did the trick. I had tried it before, but got errors every time, but no longer after moving my OrderyBy() and Where() to the top of my query.

– Ryan Taite
Nov 14 '18 at 19:54





@TyCobb I was able to figure it out. Adding .ToList() to EventProgramsViewModels = ....Select(... => new EventProgramViewModel ... ) did the trick. I had tried it before, but got errors every time, but no longer after moving my OrderyBy() and Where() to the top of my query.

– Ryan Taite
Nov 14 '18 at 19:54












1 Answer
1






active

oldest

votes


















3














There are two issues.



The first (which you solved with the Update 1) is caused by the current EF Core query translation defect which causes client evaluation of the Where clause (the OrderBy is ok). So moving the filtering before the projection is the current way to workaround it.



The second is the so called N + 1 subquery issue. EF Core 2.1 contains Optimization of correlated subqueries, which works in your case, but as mentioned in the documentation, you are expected to opt-in for it by adding ToList (or ToArray):




We have improved our query translation to avoid executing "N + 1" SQL queries in many common scenarios in which the usage of a navigation property in the projection leads to joining data from the root query with data from a correlated subquery. The optimization requires buffering the results from the subquery, and we require that you modify the query to opt-in the new behavior.




and then




By including ToList() in the right place, you indicate that buffering is appropriate for the Orders, which enable the optimization




So the final query should be something like this:



var testQuery = context.Events
//.AsNoTracking() <-- No need when using projection
.OrderByDescending(@event => @event.Date)
.ThenBy(@event => @event.Name)
.Where(@event =>
!search.ProgramsChosen.Any() || @event.EventPrograms.Any(
eventProgram =>
search.ProgramsChosen.Contains(eventProgram.Program
.Name)))
.Select(e => new EventViewModel

Id = e.Id,
Name = e.Name,
Date = e.Date,
EventProgramViewModels = e.EventPrograms.Select(eventProgram =>
new EventProgramViewModel

ProgramViewModel = new ProgramViewModel

Name = eventProgram.Program.Name

).ToList() // <--
)
.ToList()
;


which will result in 2 SQL queries:



SELECT [event].[Id], [event].[Name], [event].[Date]
FROM [Events] AS [event]
WHERE EXISTS (
SELECT 1
FROM [EventPrograms] AS [eventProgramViewModel]
INNER JOIN [Programs] AS [eventProgramViewModel.Program] ON [eventProgramViewModel].[ProgramId] = [eventProgramViewModel.Program].[Id]
WHERE [eventProgramViewModel.Program].[Name] IN (N'P2', N'P4', N'P7') AND ([event].[Id] = [eventProgramViewModel].[EventId]))
ORDER BY [event].[Date] DESC, [event].[Name], [event].[Id]


and



SELECT [t].[Date], [t].[Name], [t].[Id], [eventProgram.Program].[Name] AS [Name0], [event.EventPrograms].[EventId]
FROM [EventPrograms] AS [event.EventPrograms]
INNER JOIN [Programs] AS [eventProgram.Program] ON [event.EventPrograms].[ProgramId] = [eventProgram.Program].[Id]
INNER JOIN (
SELECT [event0].[Date], [event0].[Name], [event0].[Id]
FROM [Events] AS [event0]
WHERE EXISTS (
SELECT 1
FROM [EventPrograms] AS [eventProgramViewModel0]
INNER JOIN [Programs] AS [eventProgramViewModel.Program0] ON [eventProgramViewModel0].[ProgramId] = [eventProgramViewModel.Program0].[Id]
WHERE [eventProgramViewModel.Program0].[Name] IN (N'P2', N'P4', N'P7') AND ([event0].[Id] = [eventProgramViewModel0].[EventId]))
) AS [t] ON [event.EventPrograms].[EventId] = [t].[Id]
ORDER BY [t].[Date] DESC, [t].[Name], [t].[Id]





share|improve this answer























  • That's exactly it! I just posted a comment a moment ago to TyCobb on my question how I came to same conclusion. Thanks for figuring it out, writing it up, and posting!

    – Ryan Taite
    Nov 14 '18 at 19:57











  • Yeah, I just saw you found it while I was writing the answer :)

    – Ivan Stoev
    Nov 14 '18 at 19:58











  • Wow, good to know on the the whole ToList for subqueries. Currently still working with 6.2 and was expecting the subqueries to work the same.

    – TyCobb
    Nov 14 '18 at 23:56










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53306770%2fef-core-how-to-filter-a-nested-many-to-many-list-by-another-list%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














There are two issues.



The first (which you solved with the Update 1) is caused by the current EF Core query translation defect which causes client evaluation of the Where clause (the OrderBy is ok). So moving the filtering before the projection is the current way to workaround it.



The second is the so called N + 1 subquery issue. EF Core 2.1 contains Optimization of correlated subqueries, which works in your case, but as mentioned in the documentation, you are expected to opt-in for it by adding ToList (or ToArray):




We have improved our query translation to avoid executing "N + 1" SQL queries in many common scenarios in which the usage of a navigation property in the projection leads to joining data from the root query with data from a correlated subquery. The optimization requires buffering the results from the subquery, and we require that you modify the query to opt-in the new behavior.




and then




By including ToList() in the right place, you indicate that buffering is appropriate for the Orders, which enable the optimization




So the final query should be something like this:



var testQuery = context.Events
//.AsNoTracking() <-- No need when using projection
.OrderByDescending(@event => @event.Date)
.ThenBy(@event => @event.Name)
.Where(@event =>
!search.ProgramsChosen.Any() || @event.EventPrograms.Any(
eventProgram =>
search.ProgramsChosen.Contains(eventProgram.Program
.Name)))
.Select(e => new EventViewModel

Id = e.Id,
Name = e.Name,
Date = e.Date,
EventProgramViewModels = e.EventPrograms.Select(eventProgram =>
new EventProgramViewModel

ProgramViewModel = new ProgramViewModel

Name = eventProgram.Program.Name

).ToList() // <--
)
.ToList()
;


which will result in 2 SQL queries:



SELECT [event].[Id], [event].[Name], [event].[Date]
FROM [Events] AS [event]
WHERE EXISTS (
SELECT 1
FROM [EventPrograms] AS [eventProgramViewModel]
INNER JOIN [Programs] AS [eventProgramViewModel.Program] ON [eventProgramViewModel].[ProgramId] = [eventProgramViewModel.Program].[Id]
WHERE [eventProgramViewModel.Program].[Name] IN (N'P2', N'P4', N'P7') AND ([event].[Id] = [eventProgramViewModel].[EventId]))
ORDER BY [event].[Date] DESC, [event].[Name], [event].[Id]


and



SELECT [t].[Date], [t].[Name], [t].[Id], [eventProgram.Program].[Name] AS [Name0], [event.EventPrograms].[EventId]
FROM [EventPrograms] AS [event.EventPrograms]
INNER JOIN [Programs] AS [eventProgram.Program] ON [event.EventPrograms].[ProgramId] = [eventProgram.Program].[Id]
INNER JOIN (
SELECT [event0].[Date], [event0].[Name], [event0].[Id]
FROM [Events] AS [event0]
WHERE EXISTS (
SELECT 1
FROM [EventPrograms] AS [eventProgramViewModel0]
INNER JOIN [Programs] AS [eventProgramViewModel.Program0] ON [eventProgramViewModel0].[ProgramId] = [eventProgramViewModel.Program0].[Id]
WHERE [eventProgramViewModel.Program0].[Name] IN (N'P2', N'P4', N'P7') AND ([event0].[Id] = [eventProgramViewModel0].[EventId]))
) AS [t] ON [event.EventPrograms].[EventId] = [t].[Id]
ORDER BY [t].[Date] DESC, [t].[Name], [t].[Id]





share|improve this answer























  • That's exactly it! I just posted a comment a moment ago to TyCobb on my question how I came to same conclusion. Thanks for figuring it out, writing it up, and posting!

    – Ryan Taite
    Nov 14 '18 at 19:57











  • Yeah, I just saw you found it while I was writing the answer :)

    – Ivan Stoev
    Nov 14 '18 at 19:58











  • Wow, good to know on the the whole ToList for subqueries. Currently still working with 6.2 and was expecting the subqueries to work the same.

    – TyCobb
    Nov 14 '18 at 23:56















3














There are two issues.



The first (which you solved with the Update 1) is caused by the current EF Core query translation defect which causes client evaluation of the Where clause (the OrderBy is ok). So moving the filtering before the projection is the current way to workaround it.



The second is the so called N + 1 subquery issue. EF Core 2.1 contains Optimization of correlated subqueries, which works in your case, but as mentioned in the documentation, you are expected to opt-in for it by adding ToList (or ToArray):




We have improved our query translation to avoid executing "N + 1" SQL queries in many common scenarios in which the usage of a navigation property in the projection leads to joining data from the root query with data from a correlated subquery. The optimization requires buffering the results from the subquery, and we require that you modify the query to opt-in the new behavior.




and then




By including ToList() in the right place, you indicate that buffering is appropriate for the Orders, which enable the optimization




So the final query should be something like this:



var testQuery = context.Events
//.AsNoTracking() <-- No need when using projection
.OrderByDescending(@event => @event.Date)
.ThenBy(@event => @event.Name)
.Where(@event =>
!search.ProgramsChosen.Any() || @event.EventPrograms.Any(
eventProgram =>
search.ProgramsChosen.Contains(eventProgram.Program
.Name)))
.Select(e => new EventViewModel

Id = e.Id,
Name = e.Name,
Date = e.Date,
EventProgramViewModels = e.EventPrograms.Select(eventProgram =>
new EventProgramViewModel

ProgramViewModel = new ProgramViewModel

Name = eventProgram.Program.Name

).ToList() // <--
)
.ToList()
;


which will result in 2 SQL queries:



SELECT [event].[Id], [event].[Name], [event].[Date]
FROM [Events] AS [event]
WHERE EXISTS (
SELECT 1
FROM [EventPrograms] AS [eventProgramViewModel]
INNER JOIN [Programs] AS [eventProgramViewModel.Program] ON [eventProgramViewModel].[ProgramId] = [eventProgramViewModel.Program].[Id]
WHERE [eventProgramViewModel.Program].[Name] IN (N'P2', N'P4', N'P7') AND ([event].[Id] = [eventProgramViewModel].[EventId]))
ORDER BY [event].[Date] DESC, [event].[Name], [event].[Id]


and



SELECT [t].[Date], [t].[Name], [t].[Id], [eventProgram.Program].[Name] AS [Name0], [event.EventPrograms].[EventId]
FROM [EventPrograms] AS [event.EventPrograms]
INNER JOIN [Programs] AS [eventProgram.Program] ON [event.EventPrograms].[ProgramId] = [eventProgram.Program].[Id]
INNER JOIN (
SELECT [event0].[Date], [event0].[Name], [event0].[Id]
FROM [Events] AS [event0]
WHERE EXISTS (
SELECT 1
FROM [EventPrograms] AS [eventProgramViewModel0]
INNER JOIN [Programs] AS [eventProgramViewModel.Program0] ON [eventProgramViewModel0].[ProgramId] = [eventProgramViewModel.Program0].[Id]
WHERE [eventProgramViewModel.Program0].[Name] IN (N'P2', N'P4', N'P7') AND ([event0].[Id] = [eventProgramViewModel0].[EventId]))
) AS [t] ON [event.EventPrograms].[EventId] = [t].[Id]
ORDER BY [t].[Date] DESC, [t].[Name], [t].[Id]





share|improve this answer























  • That's exactly it! I just posted a comment a moment ago to TyCobb on my question how I came to same conclusion. Thanks for figuring it out, writing it up, and posting!

    – Ryan Taite
    Nov 14 '18 at 19:57











  • Yeah, I just saw you found it while I was writing the answer :)

    – Ivan Stoev
    Nov 14 '18 at 19:58











  • Wow, good to know on the the whole ToList for subqueries. Currently still working with 6.2 and was expecting the subqueries to work the same.

    – TyCobb
    Nov 14 '18 at 23:56













3












3








3







There are two issues.



The first (which you solved with the Update 1) is caused by the current EF Core query translation defect which causes client evaluation of the Where clause (the OrderBy is ok). So moving the filtering before the projection is the current way to workaround it.



The second is the so called N + 1 subquery issue. EF Core 2.1 contains Optimization of correlated subqueries, which works in your case, but as mentioned in the documentation, you are expected to opt-in for it by adding ToList (or ToArray):




We have improved our query translation to avoid executing "N + 1" SQL queries in many common scenarios in which the usage of a navigation property in the projection leads to joining data from the root query with data from a correlated subquery. The optimization requires buffering the results from the subquery, and we require that you modify the query to opt-in the new behavior.




and then




By including ToList() in the right place, you indicate that buffering is appropriate for the Orders, which enable the optimization




So the final query should be something like this:



var testQuery = context.Events
//.AsNoTracking() <-- No need when using projection
.OrderByDescending(@event => @event.Date)
.ThenBy(@event => @event.Name)
.Where(@event =>
!search.ProgramsChosen.Any() || @event.EventPrograms.Any(
eventProgram =>
search.ProgramsChosen.Contains(eventProgram.Program
.Name)))
.Select(e => new EventViewModel

Id = e.Id,
Name = e.Name,
Date = e.Date,
EventProgramViewModels = e.EventPrograms.Select(eventProgram =>
new EventProgramViewModel

ProgramViewModel = new ProgramViewModel

Name = eventProgram.Program.Name

).ToList() // <--
)
.ToList()
;


which will result in 2 SQL queries:



SELECT [event].[Id], [event].[Name], [event].[Date]
FROM [Events] AS [event]
WHERE EXISTS (
SELECT 1
FROM [EventPrograms] AS [eventProgramViewModel]
INNER JOIN [Programs] AS [eventProgramViewModel.Program] ON [eventProgramViewModel].[ProgramId] = [eventProgramViewModel.Program].[Id]
WHERE [eventProgramViewModel.Program].[Name] IN (N'P2', N'P4', N'P7') AND ([event].[Id] = [eventProgramViewModel].[EventId]))
ORDER BY [event].[Date] DESC, [event].[Name], [event].[Id]


and



SELECT [t].[Date], [t].[Name], [t].[Id], [eventProgram.Program].[Name] AS [Name0], [event.EventPrograms].[EventId]
FROM [EventPrograms] AS [event.EventPrograms]
INNER JOIN [Programs] AS [eventProgram.Program] ON [event.EventPrograms].[ProgramId] = [eventProgram.Program].[Id]
INNER JOIN (
SELECT [event0].[Date], [event0].[Name], [event0].[Id]
FROM [Events] AS [event0]
WHERE EXISTS (
SELECT 1
FROM [EventPrograms] AS [eventProgramViewModel0]
INNER JOIN [Programs] AS [eventProgramViewModel.Program0] ON [eventProgramViewModel0].[ProgramId] = [eventProgramViewModel.Program0].[Id]
WHERE [eventProgramViewModel.Program0].[Name] IN (N'P2', N'P4', N'P7') AND ([event0].[Id] = [eventProgramViewModel0].[EventId]))
) AS [t] ON [event.EventPrograms].[EventId] = [t].[Id]
ORDER BY [t].[Date] DESC, [t].[Name], [t].[Id]





share|improve this answer













There are two issues.



The first (which you solved with the Update 1) is caused by the current EF Core query translation defect which causes client evaluation of the Where clause (the OrderBy is ok). So moving the filtering before the projection is the current way to workaround it.



The second is the so called N + 1 subquery issue. EF Core 2.1 contains Optimization of correlated subqueries, which works in your case, but as mentioned in the documentation, you are expected to opt-in for it by adding ToList (or ToArray):




We have improved our query translation to avoid executing "N + 1" SQL queries in many common scenarios in which the usage of a navigation property in the projection leads to joining data from the root query with data from a correlated subquery. The optimization requires buffering the results from the subquery, and we require that you modify the query to opt-in the new behavior.




and then




By including ToList() in the right place, you indicate that buffering is appropriate for the Orders, which enable the optimization




So the final query should be something like this:



var testQuery = context.Events
//.AsNoTracking() <-- No need when using projection
.OrderByDescending(@event => @event.Date)
.ThenBy(@event => @event.Name)
.Where(@event =>
!search.ProgramsChosen.Any() || @event.EventPrograms.Any(
eventProgram =>
search.ProgramsChosen.Contains(eventProgram.Program
.Name)))
.Select(e => new EventViewModel

Id = e.Id,
Name = e.Name,
Date = e.Date,
EventProgramViewModels = e.EventPrograms.Select(eventProgram =>
new EventProgramViewModel

ProgramViewModel = new ProgramViewModel

Name = eventProgram.Program.Name

).ToList() // <--
)
.ToList()
;


which will result in 2 SQL queries:



SELECT [event].[Id], [event].[Name], [event].[Date]
FROM [Events] AS [event]
WHERE EXISTS (
SELECT 1
FROM [EventPrograms] AS [eventProgramViewModel]
INNER JOIN [Programs] AS [eventProgramViewModel.Program] ON [eventProgramViewModel].[ProgramId] = [eventProgramViewModel.Program].[Id]
WHERE [eventProgramViewModel.Program].[Name] IN (N'P2', N'P4', N'P7') AND ([event].[Id] = [eventProgramViewModel].[EventId]))
ORDER BY [event].[Date] DESC, [event].[Name], [event].[Id]


and



SELECT [t].[Date], [t].[Name], [t].[Id], [eventProgram.Program].[Name] AS [Name0], [event.EventPrograms].[EventId]
FROM [EventPrograms] AS [event.EventPrograms]
INNER JOIN [Programs] AS [eventProgram.Program] ON [event.EventPrograms].[ProgramId] = [eventProgram.Program].[Id]
INNER JOIN (
SELECT [event0].[Date], [event0].[Name], [event0].[Id]
FROM [Events] AS [event0]
WHERE EXISTS (
SELECT 1
FROM [EventPrograms] AS [eventProgramViewModel0]
INNER JOIN [Programs] AS [eventProgramViewModel.Program0] ON [eventProgramViewModel0].[ProgramId] = [eventProgramViewModel.Program0].[Id]
WHERE [eventProgramViewModel.Program0].[Name] IN (N'P2', N'P4', N'P7') AND ([event0].[Id] = [eventProgramViewModel0].[EventId]))
) AS [t] ON [event.EventPrograms].[EventId] = [t].[Id]
ORDER BY [t].[Date] DESC, [t].[Name], [t].[Id]






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 14 '18 at 19:54









Ivan StoevIvan Stoev

107k786139




107k786139












  • That's exactly it! I just posted a comment a moment ago to TyCobb on my question how I came to same conclusion. Thanks for figuring it out, writing it up, and posting!

    – Ryan Taite
    Nov 14 '18 at 19:57











  • Yeah, I just saw you found it while I was writing the answer :)

    – Ivan Stoev
    Nov 14 '18 at 19:58











  • Wow, good to know on the the whole ToList for subqueries. Currently still working with 6.2 and was expecting the subqueries to work the same.

    – TyCobb
    Nov 14 '18 at 23:56

















  • That's exactly it! I just posted a comment a moment ago to TyCobb on my question how I came to same conclusion. Thanks for figuring it out, writing it up, and posting!

    – Ryan Taite
    Nov 14 '18 at 19:57











  • Yeah, I just saw you found it while I was writing the answer :)

    – Ivan Stoev
    Nov 14 '18 at 19:58











  • Wow, good to know on the the whole ToList for subqueries. Currently still working with 6.2 and was expecting the subqueries to work the same.

    – TyCobb
    Nov 14 '18 at 23:56
















That's exactly it! I just posted a comment a moment ago to TyCobb on my question how I came to same conclusion. Thanks for figuring it out, writing it up, and posting!

– Ryan Taite
Nov 14 '18 at 19:57





That's exactly it! I just posted a comment a moment ago to TyCobb on my question how I came to same conclusion. Thanks for figuring it out, writing it up, and posting!

– Ryan Taite
Nov 14 '18 at 19:57













Yeah, I just saw you found it while I was writing the answer :)

– Ivan Stoev
Nov 14 '18 at 19:58





Yeah, I just saw you found it while I was writing the answer :)

– Ivan Stoev
Nov 14 '18 at 19:58













Wow, good to know on the the whole ToList for subqueries. Currently still working with 6.2 and was expecting the subqueries to work the same.

– TyCobb
Nov 14 '18 at 23:56





Wow, good to know on the the whole ToList for subqueries. Currently still working with 6.2 and was expecting the subqueries to work the same.

– TyCobb
Nov 14 '18 at 23:56



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53306770%2fef-core-how-to-filter-a-nested-many-to-many-list-by-another-list%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Kleinkühnau

Makov (Slowakei)

Deutsches Schauspielhaus