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, new() { /// public Guid Guid { get; private set; } = Guid.NewGuid(); /// public IZeroDocumentSession Session => Context.Store.Session(Config.Database); protected IZeroContext Context { get; private set; } protected StoreConfig Config { get; private set; } = new(); protected IInterceptors Interceptors { get; private set; } protected IStoreOperations Operations { get; private set; } protected IZeroOptions Options { get; private set; } public EntityStore(IStoreContext collectionContext) { Operations = collectionContext.Operations; Context = collectionContext.Context; Interceptors = collectionContext.Interceptors; Options = collectionContext.Options; } /// 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 GetChangeVector(T model) => Operations.GetChangeVector(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> 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, new() { /// /// Id for this store /// Guid Guid { get; } /// /// Access the current document session /// IZeroDocumentSession Session { 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 GetChangeVector(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); /// /// Deletes an entity /// Task> Delete(T model); }