mysql/sqlserver CodeFirst 完成测试

This commit is contained in:
28810
2018-12-22 18:13:25 +08:00
parent 7a61aea544
commit 0ff422eeb6
26 changed files with 712 additions and 1067 deletions

View File

@ -28,5 +28,10 @@ namespace FreeSql.DataAnnotations {
/// 是否可DBNull
/// </summary>
public bool IsNullable { get; set; }
/// <summary>
/// 数据库默认值
/// </summary>
internal object DbDefautValue { get; set; }
}
}

View File

@ -17,21 +17,31 @@ namespace FreeSql.Internal {
switch (exp.NodeType) {
case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand);
case ExpressionType.Lambda: return ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body);
case ExpressionType.Negate:
case ExpressionType.NegateChecked:
field.Append(", ").Append(ExpressionLambdaToSql(exp, _tables, null, SelectTableInfoType.From, true)).Append(" as").Append(++index);
return false;
case ExpressionType.Convert: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand);
case ExpressionType.Constant:
var constExp = exp as ConstantExpression;
field.Append(", ").Append(constExp?.Value).Append(" as").Append(++index);
return false;
case ExpressionType.Call:
field.Append(", ").Append(ExpressionLambdaToSql(exp, _tables, null, SelectTableInfoType.From, true)).Append(" as").Append(++index);
return false;
case ExpressionType.MemberAccess:
var map = new List<SelectColumnInfo>();
ExpressionSelectColumn_MemberAccess(_tables, map, SelectTableInfoType.From, exp, true);
if (map.Count > 1) {
if (_common.GetTableByEntity(exp.Type) != null) { //加载表所有字段
var map = new List<SelectColumnInfo>();
ExpressionSelectColumn_MemberAccess(_tables, map, SelectTableInfoType.From, exp, true);
parent.Consturctor = map.First().Table.Table.Type.GetConstructor(new Type[0]);
parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties;
}
for (var idx = 0; idx < map.Count; idx++) {
field.Append(", ").Append(map[idx].Table.Alias).Append(".").Append(_common.QuoteSqlName(map[idx].Column.Attribute.Name)).Append(" as").Append(++index);
if (map.Count > 1) parent.Childs.Add(new ReadAnonymousTypeInfo { CsName = map[idx].Column.CsName });
for (var idx = 0; idx < map.Count; idx++) {
field.Append(", ").Append(map[idx].Table.Alias).Append(".").Append(_common.QuoteSqlName(map[idx].Column.Attribute.Name)).Append(" as").Append(++index);
parent.Childs.Add(new ReadAnonymousTypeInfo { CsName = map[idx].Column.CsName });
}
} else {
field.Append(", ").Append(ExpressionLambdaToSql(exp, _tables, null, SelectTableInfoType.From, true)).Append(" as").Append(++index);
return false;
}
return false;
case ExpressionType.New:
@ -39,7 +49,7 @@ namespace FreeSql.Internal {
parent.Consturctor = newExp.Type.GetConstructors()[0];
parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Arguments;
for (var a = 0; a < newExp.Members.Count; a++) {
var child = new ReadAnonymousTypeInfo { CsName = newExp.Members[a].Name };
var child = new ReadAnonymousTypeInfo { CsName = newExp.Members[a].Name, CsType = newExp.Arguments[a].Type };
parent.Childs.Add(child);
ReadAnonymousField(_tables, field, child, ref index, newExp.Arguments[a]);
}
@ -53,7 +63,7 @@ namespace FreeSql.Internal {
case ReadAnonymousTypeInfoConsturctorType.Arguments:
var args = new object[parent.Childs.Count];
for (var a = 0; a < parent.Childs.Count; a++) {
args[a] = ReadAnonymous(parent.Childs[a], dr, ref index);
args[a] = Utils.GetDataReaderValue(parent.Childs[a].CsType, ReadAnonymous(parent.Childs[a], dr, ref index));
}
return parent.Consturctor.Invoke(args);
case ReadAnonymousTypeInfoConsturctorType.Properties:
@ -162,6 +172,9 @@ namespace FreeSql.Internal {
case ExpressionType.Negate:
case ExpressionType.NegateChecked: return "-" + ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, _tables, _selectColumnMap, tbtype, isQuoteName);
case ExpressionType.Constant: return _common.FormatSql("{0}", (exp as ConstantExpression)?.Value);
case ExpressionType.Conditional:
var condExp = exp as ConditionalExpression;
return $"case when {ExpressionLambdaToSql(condExp.Test, _tables, _selectColumnMap, tbtype, isQuoteName)} then {ExpressionLambdaToSql(condExp.IfTrue, _tables, _selectColumnMap, tbtype, isQuoteName)} else {ExpressionLambdaToSql(condExp.IfFalse, _tables, _selectColumnMap, tbtype, isQuoteName)} end";
case ExpressionType.Call:
var exp3 = exp as MethodCallExpression;
switch (exp3.Object?.Type.FullName ?? exp3.Method.DeclaringType.FullName) {
@ -169,6 +182,7 @@ namespace FreeSql.Internal {
case "System.Math": return ExpressionLambdaToSqlCallMath(exp3, _tables, _selectColumnMap, tbtype, isQuoteName);
case "System.DateTime": return ExpressionLambdaToSqlCallDateTime(exp3, _tables, _selectColumnMap, tbtype, isQuoteName);
case "System.TimeSpan": return ExpressionLambdaToSqlCallTimeSpan(exp3, _tables, _selectColumnMap, tbtype, isQuoteName);
case "System.Convert": return ExpressionLambdaToSqlCallConvert(exp3, _tables, _selectColumnMap, tbtype, isQuoteName);
}
throw new Exception($"MySqlExpression 未现实函数表达式 {exp3} 解析");
case ExpressionType.MemberAccess:
@ -304,5 +318,6 @@ namespace FreeSql.Internal {
internal abstract string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
internal abstract string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
internal abstract string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
internal abstract string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName);
}
}

View File

@ -248,7 +248,7 @@ namespace FreeSql.Internal.CommonProvider {
}
var tran = TransactionCurrentThread;
if (IsTracePerformance) logtxt += $" PrepareCommand_part1: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms cmdParms: {cmdParms.Length}\r\n";
if (IsTracePerformance) logtxt += $" PrepareCommand_part1: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms cmdParms: {cmd.Parameters.Count}\r\n";
if (tran != null) {
if (IsTracePerformance) dt = DateTime.Now;

View File

@ -207,7 +207,7 @@ namespace FreeSql.Internal.CommonProvider {
}
}
if (IsTracePerformance) logtxt += $" PrepareCommand_tran==null: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms\r\n";
if (IsTracePerformance) logtxt += $" PrepareCommand_tran==null: {DateTime.Now.Subtract(dt).TotalMilliseconds}ms cmdParms: {cmd.Parameters.Count}\r\n";
return cmd;
}

View File

@ -65,7 +65,6 @@ namespace FreeSql.Internal.CommonProvider {
sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name));
++colidx;
}
if (colidx == 0) return null;
sb.Append(") VALUES");
_params = new DbParameter[colidx * _source.Count];
var didx = 0;

