/// <summary> /// Deletes entry into Table /// </summary> public virtual async Task <object> Delete <Table>(IDeleteDb <Table> dto) { using var db = AutoQuery.GetDb <Table>(Request); using (Profiler.Current.Step("AutoQuery.Delete")) { var response = await ExecAndReturnResponseAsync <Table>(dto, db, async ctx => { var dtoValues = ResolveDtoValues(dto, skipDefaults: true); //Should have at least 1 non-default filter if (dtoValues.Count == 0) { throw new NotSupportedException($"'{dto.GetType().Name}' did not contain any filters"); } var meta = AutoCrudMetadata.Create(dto.GetType()); var pkFieldDef = meta.ModelDef.PrimaryKey; var idValue = pkFieldDef != null && dtoValues.TryGetValue(pkFieldDef.Name, out var oId) ? oId : null; // Should only update a Single Row if (GetAutoFilterExpressions(db, dto, dtoValues, Request, out var expr, out var exprParams)) { //If there were Auto Filters, construct filter expression manually by adding any remaining DTO values foreach (var entry in dtoValues) { var fieldDef = meta.ModelDef.GetFieldDefinition(entry.Key); if (fieldDef == null) { throw new NotSupportedException($"Unknown '{entry.Key}' Field in '{dto.GetType().Name}' IDeleteDb<{typeof(Table).Name}> Request"); } if (expr.Length > 0) { expr += " AND "; } var quotedColumn = db.GetDialectProvider().GetQuotedColumnName(meta.ModelDef, fieldDef); expr += quotedColumn + " = {" + exprParams.Count + "}"; exprParams.Add(entry.Value); } var q = db.From <Table>(); q.Where(expr, exprParams.ToArray()); return(new ExecValue(idValue, await db.DeleteAsync(q))); }
private Dictionary <string, object> ResolveDtoValues(object dto, bool skipDefaults = false) { var dtoValues = dto.ToObjectDictionary(); var meta = AutoCrudMetadata.Create(dto.GetType()); if (meta.MapAttrs != null) { foreach (var entry in meta.MapAttrs) { if (dtoValues.TryRemove(entry.Key, out var value)) { dtoValues[entry.Value.To] = value; } } } var appHost = HostContext.AppHost; if (skipDefaults || meta.UpdateAttrs != null || meta.DefaultAttrs != null) { List <string> removeKeys = null; Dictionary <string, object> replaceValues = null; foreach (var entry in dtoValues) { var isNullable = meta.NullableProps?.Contains(entry.Key) == true; var isDefaultValue = entry.Value == null || (!isNullable && AutoMappingUtils.IsDefaultValue(entry.Value)); if (isDefaultValue) { var handled = false; if (meta.DefaultAttrs != null && meta.DefaultAttrs.TryGetValue(entry.Key, out var defaultAttr)) { handled = true; replaceValues ??= new Dictionary <string, object>(); replaceValues[entry.Key] = appHost.EvalScriptValue(defaultAttr, Request); } if (!handled) { if (skipDefaults || (meta.UpdateAttrs != null && meta.UpdateAttrs.TryGetValue(entry.Key, out var attr) && attr.Style == AutoUpdateStyle.NonDefaults)) { removeKeys ??= new List <string>(); removeKeys.Add(entry.Key); } } } } if (removeKeys != null) { foreach (var key in removeKeys) { dtoValues.RemoveKey(key); } } if (replaceValues != null) { foreach (var entry in replaceValues) { dtoValues[entry.Key] = entry.Value; } } } if (meta.PopulateAttrs != null) { foreach (var populateAttr in meta.PopulateAttrs) { dtoValues[populateAttr.Field] = appHost.EvalScriptValue(populateAttr, Request); } } var populatorFn = AutoMappingUtils.GetPopulator( typeof(Dictionary <string, object>), meta.DtoType); populatorFn?.Invoke(dtoValues, dto); // Ensure RowVersion is always populated if defined on Request DTO if (meta.RowVersionGetter != null && !dtoValues.ContainsKey(Keywords.RowVersion)) { dtoValues[Keywords.RowVersion] = default(uint); } return(dtoValues); }
internal bool GetAutoFilterExpressions(IDbConnection db, object dto, Dictionary <string, object> dtoValues, IRequest req, out string expr, out List <object> exprParams) { var meta = AutoCrudMetadata.Create(dto.GetType()); if (meta.AutoFilters != null) { var dialectProvider = db.GetDialectProvider(); var sb = StringBuilderCache.Allocate(); var exprParamsList = new List <object>(); //Update's require PK's, Delete's don't need to if (dtoValues.TryRemove(meta.ModelDef.PrimaryKey.Name, out var idValue)) { var idColumn = dialectProvider.GetQuotedColumnName(meta.ModelDef, meta.ModelDef.PrimaryKey); sb.Append(idColumn + " = {0}"); exprParamsList.Add(idValue); } var appHost = HostContext.AppHost; for (var i = 0; i < meta.AutoFilters.Count; i++) { var filter = meta.AutoFilters[i]; var dbAttr = meta.AutoFiltersDbFields[i]; var fieldDef = meta.ModelDef.GetFieldDefinition(filter.Field); if (fieldDef == null) { throw new NotSupportedException($"{dto.GetType().Name} '{filter.Field}' AutoFilter was not found on '{meta.ModelType.Name}'"); } var quotedColumn = dialectProvider.GetQuotedColumnName(meta.ModelDef, fieldDef); var value = appHost.EvalScriptValue(filter, req); var ret = ExprResult.CreateExpression("AND", quotedColumn, value, dbAttr); if (ret != null) { if (sb.Length > 0) { sb.Append(" AND "); } var exprResult = ret.Value; if (exprResult.Format.IndexOf("{1}", StringComparison.Ordinal) >= 0) { throw new NotSupportedException($"SQL Template '{exprResult.Format}' with multiple arguments is not supported"); } if (exprResult.Values != null) { for (var index = 0; index < exprResult.Values.Length; index++) { sb.Append(exprResult.Format.Replace("{" + index + "}", "{" + exprParamsList.Count + "}")); exprParamsList.Add(exprResult.Values[index]); } } } expr = StringBuilderCache.ReturnAndFree(sb); exprParams = exprParamsList; return(true); } } expr = null; exprParams = null; return(false); }