2018-12-22 18:13:25 +08:00

169 lines
7.3 KiB
C#

using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace FreeSql.Internal.CommonProvider {
abstract partial class UpdateProvider<T1> : IUpdate<T1> where T1 : class {
protected IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
protected List<T1> _source = new List<T1>();
protected Dictionary<string, bool> _ignore = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
protected TableInfo _table;
protected StringBuilder _where = new StringBuilder();
protected StringBuilder _set = new StringBuilder();
protected List<DbParameter> _params = new List<DbParameter>();
protected List<DbParameter> _paramsSource = new List<DbParameter>();
public UpdateProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) {
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
_table = _commonUtils.GetTableByEntity(typeof(T1));
this.Where(_commonUtils.WhereObject(_table, "", dywhere));
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure<T1>();
}
public long ExecuteAffrows() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
return _orm.Ado.ExecuteNonQuery(CommandType.Text, sql, _params.Concat(_paramsSource).ToArray());
}
public abstract List<T1> ExecuteUpdated();
public IUpdate<T1> IgnoreColumns(Expression<Func<T1, object>> columns) {
var cols = _commonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(null, columns?.Body, false).Distinct();
_ignore.Clear();
foreach (var col in cols) _ignore.Add(col, true);
return this;
}
public IUpdate<T1> SetSource(T1 source) => this.SetSource(new[] { source });
public IUpdate<T1> SetSource(IEnumerable<T1> source) {
if (source == null || source.Any() == false) return this;
_source.AddRange(source.Where(a => a != null));
return this.Where(_source);
}
public IUpdate<T1> Set<TMember>(Expression<Func<T1, TMember>> column, TMember value) {
var col = _commonExpression.ExpressionSelectColumn_MemberAccess(null, null, SelectTableInfoType.From, column?.Body, true);
if (string.IsNullOrEmpty(col)) return this;
_set.Append(", ").Append(col).Append(" = ").Append(_commonUtils.QuoteParamterName("p_")).Append(_params.Count);
_commonUtils.AppendParamter(_params, null, value);
//foreach (var t in _source) Utils.FillPropertyValue(t, tryf.CsName, value);
return this;
}
public IUpdate<T1> Set<TMember>(Expression<Func<T1, TMember>> binaryExpression) {
if (binaryExpression?.Body is BinaryExpression == false) return this;
var cols = new List<SelectColumnInfo>();
var expt = _commonExpression.ExpressionWhereLambdaNoneForeignObject(null, cols, binaryExpression);
if (cols.Any() == false) return this;
foreach (var col in cols) {
if (col.Column.Attribute.IsNullable) {
var replval = col.Column.Attribute.DbDefautValue;
if (replval == null) continue;
var replname = _commonUtils.QuoteSqlName(col.Column.Attribute.Name);
expt = expt.Replace(replname, _commonUtils.IsNull(replname, _commonUtils.FormatSql("{0}", replval)));
}
}
_set.Append(", ").Append(_commonUtils.QuoteSqlName(cols.First().Column.Attribute.Name)).Append(" = ").Append(expt);
return this;
}
public IUpdate<T1> SetRaw(string sql, object parms = null) {
if (string.IsNullOrEmpty(sql)) return this;
_set.Append(", ").Append(sql);
if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
return this;
}
public IUpdate<T1> Where(Expression<Func<T1, bool>> expression) => this.Where(_commonExpression.ExpressionWhereLambdaNoneForeignObject(null, null, expression?.Body));
public IUpdate<T1> Where(string sql, object parms = null) {
if (string.IsNullOrEmpty(sql)) return this;
_where.Append(" AND (").Append(sql).Append(")");
if (parms != null) _params.AddRange(_commonUtils.GetDbParamtersByObject(sql, parms));
return this;
}
public IUpdate<T1> Where(T1 item) => this.Where(new[] { item });
public IUpdate<T1> Where(IEnumerable<T1> items) => this.Where(_commonUtils.WhereItems(_table, "", items));
public IUpdate<T1> WhereExists<TEntity2>(ISelect<TEntity2> select, bool notExists = false) where TEntity2 : class => this.Where($"{(notExists ? "NOT " : "")}EXISTS({select.ToSql("1")})");
protected abstract void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys);
protected abstract void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d);
public string ToSql() {
if (_where.Length == 0) return null;
var sb = new StringBuilder();
sb.Append("UPDATE ").Append(_commonUtils.QuoteSqlName(_table.DbName)).Append(" SET ");
if (_set.Length > 0) { //指定 set 更新
sb.Append(_set.ToString().Substring(2));
} else if (_source.Count == 1) { //保存 Source
_paramsSource.Clear();
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.CsName) == false) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ").Append(_commonUtils.QuoteParamterName($"p_{_paramsSource.Count}"));
_commonUtils.AppendParamter(_paramsSource, null, _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(_source.First()) : DBNull.Value);
++colidx;
}
}
if (colidx == 0) return null;
} else if (_source.Count > 1) { //批量保存 Source
if (_table.Primarys.Any() == false) return null;
var caseWhen = new StringBuilder();
caseWhen.Append("CASE ");
ToSqlCase(caseWhen, _table.Primarys);
//if (_table.Primarys.Length > 1) caseWhen.Append("CONCAT(");
//var pkidx = 0;
//foreach (var pk in _table.Primarys) {
// if (pkidx > 0) caseWhen.Append(", ");
// caseWhen.Append(_commonUtils.QuoteSqlName(pk.Attribute.Name));
// ++pkidx;
//}
//if (_table.Primarys.Length > 1) caseWhen.Append(")");
var cw = caseWhen.ToString();
_paramsSource.Clear();
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.CsName) == false) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ").Append(cw);
foreach (var d in _source) {
sb.Append(" \r\nWHEN ");
ToSqlWhen(sb, _table.Primarys, d);
//if (_table.Primarys.Length > 1) sb.Append("CONCAT(");
//pkidx = 0;
//foreach (var pk in _table.Primarys) {
// if (pkidx > 0) sb.Append(", ");
// sb.Append(_commonUtils.FormatSql("{0}", _table.Properties.TryGetValue(pk.CsName, out var tryp2) ? tryp2.GetValue(d) : null));
// ++pkidx;
//}
//if (_table.Primarys.Length > 1) sb.Append(")");
sb.Append(" THEN ").Append(_commonUtils.QuoteParamterName($"p_{_paramsSource.Count}"));
_commonUtils.AppendParamter(_paramsSource, null, _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(d) : DBNull.Value);
}
sb.Append(" END");
++colidx;
}
}
if (colidx == 0) return null;
} else
return null;
sb.Append(" \r\nWHERE ").Append(_where.ToString().Substring(5));
return sb.ToString();
}
}
}