View File

@ -178,6 +178,7 @@ namespace FreeSql.Internal.CommonProvider {
var type = typeof(T1);
var map = new ReadAnonymousTypeInfo { Consturctor = type.GetConstructor(new Type[0]), ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties };
var field = new StringBuilder();
var dicfield = new Dictionary<string, bool>();
var tb = _tables.First();
var index = 0;
var ps = typeof(T1).GetProperties();
@ -185,7 +186,11 @@ namespace FreeSql.Internal.CommonProvider {
var child = new ReadAnonymousTypeInfo { CsName = p.Name };
if (tb.Table.ColumnsByCs.TryGetValue(p.Name, out var col)) { //普通字段
if (index > 0) field.Append(", ");
field.Append(tb.Alias).Append(".").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" as").Append(++index);
var quoteName = _commonUtils.QuoteSqlName(col.Attribute.Name);
field.Append(tb.Alias).Append(".").Append(quoteName);
++index;
if (dicfield.ContainsKey(quoteName)) field.Append(" as").Append(index);
else dicfield.Add(quoteName, true);
} else {
var tb2 = _tables.Where(a => a.Table.Type == p.PropertyType && a.Alias.Contains(p.Name)).FirstOrDefault();
if (tb2 == null && ps.Where(pw => pw.PropertyType == p.PropertyType).Count() == 1) tb2 = _tables.Where(a => a.Table.Type == p.PropertyType).FirstOrDefault();
@ -194,7 +199,11 @@ namespace FreeSql.Internal.CommonProvider {
child.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties;
foreach (var col2 in tb2.Table.Columns.Values) {
if (index > 0) field.Append(", ");
field.Append(tb2.Alias).Append(".").Append(_commonUtils.QuoteSqlName(col2.Attribute.Name)).Append(" as").Append(++index);
var quoteName = _commonUtils.QuoteSqlName(col2.Attribute.Name);
field.Append(tb2.Alias).Append(".").Append(quoteName);
++index;
if (dicfield.ContainsKey(quoteName)) field.Append(" as").Append(index);
else dicfield.Add(quoteName, true);
child.Childs.Add(new ReadAnonymousTypeInfo { CsName = col2.CsName });
}
}

View File

@ -47,9 +47,8 @@ namespace FreeSql.Internal.CommonProvider {
default: throw new NotImplementedException($"未现实 {expCall.Method.Name}");
}
}
return this;
}
throw new NotImplementedException($"未现实 {exp}");
return this;
}
public ISelect<T1> As(string alias) {

View File

@ -66,13 +66,10 @@ namespace FreeSql.Internal.CommonProvider {
if (cols.Any() == false) return this;
foreach (var col in cols) {
if (col.Column.Attribute.IsNullable) {
var repltype = col.Column.CsType;
if (repltype.FullName.StartsWith("System.Nullable`1[[System.")) repltype = repltype.GenericTypeArguments[0];
var replval = Activator.CreateInstance(repltype);
var replval = col.Column.Attribute.DbDefautValue;
if (replval == null) continue;
var replname = _commonUtils.QuoteSqlName(col.Column.Attribute.Name);
replval = _commonUtils.FormatSql("{0}", replval);
expt = expt.Replace(replname, _commonUtils.IsNull(replname, replval));
expt = expt.Replace(replname, _commonUtils.IsNull(replname, _commonUtils.FormatSql("{0}", replval)));
}
}
_set.Append(", ").Append(_commonUtils.QuoteSqlName(cols.First().Column.Attribute.Name)).Append(" = ").Append(expt);

View File

@ -6,6 +6,7 @@ using System.Text;
namespace FreeSql.Internal.Model {
class ReadAnonymousTypeInfo {
public string CsName { get; set; }
public Type CsType { get; set; }
public ConstructorInfo Consturctor { get; set; }
public ReadAnonymousTypeInfoConsturctorType ConsturctorType { get; set; }
public List<ReadAnonymousTypeInfo> Childs = new List<ReadAnonymousTypeInfo>();

View File

@ -13,6 +13,5 @@ namespace FreeSql.Internal.Model {
public string DbName { get; set; }
public string DbOldName { get; set; }
public string SelectFilter { get; set; }
public List<List<ColumnInfo>> Uniques { get; set; } = new List<List<ColumnInfo>>();
}
}

View File

@ -35,12 +35,22 @@ namespace FreeSql.Internal {
Name = p.Name,
DbType = tp.Value.dbtypeFull,
IsIdentity = false,
IsNullable = tp.Value.isnullable ?? false,
IsNullable = tp.Value.isnullable ?? true,
IsPrimary = false,
};
if (string.IsNullOrEmpty(colattr.DbType) == false) colattr.DbType = colattr.DbType.ToUpper();
if (tp != null && tp.Value.isnullable == null) colattr.IsNullable = tp.Value.dbtypeFull.Contains("NOT NULL") == false;
if (string.IsNullOrEmpty(colattr.DbType) == false) colattr.IsNullable = colattr.DbType.Contains("NOT NULL") == false;
if (string.IsNullOrEmpty(colattr.Name)) colattr.Name = p.Name;
if (string.IsNullOrEmpty(colattr.DbType)) colattr.DbType = tp?.dbtypeFull ?? "varchar(255)";
if (colattr.DbType.IndexOf("NOT NULL") == -1 && tp?.isnullable == false) colattr.DbType += " NOT NULL";
if ((colattr.IsNullable == false || colattr.IsIdentity || colattr.IsPrimary) && colattr.DbType.Contains("NOT NULL") == false) colattr.DbType += " NOT NULL";
if (colattr.IsNullable == true && colattr.DbType.Contains("NOT NULL")) colattr.DbType = colattr.DbType.Replace("NOT NULL", "");
colattr.DbType = Regex.Replace(colattr.DbType, @"\([^\)]+\)", m => Regex.Replace(m.Groups[0].Value, @"\s", ""));
colattr.DbDefautValue = trytb.Properties[p.Name].GetValue(Activator.CreateInstance(trytb.Type));
if (colattr.DbDefautValue == null && p.PropertyType.FullName == "System.String") colattr.DbDefautValue = string.Empty;
if (colattr.DbDefautValue == null) colattr.DbDefautValue = Activator.CreateInstance(p.PropertyType.GenericTypeArguments.FirstOrDefault() ?? p.PropertyType);
if (colattr.DbDefautValue == null) colattr.DbDefautValue = "";
if (colattr.DbDefautValue.GetType().FullName == "System.DateTime") colattr.DbDefautValue = new DateTime(1970, 1, 1);
var col = new ColumnInfo {
Table = trytb,
@ -52,6 +62,7 @@ namespace FreeSql.Internal {
trytb.ColumnsByCs.Add(p.Name, col);
}
trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsPrimary).ToArray();
if (trytb.Primarys.Any() == false) trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsIdentity).ToArray();
_cacheGetTableByEntity.TryAdd(entity.FullName, trytb);
return trytb;
}
@ -122,22 +133,14 @@ namespace FreeSql.Internal {
if (prop == null) throw new Exception(string.Concat(type.FullName, " 没有定义属性 ", members[a]));
if (a < members.Length - 1) current = prop.GetValue(current);
}
if (value == null || value == DBNull.Value) {
prop.SetValue(current, null, null);
return;
}
var propType = prop.PropertyType;
if (propType.FullName.StartsWith("System.Nullable`1[")) propType = propType.GenericTypeArguments.First();
if (propType.IsEnum) {
var valueStr = string.Concat(value);
if (string.IsNullOrEmpty(valueStr) == false) prop.SetValue(current, Enum.Parse(propType, valueStr), null);
return;
}
if (propType != value.GetType()) {
prop.SetValue(current, Convert.ChangeType(value, propType), null);
return;
}
prop.SetValue(current, value, null);
prop.SetValue(current, GetDataReaderValue(prop.PropertyType, value), null);
}
internal static object GetDataReaderValue(Type type, object value) {
if (value == null || value == DBNull.Value) return null;
if (type.FullName.StartsWith("System.Nullable`1[")) type = type.GenericTypeArguments.First();
if (type.IsEnum) return Enum.Parse(type, string.Concat(value));
if (type != value.GetType()) return Convert.ChangeType(value, type);
return value;
}
internal static string GetCsName(string name) {
name = Regex.Replace(name.TrimStart('@'), @"[^\w]", "_");

View File

@ -106,7 +106,7 @@ namespace FreeSql.MySql {
sb.Append("CREATE TABLE IF NOT EXISTS ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" (");
foreach (var tbcol in tb.Columns.Values) {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ");
sb.Append(tbcol.Attribute.DbType.ToUpper());
sb.Append(tbcol.Attribute.DbType);
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT");
sb.Append(",");
}
@ -143,10 +143,10 @@ where a.table_schema in ({0}) and a.table_name in ({1})".FormatMySql(isRenameTab
if (addcols.TryGetValue(column, out var trycol)) {
if ((trycol.Attribute.DbType.IndexOf(" unsigned", StringComparison.CurrentCultureIgnoreCase) != -1) != is_unsigned ||
Regex.Replace(trycol.Attribute.DbType, @"\([^\)]+\)", m => Regex.Replace(m.Groups[0].Value, @"\s", "")).StartsWith(sqlType, StringComparison.CurrentCultureIgnoreCase) == false ||
(trycol.Attribute.DbType.IndexOf("NOT NULL", StringComparison.CurrentCultureIgnoreCase) == -1) != is_nullable ||
trycol.Attribute.DbType.StartsWith(sqlType, StringComparison.CurrentCultureIgnoreCase) == false ||
trycol.Attribute.IsNullable != is_nullable ||
trycol.Attribute.IsIdentity != is_identity) {
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(column)).Append(" ").Append(trycol.Attribute.DbType.ToUpper());
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(column)).Append(" ").Append(trycol.Attribute.DbType);
if (trycol.Attribute.IsIdentity && trycol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT");
sb.Append(";\r\n");
}
@ -156,12 +156,12 @@ where a.table_schema in ({0}) and a.table_name in ({1})".FormatMySql(isRenameTab
}
foreach (var addcol in addcols.Values) {
if (string.IsNullOrEmpty(addcol.Attribute.OldName) == false && surplus.ContainsKey(addcol.Attribute.OldName)) { //修改列名
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" CHANGE COLUMN ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.OldName)).Append(" ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.Name)).Append(" ").Append(addcol.Attribute.DbType.ToUpper());
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" CHANGE COLUMN ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.OldName)).Append(" ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.Name)).Append(" ").Append(addcol.Attribute.DbType);
if (addcol.Attribute.IsIdentity && addcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT");
sb.Append(";\r\n");
} else { //添加列
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.Name)).Append(" ").Append(addcol.Attribute.DbType.ToUpper());
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.Name)).Append(" ").Append(addcol.Attribute.DbType);
if (addcol.Attribute.IsIdentity && addcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT");
sb.Append(";\r\n");
}

