EF-Core - Czy da się do .Include() dodać .Where() ?

0

Witam serdecznie. Ostatnio chodzi mi po głowie: Jak mam dwa modele:

    public class Library
    {
        public Guid Id { get; set; }
        public string Name { get; set; }

        public virtual List<Book> NotAssocciatedBooks { get; set; }
        public virtual List<Book> AssocciatedBooks { get; set; }
    }
    public class Book
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public Guid LibraryId { get; set; }
        public virtual Library Library { get; set; }
        public string AssociatedUserId { get; set; }
        public ApplicationUser AssociatedUser { get; set; }

    }

To jest możliwe, aby NotAssocciatedBooks wybierały książki z danej biblioteki których użytkownik jest równy null a
AssocciatedBooks wybierały książki z danej biblioteki których użytkownik nie jest równy null ? Chodzi mi wtedy o proste wywołanie:

var library = await _dbContext.Include(x => x.AssocciatedBooks).FirstOrDefaultAsync(x => x.Id == id);
var libraryDto = new LibraryDto()
{
     library = library,
     associatedBooksCount = library.AssocciatedBooks.count()
}
0

Nie mam EF przy sobie, ale nie zadziała tak?

var library = _dbContext.Libraries.Include(x=>x.AssocciatedBooks).Where(x=>x.AssocciatedBooks.AssociatedUser == null);
1

Chyba chodzi o filtr w Include. Jakis nuget chyba to ma. Z.EntityFramework.Extensions?

1
AdamWox napisał(a):

var library = _dbContext.Libraries.Include(x=>x.AssocciatedBooks).Where(x=>x.AssocciatedBooks.AssociatedUser == null);

To filtruje Libraries, a Libraries chcemy wyciągnąć wszystkie, dopiero dla każdej biblioteki chcemy wyciągnąć tylko te książki, które nie mają użytkownika.

@gswidwa1: Jeżeli używasz EF Core w wersji 5.0 lub nowszej to filtrowanie po include powinno działać normalnie: https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-5.0/whatsnew#filtered-include
Dla starszych wersji można zrobić coś takiego z selectem:

var library = _dbContext.Libraries.Select(x => new { Library = x, AssocciatedBooks = x.AssocciatedBooks.Where(y => y.AssociatedUser == null)})
                        .AsEnumerable()
                        .Select(x => x.Library)
                        .ToList();

EF powinien wygenerować jedno zapytanie do bazy.

Inna sprawa że jeżeli chcesz i tak wyciągnąć wszystkie książki, tylko rozdzielić je na 2 listy w zależności czy mają użytkownika czy nie, to chyba lepiej wyciągnąć z bazy to co potrzebujesz, a filtrować u siebie w kodzie, np tak:

    public class Library
    {
        public Guid Id { get; set; }
        public string Name { get; set; }

        public virtual List<Book> Books { get; set; }

        public List<Book> NotAssocciatedBooks
        {
            get 
            {
                if(Books == null) return new List<Books>();
                return Books.Where(x => string.IsNullOrWhiteSpace(x.AssociatedUserId)).ToList();
            }
        }
        
        public List<Book> AssocciatedBooks
        {
            get 
            { 
                if(Books == null) return new List<Books>();
                return Books.Where(x => !string.IsNullOrWhiteSpace(x.AssociatedUserId)).ToList(); 
            }
        }
    }

btw. wyciąganie połowy bazy w jednym zapytaniu to nie jest najlepszy pomysł.

0

zawsze mozesz na poziomie jakiegos repository zrobic w stylu

IQueryable<Book> QueryNotAssociatedBooks() => context.books.where(x=>  string.IsNullOrWhiteSpace(x.AssociatedUserId)
IQueryable<Book> QueryAssociatedBooks() => context.books.where(x=>  !string.IsNullOrWhiteSpace(x.AssociatedUserId)

1 użytkowników online, w tym zalogowanych: 0, gości: 1