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

@ -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]", "_");