View File

@ -36,9 +36,9 @@ namespace FreeSql.MySql {
}
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "Date": return $"cast(date_format({left}, '%Y-%m-%d') as datetime)";
case "TimeOfDay": return $"(timestampdiff(microsecond, date_format({left}, '1970-1-1 %H:%i:%s.%f'), {left}) + 62135596800000000)";
case "DayOfWeek": return $"(dayofweek({left}) - 1)";
case "Date": return $"cast(date_format({left},'%Y-%m-%d') as datetime)";
case "TimeOfDay": return $"timestampdiff(microsecond, date_format({left},'%Y-%m-%d'), {left})";
case "DayOfWeek": return $"(dayofweek({left})-1)";
case "Day": return $"dayofmonth({left})";
case "DayOfYear": return $"dayofyear({left})";
case "Month": return $"month({left})";
@ -46,8 +46,8 @@ namespace FreeSql.MySql {
case "Hour": return $"hour({left})";
case "Minute": return $"minute({left})";
case "Second": return $"second({left})";
case "Millisecond": return $"floor(microsecond({left}) / 1000)";
case "Ticks": return $"(timestampdiff(microsecond, '1970-1-1', {left}) * 10 + 621355968000000000)";
case "Millisecond": return $"floor(microsecond({left})/1000)";
case "Ticks": return $"(timestampdiff(microsecond, '0001-1-1', {left})*10)";
}
return null;
}
@ -94,7 +94,7 @@ namespace FreeSql.MySql {
case "Substring":
var substrArgs1 = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (long.TryParse(substrArgs1, out var testtrylng1)) substrArgs1 = (testtrylng1 + 1).ToString();
else substrArgs1 += " + 1";
else substrArgs1 += "+1";
if (exp.Arguments.Count == 1) return $"substr({left}, {substrArgs1})";
return $"substr({left}, {substrArgs1}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "IndexOf":
@ -102,10 +102,10 @@ namespace FreeSql.MySql {
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") {
var locateArgs1 = ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName);
if (long.TryParse(locateArgs1, out var testtrylng2)) locateArgs1 = (testtrylng2 + 1).ToString();
else locateArgs1 += " + 1";
return $"(locate({left}, {indexOfFindStr}, {locateArgs1}) - 1)";
else locateArgs1 += "+1";
return $"(locate({left}, {indexOfFindStr}, {locateArgs1})-1)";
}
return $"(locate({left}, {indexOfFindStr}) - 1)";
return $"(locate({left}, {indexOfFindStr})-1)";
case "PadLeft":
if (exp.Arguments.Count == 1) return $"lpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
return $"lpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
@ -167,74 +167,95 @@ namespace FreeSql.MySql {
internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Object == null) {
switch (exp.Method.Name) {
case "Compare": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}) - ({ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "Compare": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} - ({ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "DaysInMonth": return $"dayofmonth(last_day(concat({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, '-', {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)}, '-01')))";
case "Equals": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} = {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "IsLeapYear":
var isLeapYearArgs1 = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
return $"(({isLeapYearArgs1}) % 4 = 0 AND ({isLeapYearArgs1}) % 100 <> 0 OR ({isLeapYearArgs1}) % 400 = 0)";
return $"(({isLeapYearArgs1})%4=0 AND ({isLeapYearArgs1})%100 <> 0 OR ({isLeapYearArgs1})%400 = 0)";
case "Parse": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as datetime)";
case "ParseExact":
case "TryParse":
case "TryParseExact": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as datetime)";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
var args1 = exp.Arguments.Count == 0 ? null : ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "Add": return $"date_add({left}, interval ({args1}) microsecond)";
case "AddDays": return $"date_add({left}, interval ({args1}) day)";
case "AddHours": return $"date_add({left}, interval ({args1}) hour)";
case "AddMilliseconds": return $"date_add({left}, interval ({args1}) * 1000 microsecond)";
case "AddMinutes": return $"date_add({left}, interval ({args1}) minute)";
case "AddMonths": return $"date_add({left}, interval ({args1}) month)";
case "AddSeconds": return $"date_add({left}, interval ({args1}) second)";
case "AddTicks": return $"date_add({left}, interval ({args1}) / 10 microsecond)";
case "AddYears": return $"date_add({left}, interval ({args1}) year)";
case "Subtract":
if (exp.Arguments[0].Type.FullName == "System.DateTime" || exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.DateTime")
return $"timestampdiff(microsecond, {args1}, {left})";
if (exp.Arguments[0].Type.FullName == "System.TimeSpan" || exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.TimeSpan")
return $"date_sub({left}, interval ({args1}) microsecond)";
break;
case "Equals": return $"({left} = {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "CompareTo": return $"(({left}) - ({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "ToString": return $"date_format({left}, '%Y-%m-%d %H:%i:%s.%f')";
} else {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
var args1 = exp.Arguments.Count == 0 ? null : ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "Add": return $"date_add({left}, interval ({args1}) microsecond)";
case "AddDays": return $"date_add({left}, interval ({args1}) day)";
case "AddHours": return $"date_add({left}, interval ({args1}) hour)";
case "AddMilliseconds": return $"date_add({left}, interval ({args1})*1000 microsecond)";
case "AddMinutes": return $"date_add({left}, interval ({args1}) minute)";
case "AddMonths": return $"date_add({left}, interval ({args1}) month)";
case "AddSeconds": return $"date_add({left}, interval ({args1}) second)";
case "AddTicks": return $"date_add({left}, interval ({args1})/10 microsecond)";
case "AddYears": return $"date_add({left}, interval ({args1}) year)";
case "Subtract":
if (exp.Arguments[0].Type.FullName == "System.DateTime" || exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.DateTime")
return $"timestampdiff(microsecond, {args1}, {left})";
if (exp.Arguments[0].Type.FullName == "System.TimeSpan" || exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.TimeSpan")
return $"date_sub({left}, interval ({args1}) microsecond)";
break;
case "Equals": return $"({left} = {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "CompareTo": return $"(({left}) - ({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "ToString": return $"date_format({left}, '%Y-%m-%d %H:%i:%s.%f')";
}
}
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Object == null) {
switch (exp.Method.Name) {
case "Compare": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}) - ({ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "Compare": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}-({ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "Equals": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} = {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "FromDays": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} * {(long)1000000 * 60 * 60 * 24})";
case "FromHours": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} * {(long)1000000 * 60 * 60})";
case "FromMilliseconds": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} * 1000)";
case "FromMinutes": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} * {(long)1000000 * 60})";
case "FromSeconds": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} * 1000000)";
case "FromTicks": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} / 10)";
case "FromDays": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})*{(long)1000000 * 60 * 60 * 24})";
case "FromHours": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})*{(long)1000000 * 60 * 60})";
case "FromMilliseconds": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})*1000)";
case "FromMinutes": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})*{(long)1000000 * 60})";
case "FromSeconds": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})*1000000)";
case "FromTicks": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})/10)";
case "Parse": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as signed)";
case "ParseExact":
case "TryParse":
case "TryParseExact": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as signed)";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
var args1 = exp.Arguments.Count == 0 ? null : ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "Add": return $"({left} + {args1})";
case "Subtract": return $"({left} - {args1})";
case "Equals": return $"({left} = {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "CompareTo": return $"(({left}) - ({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "ToString": return $"cast({left} as varchar)";
} else {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
var args1 = exp.Arguments.Count == 0 ? null : ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "Add": return $"({left}+{args1})";
case "Subtract": return $"({left}-({args1}))";
case "Equals": return $"({left} = {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "CompareTo": return $"({left}-({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "ToString": return $"cast({left} as char)";
}
}
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Object == null) {
switch (exp.Method.Name) {
case "ToBoolean": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} not in ('0','false'))";
case "ToByte": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as unsigned)";
case "ToChar": return $"substr(cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as char), 1, 1)";
case "ToDateTime": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as datetime)";
case "ToDecimal": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as decimal(36,18))";
case "ToDouble": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as decimal(32,16))";
case "ToInt16":
case "ToInt32":
case "ToInt64":
case "ToSByte": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as signed)";
case "ToSingle": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as decimal(14,7))";
case "ToString": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as char)";
case "ToUInt16":
case "ToUInt32":
case "ToUInt64": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as unsigned)";
}
}
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
}
}
}

