Working on a REST API with an ASP.NET Core 5 and EF Core 5 backend.
I got the following entities, DTOs and mappings (only including the relevant code):
// Entities
//
class Book {
public int Id { get; set; }
public string Title { get; set; }
public int AuthorId { get; set; } // foreing-key
public Author Author { get; set; } // nav prop
}
class Author {
public int Id { get; set; }
public string Name { get; set; }
}
(assume proper EF config to indicate HasOne/HasMany WithOne/WithMany accordingly)
// DTOs
//
class AuthorDTO { ... }
class BookDTO {
...
AuthorDTO Author { get; set; }
}
// Automapper Maps
//
CreateMap<Book, BookDTO>();
CreateMap<Author, AuthorDTO>();
If I run the code below, life is good. In fact, any filtering done on the root-level fields of the BookDTO runs just fine:
var data = await dbContex
.Books
.ProjectTo<BookDTO>(mapper.ConfigurationProvider)
.Where(bDto => bDto.Id == 4)
.ToListAsync();
Filtering done on the nested AuthorDTO fields works as long as the field is a nullable or a reference type. Eg.
var data = await dbContex
.Books
.ProjectTo<BookDTO>(mapper.ConfigurationProvider)
.Where(bDto => bDto.Author.Name == "John")
.ToListAsync();
However, queries on non-nullable or value types fails:
var data = await dbContex
.Books
.ProjectTo<BookDTO>(mapper.ConfigurationProvider)
.Where(bDto => bDto.Author.Id == 10)
.ToListAsync();
Error:
"The binary operator Equal is not defined for the types 'System.Nullable`1[System.Int32]' and 'System.Int32'."
If I'd declare the AuthorDTO Id as int?, the code works.
I've already tried several casting combinations within the Where clause.
Any suggestions would be welcome.
PS: None of these issues happen if I put the Where clause before the ProjectTo projection and do all filtering based on the entities fields instead of the DTO fields. For those of you wondering why I'm doing the filtering based on the DTO: I'm using Sieve, a package that allows me to do filtering and paging "a la OData", and the fields that the client receives when calling my API are those in the DTOs, so I really need to apply all queries after the ProjectTo.