using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using FluentValidation.Results; using Microsoft.Extensions.Logging; using ServiceStack.OrmLite; using zero.Models; using zero.Extensions; namespace zero.Sqlite; public partial class DbOperations : IDbOperations { /// public virtual Task> Create(T model, Func> validate = null) where T : ZeroIdEntity, new() => Save(model, validate); /// public virtual Task> Update(T model, Func> validate = null) where T : ZeroIdEntity, new() => Save(model, validate, true); /// public virtual async Task> CreateOrUpdate(T model, Func> validate = null) where T : ZeroIdEntity, new() { bool update = !model.Id.IsNullOrEmpty() && await Any(x => x.Id == model.Id); return await Save(model, validate, update); } /// protected virtual async Task> Save(T model, Func> validate = null, bool update = false) where T : ZeroIdEntity, new() { if (model == null) { Logger.LogWarning("Could not create/update entity (model is null) for type {type}", typeof(T)); return Result.Fail("@errors.onsave.empty"); } // check if the Id for a model already exists if (!model.Id.IsNullOrEmpty()) { T previousModel = await Db.SingleByIdAsync(model.Id); if (update && previousModel == null) { return Result.Fail("@errors.onsave.noidmatch"); } else if (!update && previousModel != null) { return Result.Fail("@errors.oncreate.idmismatch"); } } // validate flavor if (model is ISupportsFlavors flavorModel && !flavorModel.Flavor.IsNullOrEmpty()) { if (!Flavors.Exists(flavorModel.Flavor)) { Logger.LogWarning("Flavor {flavor} not found for type {type}", flavorModel.Flavor, typeof(T)); return Result.Fail("@errors.onsave.flavornotfound"); } } // prepare model PrepareForSave(model); // run validator if (validate != null) { ValidationResult validation = await validate(model); if (!validation.IsValid) { Logger.LogInformation("Validation failed for {id} ({errors})", model.Id, validation.Errors); return Result.Fail(validation); } } // create ID before-hand so interceptors can use it if (!update && !model.Id.HasValue()) { model.Id = await GenerateId(model); } // store our model await Db.SaveAsync(model); string action = update ? "Updated" : "Created"; if (model is ZeroEntity zeroEntity) { Logger.LogInformation(action + " {id} with name {name}", model.Id, zeroEntity.Name); } else { Logger.LogInformation(action + " {id}", model.Id); } return Result.Success(model); } /// public virtual async Task Sort(IEnumerable ids) where T : ZeroEntity, new() { List items = await LoadAll(); uint sort = 0; foreach (string id in ids) { T item = items.FirstOrDefault(x => x.Id == id); if (item != null) { sort += 10; item.Sort = sort; item.LastModifiedDate = DateTimeOffset.Now; } } await Db.UpdateAllAsync(items); } }