using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; namespace adas_core.Domain; /// /// Allow to pass to a /// multiple requests like: /// * Include (to fetch eagerly relations inside T entity) /// Use a Builder pattern. /// /// /// var queryCustomizer = QueryCustomizer<Video>.New() /// .Include(v => v.Room) /// .Include(v => v.Clips) /// .Include(v => v.Diagnosis) /// .Include(v => v.Movies) /// .Include(v => v.Patient) /// .Include(v => v.Service) /// .Include(v => v.Thumbnail) /// .Include(v => v.VideoDoctors) /// .Include(v => v.Procedure) /// .Include(v => v.Recordings) /// .Include(v => v.Chapters) /// .Include(v => v.LogDownloadVideoUsers) /// .Include("VideoDoctors.Doctor") /// ; /// var v = _videoRepository.GetById(id, queryCustomizer); /// /// /// public class QueryCustomizer where T : class { private readonly List>> _includeLinqExpressions = []; private readonly List _includeLinqStringExpressions = []; /// /// Creates and returns a new instance of the class. /// /// A new instance. public static QueryCustomizer New() { return new QueryCustomizer(); } /// /// Adds a related entity to the set of include expressions used by the query, enabling eager loading of the specified navigation property. /// /// A lambda expression selecting the related entity to include in the query results. /// The current instance to allow fluent chaining of additional includes or customizations. public QueryCustomizer Include(Expression> includeExpression) { _includeLinqExpressions.Add(includeExpression); return this; } /// /// Adds one or more include expressions to the query customizer, enabling eager loading of related entities in the resulting query. /// /// The expressions specifying the related entities to include in the query. /// The current instance to support fluent method chaining. public QueryCustomizer Include(params Expression>[] includeExpressions) { _includeLinqExpressions.AddRange(includeExpressions); return this; } /// /// Adds an include expression to the customizer, typically used to specify related entities to eager-load in the query, and returns the current instance to support fluent chaining. /// /// The include expression to be added to the collection of include expressions. /// The current instance with the include expression added. public QueryCustomizer Include(string includeExpression) { _includeLinqStringExpressions.Add(includeExpression); return this; } /// /// Adds the specified include expressions to the query, allowing additional related entities or navigation properties to be loaded alongside the primary result. /// /// The string expressions representing the related entities or paths to include in the query. /// The current instance to enable fluent method chaining. public QueryCustomizer Include(params string[] includeExpressions) { _includeLinqStringExpressions.AddRange(includeExpressions); return this; } /// /// Applies a sequence of Include expressions to the specified queryable, enabling eager loading of related entities. /// Includes are applied in two passes: first using the pre-built LINQ expressions, then using the string-based include expressions. /// /// The source queryable to which the include expressions will be applied. /// An with all configured include expressions applied. public IQueryable AddToQueryable(IQueryable queryable) { var resultQueryable = queryable; resultQueryable = _includeLinqExpressions .Aggregate(resultQueryable, (current, expression) => current.Include(expression)) ; resultQueryable = _includeLinqStringExpressions .Aggregate(resultQueryable, (current, expression) => current.Include(expression)) ; return resultQueryable; } }