/// <summary> /// this method needs to be handled with much care. /// First, the input list must not stem from a request finishing with a call to AsNoTracking method. /// Second, the query from which the input stems must be closed properly. /// This means that the result of a query must be cast to any kind of IEnumerable (List, Array) /// which will close the preceding query. /// </summary> /// <param name="dbAccess"></param> /// <param name="entities"></param> /// <returns></returns> public static DbResults <T> Delete <T, TId>(this DbContext dbAccess, IEnumerable <T> entities) where T : BaseAuditable <TId> { var results = new DbResults <T>(); if (null != entities) { using var transaction = dbAccess.Database.BeginTransaction(); foreach (var entity in entities) { var result = new DbResult <T> { Entity = entity }; if (null == entity) { result.ResultCode = DbResultCode.EntityIsNull; continue; } // Check 1: model has no unique key - skip if (EqualityComparer <TId> .Default.Equals(entity.Id, default)) { result.ResultCode = DbResultCode.Impractical; continue; } // Check 2: model can be deleted dbAccess.Entry(entity).State = EntityState.Deleted; var changes = dbAccess.SaveChanges(); if (0 == changes || dbAccess.Entry(entity).State != EntityState.Detached) { result.ResultCode = DbResultCode.SaveFailed; } results.Results.Add(result); } if (results.Success) { transaction.Commit(); } else { transaction.Rollback(); } } return(results); }
public static void ValidateEntity <T, TId>(T entity, DbResult <T> result) where T : IAuditable <TId> { entity.CreatedAt = EqualityComparer <DateTime> .Default.Equals(entity.CreatedAt, default) ? DateTime.UtcNow : entity.CreatedAt; entity.CreatedBy ??= Requestor; var validationContext = new ValidationContext(entity); if (!Validator.TryValidateObject(entity, validationContext, result.ValidationResults, true)) { result.ResultCode |= DbResultCode.ValidationFailed; } }
public static DbResult <T> CheckUpdateEntity <T, TId>(this DbContext dbContext, T entity) where T : BaseAuditable <TId> { var result = new DbResult <T> { Entity = entity }; // Check 0: entity is NULL if (null == entity) { result.ResultCode = DbResultCode.EntityIsNull; return(result); } // Check 1: entity has no unique key - skip if (EqualityComparer <TId> .Default.Equals(entity.Id, default)) { result.ResultCode |= DbResultCode.Impractical; } // Check 2: entity does not pass validation - skip ValidateEntity <T, TId>(entity, result); // Check 3: entity violates UK constraint - skip if (entity is IUniqueAuditable uniqueEntity) { var baseAuditables = dbContext.Set <T>().AsEnumerable() ?? new List <T>(); if (baseAuditables.Any(q => uniqueEntity.HasSameUniqueKey(q) && !EqualityComparer <TId> .Default.Equals(entity.Id, q.Id))) { result.ResultCode |= DbResultCode.Duplicate; } } return(result); }