View File

@ -176,5 +176,28 @@ namespace FreeSql.PostgreSQL {
}
throw new Exception($"PostgreSQLExpression 未现实函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Object == null) {
switch (exp.Method.Name) {
case "ToBoolean": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} not in ('0','false'))";
case "ToByte": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as unsigned)";
case "ToChar": return $"substr(cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as char), 1, 1)";
case "ToDateTime": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as datetime)";
case "ToDecimal": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as decimal(36,18))";
case "ToDouble": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as decimal(32,16))";
case "ToInt16":
case "ToInt32":
case "ToInt64":
case "ToSByte": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as signed)";
case "ToSingle": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as decimal(14,7))";
case "ToString": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as char)";
case "ToUInt16":
case "ToUInt32":
case "ToUInt64": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as unsigned)";
}
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
}
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
}
}
}

View File

@ -85,7 +85,7 @@ namespace FreeSql.SqlServer {
if (_orm.Ado.ExecuteScalar(CommandType.Text, string.Format("select 1 from dbo.sysobjects where id = object_id(N'[{0}].[{1}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1", tbname)) == null) { //表不存在
if (tboldname != null && _orm.Ado.ExecuteScalar(CommandType.Text, string.Format("select 1 from dbo.sysobjects where id = object_id(N'[{0}].[{1}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1", tboldname)) != null) { //旧表存在
//修改表名
//修改表名
sb.Append(_commonUtils.FormatSql("EXEC sp_rename {0}, {1};\r\n", _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}"), _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")));
isRenameTable = true;
@ -94,7 +94,7 @@ namespace FreeSql.SqlServer {
sb.Append("CREATE TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" (");
foreach (var tbcol in tb.Columns.Values) {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ");
sb.Append(tbcol.Attribute.DbType.ToUpper());
sb.Append(tbcol.Attribute.DbType);
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" identity(1,1)");
if (tbcol.Attribute.IsPrimary) sb.Append(" primary key");
sb.Append(",");
@ -126,39 +126,95 @@ left join sys.tables d on d.object_id = a.object_id
left join sys.schemas e on e.schema_id = d.schema_id
where a.object_id in (object_id(N'[{0}].[{1}]'))", isRenameTable ? tboldname : tbname);
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
foreach (var row in ds) {
string column = string.Concat(row[0]);
string sqlType = string.Concat(row[1]).ToLower();
bool is_nullable = string.Concat(row[2]) == "1";
bool is_identity = string.Concat(row[3]) == "1";
if (addcols.TryGetValue(column, out var trycol)) {
if (Regex.Replace(trycol.Attribute.DbType, @"\([^\)]+\)", m => Regex.Replace(m.Groups[0].Value, @"\s", "")).StartsWith(sqlType, StringComparison.CurrentCultureIgnoreCase) == false ||
(trycol.Attribute.DbType.IndexOf("NOT NULL", StringComparison.CurrentCultureIgnoreCase) == -1) != is_nullable ||
trycol.Attribute.IsIdentity != is_identity) {
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(column)).Append(" ").Append(trycol.Attribute.DbType.ToUpper());
if (trycol.Attribute.IsIdentity && trycol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" identity(1,1)");
sb.Append(";\r\n");
var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => new {
column = string.Concat(a[0]),
sqlType = string.Concat(a[1]),
is_nullable = string.Concat(a[2]) == "1",
is_identity = string.Concat(a[3]) == "1"
}, StringComparer.CurrentCultureIgnoreCase);
var sbalter = new StringBuilder();
var istmpatler = false;
foreach (var tbcol in tb.Columns.Values) {
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false ||
tbcol.Attribute.IsNullable != tbstructcol.is_nullable ||
tbcol.Attribute.IsIdentity != tbstructcol.is_identity) {
istmpatler = true;
break;
}
addcols.Remove(column);
} else
surplus.Add(column, true); //记录剩余字段
if (tbstructcol.column == tbcol.Attribute.OldName) {
//修改列名
sbalter.Append(_commonUtils.FormatSql("EXEC sp_rename {0}, {1}, 'COLUMN';\r\n", $"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.OldName}", tbcol.Attribute.Name));
}
continue;
}
//添加列
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType);
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sbalter.Append(" identity(1,1)");
var addcoldbdefault = tb.Properties[tbcol.CsName].GetValue(Activator.CreateInstance(tb.Type));
if (tbcol.Attribute.IsNullable == false) addcoldbdefault = tbcol.Attribute.DbDefautValue;
if (addcoldbdefault != null) sbalter.Append(_commonUtils.FormatSql(" default({0})", addcoldbdefault));
sbalter.Append(";\r\n");
}
foreach (var addcol in addcols.Values) {
if (string.IsNullOrEmpty(addcol.Attribute.OldName) == false && surplus.ContainsKey(addcol.Attribute.OldName)) { //修改列名
sb.Append(_commonUtils.FormatSql("EXEC sp_rename {0}, {1}, 'COLUMN';\r\n", $"{tbname[0]}.{tbname[1]}.{addcol.Attribute.OldName}", addcol.Attribute.Name));
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.Name)).Append(" ").Append(addcol.Attribute.DbType.ToUpper());
if (addcol.Attribute.IsIdentity && addcol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" identity(1,1)");
if (addcol.Attribute.DbType.ToUpper().Contains("NOT NULL")) sb.Append(_commonUtils.FormatSql(" default({0})", Activator.CreateInstance(addcol.CsType.GenericTypeArguments.FirstOrDefault() ?? addcol.CsType)));
sb.Append(";\r\n");
} else { //添加列
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD ").Append(_commonUtils.QuoteSqlName(addcol.Attribute.Name)).Append(" ").Append(addcol.Attribute.DbType.ToUpper());
if (addcol.Attribute.IsIdentity && addcol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" identity(1,1)");
if (addcol.Attribute.DbType.ToUpper().Contains("NOT NULL")) sb.Append(_commonUtils.FormatSql(" default({0})", Activator.CreateInstance(addcol.CsType.GenericTypeArguments.FirstOrDefault() ?? addcol.CsType)));
sb.Append(";\r\n");
if (istmpatler == false) {
sb.Append(sbalter);
continue;
}
//创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名
bool idents = false;
var tablename = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}");
var tmptablename = _commonUtils.QuoteSqlName($"{tbname[0]}.TmpFreeSqlTmp_{tbname[1]}");
sb.Append("BEGIN TRANSACTION\r\n")
.Append("SET QUOTED_IDENTIFIER ON\r\n")
.Append("SET ARITHABORT ON\r\n")
.Append("SET NUMERIC_ROUNDABORT OFF\r\n")
.Append("SET CONCAT_NULL_YIELDS_NULL ON\r\n")
.Append("SET ANSI_NULLS ON\r\n")
.Append("SET ANSI_PADDING ON\r\n")
.Append("SET ANSI_WARNINGS ON\r\n")
.Append("COMMIT\r\n");
sb.Append("BEGIN TRANSACTION;\r\n");
//创建临时表
sb.Append("CREATE TABLE ").Append(tmptablename).Append(" (");
foreach (var tbcol in tb.Columns.Values) {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ");
sb.Append(tbcol.Attribute.DbType);
if (tbcol.Attribute.IsIdentity && tbcol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" identity(1,1)");
if (tbcol.Attribute.IsPrimary) sb.Append(" primary key");
sb.Append(",");
idents = idents || tbcol.Attribute.IsIdentity;
}
sb.Remove(sb.Length - 1, 1).Append("\r\n);\r\n");
sb.Append("ALTER TABLE ").Append(tmptablename).Append(" SET (LOCK_ESCALATION = TABLE);\r\n");
if (idents) sb.Append("SET IDENTITY_INSERT ").Append(tmptablename).Append(" ON;\r\n");
sb.Append("IF EXISTS(SELECT 1 FROM ").Append(tablename).Append(")\r\n");
sb.Append("\tEXEC('INSERT INTO ").Append(tmptablename).Append(" (");
foreach (var tbcol in tb.Columns.Values) {
if (tbstruct.ContainsKey(tbcol.Attribute.Name) || tbstruct.ContainsKey(tbcol.Attribute.OldName)) { //导入旧表存在的字段
sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
}
}
sb.Remove(sb.Length - 2, 2).Append(")\r\n\t\tSELECT ");
foreach (var tbcol in tb.Columns.Values) {
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
var insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column);
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) {
var tbcoldbtype = tbcol.Attribute.DbType.Split(' ').First();
insertvalue = $"cast({insertvalue} as {tbcoldbtype})";
}
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) {
insertvalue = $"isnull({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''")})";
}
sb.Append(insertvalue).Append(", ");
}
}
sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append(" WITH (HOLDLOCK TABLOCKX)');\r\n");
if (idents) sb.Append("SET IDENTITY_INSERT ").Append(tmptablename).Append(" OFF;\r\n");
sb.Append("DROP TABLE ").Append(tablename).Append(";\r\n");
sb.Append("EXECUTE sp_rename N'").Append(tmptablename).Append("', N'").Append(tbname[1]).Append("', 'OBJECT' ;\r\n");
sb.Append("COMMIT;\r\n");
}
return sb.Length == 0 ? null : sb.ToString();
}

