using FluentValidation.Results; using Raven.Client.Documents.Indexes; using Raven.Client.Documents.Linq; namespace zero.Stores; public abstract class EntityStore : IEntityStore where T : ZeroIdEntity, ISupportsFlavors, ISupportsSorting, new() { /// public Guid Guid { get; private set; } = Guid.NewGuid(); /// public IZeroDocumentSession Session => Operations.Session; /// public StoreConfig Config => Operations.Config; protected IZeroContext Context { get; private set; } protected IInterceptors Interceptors { get; private set; } protected IStoreOperations Operations { get; private set; } protected IZeroOptions Options { get; private set; } public EntityStore(IStoreContext collectionContext) { Context = collectionContext.Context; Interceptors = collectionContext.Interceptors; Options = collectionContext.Options; Operations = new StoreOperations(collectionContext); } /// public virtual Task Empty(string flavorAlias = null) => Operations.Empty(flavorAlias); /// public virtual Task Empty(string flavorAlias = null) where TFlavor : T, new() => Operations.Empty(flavorAlias); /// public virtual Task Load(string id, string changeVector = null) => Operations.Load(id, changeVector); /// public virtual Task> Load(IEnumerable ids) => Operations.Load(ids); /// public virtual Task> Load(int pageNumber, int pageSize, Func, IQueryable> querySelector = default) => Operations.Load(pageNumber, pageSize, querySelector); /// public virtual Task> Load(int pageNumber, int pageSize, Func, IQueryable> querySelector = default) where TIndex : AbstractCommonApiForIndexes, new() => Operations.Load(pageNumber, pageSize, querySelector); /// public virtual Task> LoadAll() => Operations.LoadAll(); /// public virtual IAsyncEnumerable Stream(Func, IQueryable> expression) => Operations.Stream(expression); /// public virtual string GetChangeToken(T model) => Operations.GetChangeToken(model); /// public virtual Task> Create(T model) => Operations.Create(model, async m => await Validate(m)); /// public virtual Task> Update(T model) => Operations.Update(model, async m => await Validate(m)); /// public virtual Task>> Sort(string[] sortedIds) => Operations.Sort(sortedIds); /// public virtual Task> Delete(T model) => Operations.Delete(model); /// public virtual async Task Validate(T model) { ZeroValidator validator = new(); ValidationRules(validator); return await validator.ValidateAsync(model); } /// /// Create rules for validation /// protected virtual void ValidationRules(ZeroValidator validator) { } /// /// Do only return the model when it is set to active or inactive entities are included with IncludeInactive() /// protected virtual T WhenActive(T model) => model != null && (Config.IncludeInactive || (model is not ZeroEntity || (model as ZeroEntity).IsActive)) ? model : default; } public interface IEntityStore where T : ZeroIdEntity, ISupportsFlavors, ISupportsSorting, new() { /// /// Id for this store /// Guid Guid { get; } /// /// Access the current document session /// IZeroDocumentSession Session { get; } /// /// Configure the store /// StoreConfig Config { get; } /// /// Get new instance of an entity (with an optional flavor) /// Task Empty(string flavorAlias = null); /// /// Get new instance of an entity with a specific flavor /// Task Empty(string flavorAlias = null) where TFlavor : T, new(); /// /// Get an entity by Id /// Task Load(string id, string changeVector = null); /// /// Get entities by ids /// Task> Load(IEnumerable ids); /// /// Get entities by query /// Task> Load(int pageNumber, int pageSize, Func, IQueryable> querySelector = default); /// /// Get entities by query (by using the specified index) /// Task> Load(int pageNumber, int pageSize, Func, IQueryable> querySelector = default) where TIndex : AbstractCommonApiForIndexes, new(); /// /// Get all entities from this collection. /// Warning: Don't use this method for large collections. Stream the results instead. /// Task> LoadAll(); /// /// Stream the collection /// IAsyncEnumerable Stream(Func, IQueryable> expression); /// /// Get the change vector for a model (Proxy to IAsyncDocumentSession.GetChangeVectorFor<>) /// string GetChangeToken(T model); /// /// Validates an entity in this collection /// Task Validate(T model); /// /// Creates an entity with an optional validator /// Task> Create(T model); /// /// Updates an entity with an optional validator /// Task> Update(T model); /// /// Update sorting of entities on a specific level /// Task>> Sort(string[] sortedIds); /// /// Deletes an entity /// Task> Delete(T model); }