protected override void OnSave(string value)
 {
     base.OnSave(value);
     Model.Parameter = JsonHelper.Serialize(ParameterValues.ToDictionary(x => x.Name, x => x.Value));
 }
Example #2
0
        /// <summary>
        /// Converts the SQL into an UPDATE statement.
        /// </summary>
        /// <param name="update">The field or fields to update.</param>
        /// <returns></returns>
        public ParameterizedSql <TEntity> ToUpdate(Expression <Func <TEntity, TEntity> > update)
        {
            if (ReadOnly)
            {
                throw new InvalidOperationException("The UPDATE SQL cannot be automatically generated from this statement.");
            }
            if (!IsSelect)
            {
                throw new InvalidOperationException("Only SELECT statements can be converted to UPDATE statements.");
            }
            if (IsGrouped)
            {
                throw new InvalidOperationException("An aggregate SELECT statement cannot be converted to an UPDATE statement.");
            }
            if (HasWithExpression)
            {
                throw new InvalidOperationException("A SELECT statement with a WITH clause cannot be converted to an UPDATE statement.");
            }

            if (!(update.Body is MemberInitExpression initExpression))
            {
                throw new InvalidOperationException("The update expression must be a member initialization expression.");
            }

            var paramValues = ParameterValues.ToDictionary(x => x.Key, x => x.Value);
            var builder     = new StringBuilder();

            _logger?.LogDebug("Generating UPDATE SQL");

            var context = DbContext ??
                          throw new InvalidOperationException("No current DbContext available.");

            var entityType = context.Model.FindEntityType(typeof(TEntity)) ??
                             throw new InvalidOperationException("Failed to locate entity type.");

            builder.Append("UPDATE ");

            string subAlias;

            if (_knowledge.UpdateSupportsTableAliases)
            {
                if (_knowledge.UpdateSupportsFromClause)
                {
                    // UPDATE supports aliases and a FROM clause.
                    builder.Append(_knowledge.QuoteObjectName(_tableAlias)).Append(" SET ");
                }
                else
                {
                    // UPDATE supports aliases, but not the from clause (MySQL, MariaDB)
                    // The tables and aliases are specified immediately following the UPDATE keyword, so we can
                    // trim off the FROM keyword and just append the rest of the from clause.
                    builder.Append(_fromClause.Substring(5)).Append(" SET ");
                }

                subAlias = _knowledge.QuoteObjectName(_tableAlias) + ".";
            }
            else
            {
                builder.Append(_tableName).Append(" SET ");
                subAlias = "";
            }

            bool first = true;

            foreach (var binding in initExpression.Bindings)
            {
                if (!(binding is MemberAssignment assignment))
                {
                    throw new InvalidOperationException("Only simple assignment bindings are supported in the update expression.");
                }

                if (!first)
                {
                    builder.Append(", ");
                }
                first = false;

                var prop = entityType.FindProperty(assignment.Member.Name) ??
                           throw new InvalidOperationException(
                                     $"The entity does not contain a {assignment.Member.Name} property."
                                     );

                builder.Append(subAlias);

                builder.Append(ColumnNameFor(prop)).Append(" = ");

                AddColumnValue(assignment.Expression, builder, paramValues, context, entityType);
            }

            if (_knowledge.UpdateSupportsTableAliases)
            {
                if (_knowledge.UpdateSupportsFromClause)
                {
                    builder.Append(' ').Append(_fromClause);
                }

                builder.Append(' ').Append(_whereClause);
            }
            else
            {
                builder.Append(' ').Append(GenerateUnAliasedWhereClause());
            }

            var sql = builder.ToString().Trim();

            _logger?.LogDebug(sql);

            return(new ParameterizedSql <TEntity>(
                       this,
                       "UPDATE",
                       sql,
                       paramValues
                       ));
        }