I am using a Repository pattern, and am currently on a Fascade in which I have to use multiple repositories to return the entity. Here is a Short Version of my Models:
public record Annoucement
{
public int Id { get; set; }
public int? BatchId { get; set; }
public Batch? Batch { get; set; }
public User Creator { get; set; }
public int CreatorId { get; set; }
//other important fields
}
public record Batch
{
public int Id { get; set; }
//one-to-many
public ICollection<Announcement> Announcements {get;set;}
public User Creator { get; set; }
public int CreatorId { get; set; }
//many-to-many
public ICollection<User> UsersJoined {get; set;}
//a simple join table with UserId and BatchId
public List<UserBatch> UserBatches {get;set;}
}
public abstract record User
{
public UserDiscriminator Discriminator {get;set;} //enum
public Id {get;set;}
public ICollection<Batch> BatchesJoined {get;set;}
public List<UserBatch> UserBatches {get;set;}
}
Now, if an announcement is a batch announcement, then I have to check if the user has access to this batch's announcements. For it to be valid a User has to be in UserJoined or be the Batch Creator himself (since BatchCreator won't be inside UsersJoined is where I'm struck).
Here is what I have:
public async Task<bool> CanAccessBatchAnnouncement(int announcementId, int batchId, string loggedInUserId, CancellationToken cancellationToken)
{
return await _announcementRepo.AnyAsync(x => x.Id == announcementId && x.BatchId == batchId && _batchRepo.ContainsUser(x.BatchId.Value, loggedInUserId), cancellationToken); //error here Operator '&&' can't be applied between bool and IQueryable<bool>
}
public interface IBatchRepository
{
/// <summary>
/// an IQueryable indicating if user is present in a batch
/// reason: this avoids having two joins in a where clause since it checks for two conditions
/// </summary>
/// <param name="batchId">batchId</param>
/// <param name="userFirebaseId">userId</param>
/// <returns></returns>
public IQueryable<bool> ContainsUser(int batchId, string userId);
}
If I do _announcementRepo.Any(x => x.BatchId == batchId && ( x.Batch.CreatorId == loggedInUserId || x.Batch.UsersJoined.Select(user => user.Id).Contains(loggedInUserId))), this will translate to SQL with joining Batch twice in the where clause, I want to user BatchRepo to only apply join once with both conditions in that where clause.