View File

@ -37,8 +37,8 @@ namespace FreeSql.SqlServer {
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "Date": return $"convert(char(10),{left},120)";
case "TimeOfDay": return $"datediff(second, '1970-1-1 ' + convert(varchar, {left}, 14), {left})";
case "DayOfWeek": return $"(datepart(weekday, {left}) - 1)";
case "TimeOfDay": return $"datediff(second, convert(char(10),{left},120), {left})";
case "DayOfWeek": return $"(datepart(weekday, {left})-1)";
case "Day": return $"datepart(day, {left})";
case "DayOfYear": return $"datepart(dayofyear, {left})";
case "Month": return $"datepart(month, {left})";
@ -46,8 +46,8 @@ namespace FreeSql.SqlServer {
case "Hour": return $"datepart(hour, {left})";
case "Minute": return $"datepart(minute, {left})";
case "Second": return $"datepart(second, {left})";
case "Millisecond": return $"datepart(millisecond, {left})";
case "Ticks": return $"datediff(second, '1970-1-1', {left})";
case "Millisecond": return $"(datepart(millisecond, {left})/1000)";
case "Ticks": return $"(cast(datediff(second, '1970-1-1', {left}) as bigint)*10000000+621355968000000000)";
}
return null;
}
@ -62,16 +62,16 @@ namespace FreeSql.SqlServer {
}
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Member.Name) {
case "Days": return $"floor(({left}) / {60 * 60 * 24})";
case "Hours": return $"floor(({left}) / {60 * 60} % 24)";
case "Milliseconds": return $"(cast({left} as bigint) * 1000)";
case "Minutes": return $"floor(({left}) / 60 % 60)";
case "Seconds": return $"(({left}) % 60)";
case "Ticks": return $"(cast({left} as bigint) * 10000000)";
case "TotalDays": return $"(({left}) / {60 * 60 * 24})";
case "TotalHours": return $"(({left}) / {60 * 60})";
case "TotalMilliseconds": return $"(cast({left} as bigint) * 1000)";
case "TotalMinutes": return $"(({left}) / 60)";
case "Days": return $"floor(({left})/{60 * 60 * 24})";
case "Hours": return $"floor(({left})/{60 * 60}%24)";
case "Milliseconds": return $"(cast({left} as bigint)*1000)";
case "Minutes": return $"floor(({left})/60%60)";
case "Seconds": return $"(({left})%60)";
case "Ticks": return $"(cast({left} as bigint)*10000000)";
case "TotalDays": return $"(({left})/{60 * 60 * 24})";
case "TotalHours": return $"(({left})/{60 * 60})";
case "TotalMilliseconds": return $"(cast({left} as bigint)*1000)";
case "TotalMinutes": return $"(({left})/60)";
case "TotalSeconds": return $"({left})";
}
return null;
@ -85,22 +85,27 @@ namespace FreeSql.SqlServer {
case "Contains":
var args0Value = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (args0Value == "NULL") return $"({left}) IS NULL";
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(cast({args0Value} as nvarchar) + '%')")}";
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%' + cast({args0Value} as nvarchar))")}";
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(cast({args0Value} as nvarchar)+'%')")}";
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%'+cast({args0Value} as nvarchar))")}";
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
return $"({left}) LIKE ('%' + cast({args0Value} as nvarchar) + '%')";
return $"({left}) LIKE ('%'+cast({args0Value} as nvarchar)+'%')";
case "ToLower": return $"lower({left})";
case "ToUpper": return $"upper({left})";
case "Substring":
var substrArgs1 = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (long.TryParse(substrArgs1, out var testtrylng1)) substrArgs1 = (testtrylng1 + 1).ToString();
else substrArgs1 += " + 1";
else substrArgs1 += "+1";
if (exp.Arguments.Count == 1) return $"left({left}, {substrArgs1})";
return $"substring({left}, {substrArgs1}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "IndexOf":
var indexOfFindStr = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"(charindex({left}, {indexOfFindStr}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)} + 1) - 1)";
return $"(charindex({left}, {indexOfFindStr}) - 1)";
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") {
var locateArgs1 = ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName);
if (long.TryParse(locateArgs1, out var testtrylng2)) locateArgs1 = (testtrylng2 + 1).ToString();
else locateArgs1 += "+1";
return $"(charindex({left}, {indexOfFindStr}, {locateArgs1})-1)";
}
return $"(charindex({left}, {indexOfFindStr})-1)";
case "PadLeft":
if (exp.Arguments.Count == 1) return $"lpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
return $"lpad({left}, {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}, {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
@ -144,71 +149,93 @@ namespace FreeSql.SqlServer {
internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Object == null) {
switch (exp.Method.Name) {
case "Compare": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}) - ({ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "Compare": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} - ({ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "DaysInMonth": return $"datepart(day, dateadd(day, -1, dateadd(month, 1, cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as varchar) + '-' + cast({ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)} as varchar) + '-1')))";
case "Equals": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} = {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "IsLeapYear":
var isLeapYearArgs1 = ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
return $"(({isLeapYearArgs1}) % 4 = 0 AND ({isLeapYearArgs1}) % 100 <> 0 OR ({isLeapYearArgs1}) % 400 = 0)";
return $"(({isLeapYearArgs1})%4=0 AND ({isLeapYearArgs1})%100<>0 OR ({isLeapYearArgs1})%400=0)";
case "Parse": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as datetime)";
case "ParseExact":
case "TryParse":
case "TryParseExact": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as datetime)";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
var args1 = exp.Arguments.Count == 0 ? null : ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "Add": return $"dateadd(second, {args1}, {left})";
case "AddDays": return $"dateadd(day, {args1}, {left})";
case "AddHours": return $"dateadd(hour, {args1}, {left})";
case "AddMilliseconds": return $"dateadd(second, {args1} / 1000, {left})";
case "AddMinutes": return $"dateadd(minute, {args1}, {left})";
case "AddMonths": return $"dateadd(month, {args1}, {left})";
case "AddSeconds": return $"dateadd(second, {args1}, {left})";
case "AddTicks": return $"dateadd(second, {args1} / 10000000, {left})";
case "AddYears": return $"dateadd(year, {args1}, {left})";
case "Subtract":
if (exp.Arguments[0].Type.FullName == "System.DateTime" || exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.DateTime")
return $"datediff(second, {args1}, {left})";
if (exp.Arguments[0].Type.FullName == "System.TimeSpan" || exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.TimeSpan")
return $"dateadd(second, {args1} * -1, {left})";
break;
case "Equals": return $"({left} = {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "CompareTo": return $"(({left}) - ({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "ToString": return $"convert(varchar, {left}, 121)";
} else {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
var args1 = exp.Arguments.Count == 0 ? null : ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "Add": return $"dateadd(second, {args1}, {left})";
case "AddDays": return $"dateadd(day, {args1}, {left})";
case "AddHours": return $"dateadd(hour, {args1}, {left})";
case "AddMilliseconds": return $"dateadd(second, ({args1})/1000, {left})";
case "AddMinutes": return $"dateadd(minute, {args1}, {left})";
case "AddMonths": return $"dateadd(month, {args1}, {left})";
case "AddSeconds": return $"dateadd(second, {args1}, {left})";
case "AddTicks": return $"dateadd(second, ({args1})/10000000, {left})";
case "AddYears": return $"dateadd(year, {args1}, {left})";
case "Subtract":
if (exp.Arguments[0].Type.FullName == "System.DateTime" || exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.DateTime")
return $"datediff(second, {args1}, {left})";
if (exp.Arguments[0].Type.FullName == "System.TimeSpan" || exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.TimeSpan")
return $"dateadd(second, {args1}*-1, {left})";
break;
case "Equals": return $"({left} = {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "CompareTo": return $"(({left}) - ({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "ToString": return $"convert(varchar, {left}, 121)";
}
}
throw new Exception($"SqlServerExpression 未现实函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Object == null) {
switch (exp.Method.Name) {
case "Compare": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}) - ({ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "Compare": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}-({ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "Equals": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} = {ExpressionLambdaToSql(exp.Arguments[1], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "FromDays": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} * {60 * 60 * 24})";
case "FromHours": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} * {60 * 60})";
case "FromMilliseconds": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} / 1000)";
case "FromMinutes": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} * 60)";
case "FromDays": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})*{60 * 60 * 24})";
case "FromHours": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})*{60 * 60})";
case "FromMilliseconds": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})/1000)";
case "FromMinutes": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})*60)";
case "FromSeconds": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "FromTicks": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} / 10000000)";
case "FromTicks": return $"(({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})/10000000)";
case "Parse": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as bigint)";
case "ParseExact":
case "TryParse":
case "TryParseExact": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as bigint)";
}
return null;
} else {
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
var args1 = exp.Arguments.Count == 0 ? null : ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "Add": return $"({left}+{args1})";
case "Subtract": return $"({left}-({args1}))";
case "Equals": return $"({left} = {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "CompareTo": return $"({left}-({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "ToString": return $"cast({left} as varchar)";
}
}
var left = ExpressionLambdaToSql(exp.Object, _tables, _selectColumnMap, tbtype, isQuoteName);
var args1 = exp.Arguments.Count == 0 ? null : ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName);
switch (exp.Method.Name) {
case "Add": return $"({left} + {args1})";
case "Subtract": return $"({left} - {args1})";
case "Equals": return $"({left} = {ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)})";
case "CompareTo": return $"(({left}) - ({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)}))";
case "ToString": return $"cast({left} as varchar)";
throw new Exception($"SqlServerExpression 未现实函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, bool isQuoteName) {
if (exp.Object == null) {
switch (exp.Method.Name) {
case "ToBoolean": return $"({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} not in ('0','false'))";
case "ToByte": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as tinyint)";
case "ToChar": return $"substring(cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as nvarchar), 1, 1)";
case "ToDateTime": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as datetime)";
case "ToDecimal": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as decimal(36,18))";
case "ToDouble": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as decimal(32,16))";
case "ToInt16": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as smallint)";
case "ToInt32": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as int)";
case "ToInt64": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as bigint)";
case "ToSByte": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as tinyint)";
case "ToSingle": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as decimal(14,7))";
case "ToString": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as nvarchar)";
case "ToUInt16": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as smallint)";
case "ToUInt32": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as int)";
case "ToUInt64": return $"cast({ExpressionLambdaToSql(exp.Arguments[0], _tables, _selectColumnMap, tbtype, isQuoteName)} as bigint)";
}
}
throw new Exception($"SqlServerExpression 未现实函数表达式 {exp} 解析");
}