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;
}
}
}