using System.Collections; using System.Linq.Expressions; using System.Runtime.CompilerServices; namespace JsonContextDb.JsonContext; /// /// A queryable collection of entities that supports querying, adding, updating, and removing entities /// in a JSON-based data context. /// /// The type of entity, which must be a class with an integer Id property. public class DbSet(DbContext context) : IQueryable, IQueryable, IEnumerable, IEnumerable where T : class { // Reference to the parent JsonContext for operations. private readonly DbContext context = context ?? throw new ArgumentNullException(nameof(context)); // Queryable entity collection for LINQ operations. private IQueryable GetQueryable() => context.GetList().AsQueryable(); /// /// Gets the type of the elements in the collection. /// public Type ElementType => GetQueryable().ElementType; /// /// Gets the expression tree that represents the query. /// public Expression Expression => GetQueryable().Expression; /// /// Gets the query provider that executes the query. /// public IQueryProvider Provider => GetQueryable().Provider; /// /// Adds a single entity to the data context. /// /// The entity to add. public void Add(T entity) => context.Add(entity); /// /// Adds a collection of entities to the data context. /// /// The entities to add. public void AddRange(IEnumerable entities) => context.AddRange(entities); /// /// Adds a collection of entities to the data context. /// /// The entities to add. public void AddRange(params T[] entities) => context.AddRange(entities); /// /// Updates a single entity in the data context. /// /// The entity to update. public void Update(T entity) => context.Update(entity); /// /// Updates a collection of entities in the data context. /// /// The entities to update. public void UpdateRange(IEnumerable entities) => context.UpdateRange(entities); /// /// Removes a single entity from the data context. /// /// The entity to remove. public void Remove(T entity) => context.Remove(entity); /// /// Removes a collection of entities from the data context. /// /// The entities to remove. public void RemoveRange(IEnumerable entities) => context.RemoveRange(entities); /// /// Gets an enumerator for the collection of entities. /// /// An enumerator that can be used to iterate through the collection. public IEnumerator GetEnumerator() => GetQueryable().GetEnumerator(); /// /// Gets a non-generic enumerator for the collection of entities. /// /// An enumerator that can be used to iterate through the collection. IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); /// /// Asynchronously retrieves the first entity that matches the specified predicate, or the first entity if no predicate is provided. /// Returns null if no entity is found. /// /// An optional expression to filter entities. /// A task representing the asynchronous operation, returning the first matching entity or null. public Task FirstOrDefaultAsync(Expression>? predicate = null) { var queryable = GetQueryable(); var result = predicate != null ? queryable.FirstOrDefault(predicate) : queryable.FirstOrDefault(); return Task.FromResult(result); } /// /// Asynchronously retrieves all entities as a list. /// /// A task representing the asynchronous operation, returning a list of all entities. public Task> ToListAsync() { var result = GetQueryable().ToList(); return Task.FromResult(result); } /// /// Asynchronously streams entities that match the specified predicate, or all entities if no predicate is provided. /// /// An optional expression to filter entities. /// An asynchronous enumerable of entities that match the predicate. public async IAsyncEnumerable GetAsyncEnumerable([EnumeratorCancellation] CancellationToken cancellationToken = default, Expression>? predicate = null) { var queryable = GetQueryable(); var enumerable = predicate != null ? queryable.Where(predicate) : queryable; foreach (var entity in enumerable) { cancellationToken.ThrowIfCancellationRequested(); await Task.Yield(); // Ensures asynchronous context yield return entity; } } }