diff --git a/FreeSql.DbContext/Extensions/DependencyInjection.cs b/FreeSql.DbContext/Extensions/DependencyInjection.cs index ebd575e1..cad5047f 100644 --- a/FreeSql.DbContext/Extensions/DependencyInjection.cs +++ b/FreeSql.DbContext/Extensions/DependencyInjection.cs @@ -15,7 +15,7 @@ namespace FreeSql DbContext ctx = null; try { - var ctor = dbContextType.GetConstructors().FirstOrDefault(); + var ctor = dbContextType. GetConstructors().FirstOrDefault(); var ctorParams = ctor.GetParameters().Select(a => sp.GetService(a.ParameterType)).ToArray(); ctx = Activator.CreateInstance(dbContextType, ctorParams) as DbContext; } diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index d9f91124..dc0203b8 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -110,13 +110,6 @@ 清空状态数据 - - - 根据 lambda 条件删除数据 - - - - 添加 diff --git a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs index c76fea46..0cf69bea 100644 --- a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs @@ -1056,6 +1056,23 @@ WHERE (((cast(a.`Id` as char)) in (SELECT b.`Title` a.Id, a.Clicks }); + + Assert.Equal(@"SELECT a.`Id` as1, a.`Clicks` as2 +FROM (SELECT * from (SELECT a.`Id` Id, a.`Clicks` Clicks +FROM `tb_topic_1` a) ftb + +UNION ALL + +SELECT * from (SELECT a.`Id` Id, a.`Clicks` Clicks +FROM `tb_topic_2` a) ftb) a +limit 0,20", select + .AsTable((type, old) => type == typeof(Topic) ? $"({sqlsss})" : null) + .Page(1, 20) + .ToSql(a => new + { + a.Id, + a.Clicks + })); } public class TestInclude_OneToManyModel1 diff --git a/FreeSql.Tests/FreeSql.Tests/MySql/MySqlCodeFirstTest.cs b/FreeSql.Tests/FreeSql.Tests/MySql/MySqlCodeFirstTest.cs index 6ad6d8e6..6a0da303 100644 --- a/FreeSql.Tests/FreeSql.Tests/MySql/MySqlCodeFirstTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MySql/MySqlCodeFirstTest.cs @@ -17,11 +17,7 @@ namespace FreeSql.Tests.MySql var sql = g.mysql.CodeFirst.GetComparisonDDLStatements<ı2>(); g.mysql.CodeFirst.SyncStructure<ı2>(); - var item = new ı2 - { - = "Ա", - ʱ = DateTime.Now - }; + var item = ı2.Create("Ա", DateTime.Now); Assert.Equal(1, g.mysql.Insert<ı2>().AppendData(item).ExecuteAffrows()); Assert.NotEqual(Guid.Empty, item.); var item2 = g.mysql.Select<ı2>().Where(a => a. == item.).First(); @@ -32,12 +28,17 @@ namespace FreeSql.Tests.MySql class ı2 { [Column(IsPrimary = true)] - public Guid { get; set; } + public Guid { get; protected set; } - public string { get; set; } + public string { get; protected set; } [Column(ServerTime = DateTimeKind.Local)] - public DateTime ʱ { get; set; } + public DateTime ʱ { get; protected set; } + + public static ı2 Create(string title, DateTime ctm) + { + return new ı2 { = title, ʱ = ctm }; + } } [Fact] diff --git a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs index 86449244..f04dc599 100644 --- a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs +++ b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs @@ -47,21 +47,35 @@ public static partial class FreeSqlGlobalExtensions public static bool IsArrayOrList(this Type that) => that == null ? false : (that.IsArray || typeof(IList).IsAssignableFrom(that)); public static Type NullableTypeOrThis(this Type that) => that?.IsNullableType() == true ? that.GetGenericArguments().First() : that; internal static string NotNullAndConcat(this string that, params object[] args) => string.IsNullOrEmpty(that) ? null : string.Concat(new object[] { that }.Concat(args)); - static ConcurrentDictionary _dicGetDefaultValueFirstConstructorsParameters = new ConcurrentDictionary(); public static object CreateInstanceGetDefaultValue(this Type that) { if (that == null) return null; if (that == typeof(string)) return default(string); if (that.IsArray) return Array.CreateInstance(that, 0); - var ctorParms = _dicGetDefaultValueFirstConstructorsParameters.GetOrAdd(that, tp => tp.GetConstructors().FirstOrDefault()?.GetParameters()); + var ctorParms = that.InternalGetTypeConstructor0OrFirst(false)?.GetParameters(); if (ctorParms == null || ctorParms.Any() == false) return Activator.CreateInstance(that, null); return Activator.CreateInstance(that, ctorParms.Select(a => Activator.CreateInstance(a.ParameterType, null)).ToArray()); } + internal static NewExpression InternalNewExpression(this Type that) + { + var ctor = that.InternalGetTypeConstructor0OrFirst(); + return Expression.New(ctor, ctor.GetParameters().Select(a => Expression.Constant(a.ParameterType.CreateInstanceGetDefaultValue(), a.ParameterType))); + } + + static ConcurrentDictionary _dicInternalGetTypeConstructor0OrFirst = new ConcurrentDictionary(); + internal static ConstructorInfo InternalGetTypeConstructor0OrFirst(this Type that, bool isThrow = true) + { + var ret = _dicInternalGetTypeConstructor0OrFirst.GetOrAdd(that, tp => + tp.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null) ?? + tp.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault()); + if (ret == null && isThrow) throw new ArgumentException($"{that.FullName} 类型无方法访问构造函数"); + return ret; + } static ConcurrentDictionary> _dicGetPropertiesDictIgnoreCase = new ConcurrentDictionary>(); public static Dictionary GetPropertiesDictIgnoreCase(this Type that) => that == null ? null : _dicGetPropertiesDictIgnoreCase.GetOrAdd(that, tp => { - var props = that.GetProperties(); + var props = that.GetProperties().GroupBy(p => p.DeclaringType).Reverse().SelectMany(p => p); //将基类的属性位置放在前面 #164 var dict = new Dictionary(StringComparer.CurrentCultureIgnoreCase); foreach (var prop in props) { diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index ab2373ff..ec8770fc 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -52,7 +52,8 @@ namespace FreeSql.Internal var constExpValue = constExp.Value?.ToString() ?? "NULL"; if (constExpValue == string.Empty) constExpValue = _common.FormatSql("{0}", ""); parent.DbField = constExpValue; - } else + } + else parent.DbField = _common.FormatSql("{0}", constExp?.Value); field.Append(", ").Append(parent.DbField); if (index >= 0) field.Append(" as").Append(++index); @@ -82,8 +83,8 @@ namespace FreeSql.Internal var map = new List(); ExpressionSelectColumn_MemberAccess(_tables, map, SelectTableInfoType.From, exp, true, getSelectGroupingMapString); var tb = parent.Table = map.First().Table.Table; - parent.Consturctor = tb.Type.GetConstructor(new Type[0]); - parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties; + parent.CsType = tb.Type; + parent.Consturctor = tb.Type.InternalGetTypeConstructor0OrFirst(); parent.IsEntity = true; for (var idx = 0; idx < map.Count; idx++) { @@ -113,10 +114,25 @@ namespace FreeSql.Internal return false; case ExpressionType.MemberInit: var initExp = exp as MemberInitExpression; - parent.Consturctor = initExp.NewExpression.Type.GetConstructors()[0]; - parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties; - - if (isAllDtoMap && _tables != null && _tables.Any() && initExp.NewExpression.Type != _tables.FirstOrDefault().Table.Type) + parent.CsType = initExp.Type; + parent.Consturctor = initExp.NewExpression.Constructor; + if (initExp.NewExpression?.Arguments.Count > 0) + { + //处理构造参数 + for (var a = 0; a < initExp.NewExpression.Arguments.Count; a++) + { + var child = new ReadAnonymousTypeInfo + { + Property = null, + CsName = initExp.NewExpression.Members[a].Name, + CsType = initExp.NewExpression.Arguments[a].Type, + MapType = initExp.NewExpression.Arguments[a].Type + }; + parent.Childs.Add(child); + ReadAnonymousField(_tables, field, child, ref index, initExp.NewExpression.Arguments[a], getSelectGroupingMapString, whereCascadeExpression, false); + } + } + else if (isAllDtoMap && _tables != null && _tables.Any() && initExp.NewExpression.Type != _tables.FirstOrDefault().Table.Type) { //dto 映射 var dtoProps = initExp.NewExpression.Type.GetPropertiesDictIgnoreCase().Values; @@ -124,26 +140,26 @@ namespace FreeSql.Internal { foreach (var dtTb in _tables) { - if (dtTb.Table.Columns.TryGetValue(dtoProp.Name, out var trydtocol)) + if (dtTb.Table.Columns.TryGetValue(dtoProp.Name, out var trydtocol) == false) continue; + if (trydtocol.Attribute.IsIgnore == true) continue; + + var child = new ReadAnonymousTypeInfo { - var child = new ReadAnonymousTypeInfo - { - Property = dtoProp, - CsName = dtoProp.Name, - CsType = trydtocol.CsType, // dtoProp.PropertyType, - MapType = trydtocol.Attribute.MapType - }; - parent.Childs.Add(child); - if (dtTb.Parameter != null) - ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap); - else - { - child.DbField = $"{dtTb.Alias}.{_common.QuoteSqlName(trydtocol.Attribute.Name)}"; - field.Append(", ").Append(child.DbField); - if (index >= 0) field.Append(" as").Append(++index); - } - break; + Property = dtoProp, + CsName = dtoProp.Name, + CsType = trydtocol.CsType, // dtoProp.PropertyType, + MapType = trydtocol.Attribute.MapType + }; + parent.Childs.Add(child); + if (dtTb.Parameter != null) + ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap); + else + { + child.DbField = $"{dtTb.Alias}.{_common.QuoteSqlName(trydtocol.Attribute.Name)}"; + field.Append(", ").Append(child.DbField); + if (index >= 0) field.Append(" as").Append(++index); } + break; } } } @@ -169,15 +185,27 @@ namespace FreeSql.Internal return true; case ExpressionType.New: var newExp = exp as NewExpression; - parent.Consturctor = newExp.Type.GetConstructors()[0]; - parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Arguments; - if (newExp.Members?.Count > 0) + parent.CsType = newExp.Type; + parent.Consturctor = newExp.Constructor; + if (newExp.Arguments?.Count > 0 && + ( + newExp.Type.IsAnonymousType() || + newExp.Arguments.Any(a => + { + if (a.NodeType != ExpressionType.Constant) return true; + var constVal = (a as ConstantExpression)?.Value; + if (constVal == null) return true; + if (object.Equals(constVal, a.Type.CreateInstanceGetDefaultValue()) == false) return true; + return false; + }) + )) { - for (var a = 0; a < newExp.Members.Count; a++) + //处理构造参数 + for (var a = 0; a < newExp.Arguments.Count; a++) { var child = new ReadAnonymousTypeInfo { - Property = newExp.Type.GetProperty(newExp.Members[a].Name, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance), + Property = null, CsName = newExp.Members[a].Name, CsType = newExp.Arguments[a].Type, MapType = newExp.Arguments[a].Type @@ -188,37 +216,37 @@ namespace FreeSql.Internal } else { + parent.IsDefaultCtor = true; //dto 映射 - parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties; var dtoProps2 = newExp.Type.GetPropertiesDictIgnoreCase().Values; foreach (var dtoProp in dtoProps2) { foreach (var dtTb in _tables) { - if (dtTb.Table.ColumnsByCs.TryGetValue(dtoProp.Name, out var trydtocol)) + if (dtTb.Table.ColumnsByCs.TryGetValue(dtoProp.Name, out var trydtocol) == false) continue; + if (trydtocol.Attribute.IsIgnore == true) continue; + + var child = new ReadAnonymousTypeInfo { - var child = new ReadAnonymousTypeInfo - { - Property = dtoProp, - CsName = dtoProp.Name, - CsType = trydtocol.CsType, //dtoProp.PropertyType, - MapType = trydtocol.Attribute.MapType - }; - parent.Childs.Add(child); - if (dtTb.Parameter != null) - ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap); - else - { - child.DbField = $"{dtTb.Alias}.{_common.QuoteSqlName(trydtocol.Attribute.Name)}"; - field.Append(", ").Append(child.DbField); - if (index >= 0) field.Append(" as").Append(++index); - } - break; + Property = dtoProp, + CsName = dtoProp.Name, + CsType = trydtocol.CsType, //dtoProp.PropertyType, + MapType = trydtocol.Attribute.MapType + }; + parent.Childs.Add(child); + if (dtTb.Parameter != null) + ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap); + else + { + child.DbField = $"{dtTb.Alias}.{_common.QuoteSqlName(trydtocol.Attribute.Name)}"; + field.Append(", ").Append(child.DbField); + if (index >= 0) field.Append(" as").Append(++index); } + break; } } - if (parent.Childs.Any() == false) throw new Exception($"映射异常:{newExp.Type.Name} 没有一个属性名相同"); } + if (parent.Childs.Any() == false) throw new Exception($"映射异常:{newExp.Type.Name} 没有一个属性名相同"); return true; } parent.DbField = $"({ExpressionLambdaToSql(exp, getTSC())})"; @@ -247,33 +275,30 @@ namespace FreeSql.Internal objval = Utils.GetDataReaderValue(parent.Property.PropertyType, objval); return objval; } - switch (parent.ConsturctorType) + var ctorParmsLength = 0; + object ret; + if (parent.IsDefaultCtor || parent.IsEntity || (ctorParmsLength = parent.Consturctor.GetParameters()?.Length ?? 0) == 0) + ret = parent.CsType?.CreateInstanceGetDefaultValue() ?? parent.Consturctor.Invoke(null); + else { - case ReadAnonymousTypeInfoConsturctorType.Arguments: - var args = new object[parent.Childs.Count]; - for (var a = 0; a < parent.Childs.Count; a++) - { - var objval = ReadAnonymous(parent.Childs[a], dr, ref index, notRead, null); - if (notRead == false) - args[a] = objval; - } - return parent.Consturctor.Invoke(args); - case ReadAnonymousTypeInfoConsturctorType.Properties: - var ret = parent.Consturctor.Invoke(null); - var isnull = notRead; - for (var b = 0; b < parent.Childs.Count; b++) - { - var prop = parent.Childs[b].Property; - var dbval = parent.IsEntity ? new ReadAnonymousDbValueRef() : null; - var objval = ReadAnonymous(parent.Childs[b], dr, ref index, notRead, dbval); - if (isnull == false && parent.IsEntity && dbval.DbValue == null && parent.Table != null && parent.Table.ColumnsByCs.TryGetValue(parent.Childs[b].CsName, out var trycol) && trycol.Attribute.IsPrimary) - isnull = true; - if (isnull == false && prop.CanWrite) - prop.SetValue(ret, objval, null); - } - return isnull ? null : ret; + var ctorParms = new object[ctorParmsLength]; + for (var c = 0; c < ctorParmsLength; c++) + ctorParms[c] = ReadAnonymous(parent.Childs[c], dr, ref index, notRead, null); + ret = parent.Consturctor.Invoke(ctorParms); } - return null; + + var isnull = notRead; + for (var b = ctorParmsLength; b < parent.Childs.Count; b++) + { + var prop = parent.Childs[b].Property; + var dbval = parent.IsEntity ? new ReadAnonymousDbValueRef() : null; + var objval = ReadAnonymous(parent.Childs[b], dr, ref index, notRead, dbval); + if (isnull == false && parent.IsEntity && dbval.DbValue == null && parent.Table != null && parent.Table.ColumnsByCs.TryGetValue(parent.Childs[b].CsName, out var trycol) && trycol.Attribute.IsPrimary) + isnull = true; + if (isnull == false && prop.CanWrite) + prop.SetValue(ret, objval, null); + } + return isnull ? null : ret; } public class ReadAnonymousDbValueRef { diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index 0a36fad7..2881b8fb 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -546,7 +546,6 @@ namespace FreeSql.Internal.CommonProvider _commonExpression.ReadAnonymousField(_tables, field, map, ref index, newexp, null, _whereCascadeExpression, true); return (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null); } - static ConcurrentDictionary _dicConstructor = new ConcurrentDictionary(); static ConcurrentDictionary _dicGetAllFieldExpressionTree = new ConcurrentDictionary(); public class GetAllFieldExpressionTreeInfo { @@ -568,9 +567,8 @@ namespace FreeSql.Internal.CommonProvider var readExpValue = Expression.MakeMemberAccess(readExp, Utils.RowInfo.PropertyValue); var readExpDataIndex = Expression.MakeMemberAccess(readExp, Utils.RowInfo.PropertyDataIndex); var blockExp = new List(); - var ctor = type.GetConstructor(new Type[0]) ?? type.GetConstructors().First(); blockExp.AddRange(new Expression[] { - Expression.Assign(retExp, Expression.New(ctor, ctor.GetParameters().Select(a => Expression.Default(a.ParameterType)))), + Expression.Assign(retExp, type.InternalNewExpression()), Expression.Assign(dataIndexExp, Expression.Constant(0)) }); //typeof(Topic).GetMethod("get_Type").IsVirtual @@ -711,9 +709,8 @@ namespace FreeSql.Internal.CommonProvider var readExpValue = Expression.MakeMemberAccess(readExp, Utils.RowInfo.PropertyValue); var readExpDataIndex = Expression.MakeMemberAccess(readExp, Utils.RowInfo.PropertyDataIndex); var blockExp = new List(); - var ctor = type.GetConstructor(new Type[0]) ?? type.GetConstructors().First(); blockExp.AddRange(new Expression[] { - Expression.Assign(retExp, Expression.New(ctor, ctor.GetParameters().Select(a => Expression.Default(a.ParameterType)))), + Expression.Assign(retExp, type.InternalNewExpression()), Expression.Assign(dataIndexExp, Expression.Constant(0)) }); //typeof(Topic).GetMethod("get_Type").IsVirtual @@ -762,7 +759,7 @@ namespace FreeSql.Internal.CommonProvider } } //只读到二级属性 - var propGetSetMethod = prop.GetSetMethod(); + var propGetSetMethod = prop.GetSetMethod(true); Expression readExpAssign = null; //加速缓存 if (prop.PropertyType.IsArray) readExpAssign = Expression.New(Utils.RowInfo.Constructor, Utils.GetDataReaderValueBlockExpression(prop.PropertyType, Expression.Call(rowExp, Utils.MethodDataReaderGetValue, dataIndexExp)), @@ -836,9 +833,9 @@ namespace FreeSql.Internal.CommonProvider protected (ReadAnonymousTypeInfo map, string field) GetAllFieldReflection() { var tb1 = _tables.First().Table; - var type = tb1.Type; - var constructor = _dicConstructor.GetOrAdd(type, s => type.GetConstructor(new Type[0])); - var map = new ReadAnonymousTypeInfo { Consturctor = constructor, ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties }; + var type = tb1.TypeLazy ?? tb1.Type; + var constructor = type.InternalGetTypeConstructor0OrFirst(); + var map = new ReadAnonymousTypeInfo { CsType = type, Consturctor = constructor, IsEntity = true }; var field = new StringBuilder(); var dicfield = new Dictionary(); @@ -862,8 +859,9 @@ namespace FreeSql.Internal.CommonProvider var tb2 = _tables.Where(a => a.Table.Type == p.PropertyType && a.Alias.Contains(p.Name)).FirstOrDefault(); if (tb2 == null && ps.Where(pw => pw.Value.PropertyType == p.PropertyType).Count() == 1) tb2 = _tables.Where(a => a.Table.Type == p.PropertyType).FirstOrDefault(); if (tb2 == null) continue; - child.Consturctor = tb2.Table.Type.GetConstructor(new Type[0]); - child.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties; + child.CsType = (tb2.Table.TypeLazy ?? tb2.Table.Type); + child.Consturctor = child.CsType.InternalGetTypeConstructor0OrFirst(); + child.IsEntity = true; foreach (var col2 in tb2.Table.Columns.Values) { if (index > 0) field.Append(", "); diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select10Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select10Provider.cs index fd73c7c0..4ab36722 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select10Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select10Provider.cs @@ -101,8 +101,8 @@ namespace FreeSql.Internal.CommonProvider List ISelect.ToList() => (this as ISelect).ToList(GetToListDtoSelector()); Expression> GetToListDtoSelector() { - var ctor = typeof(TDto).GetConstructor(new Type[0]); - return Expression.Lambda>(Expression.New(ctor), + return Expression.Lambda>( + typeof(TDto).InternalNewExpression(), _tables[0].Parameter ?? Expression.Parameter(typeof(T1), "a"), Expression.Parameter(typeof(T2), "b"), Expression.Parameter(typeof(T3), "c"), diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs index 46667c86..ea6e9ff6 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs @@ -172,8 +172,8 @@ namespace FreeSql.Internal.CommonProvider public List ToList() => ToList(GetToListDtoSelector()); Expression> GetToListDtoSelector() { - var ctor = typeof(TDto).GetConstructor(new Type[0]); - return Expression.Lambda>(Expression.New(ctor), + return Expression.Lambda>( + typeof(TDto).InternalNewExpression(), _tables[0].Parameter ?? Expression.Parameter(typeof(T1), "a")); } @@ -884,8 +884,9 @@ namespace FreeSql.Internal.CommonProvider { var field = new StringBuilder(); var read = new ReadAnonymousTypeInfo(); - read.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties; - read.Consturctor = (tbrefMid.TypeLazy ?? tbrefMid.Type).GetConstructor(new Type[0]); + read.CsType = (tbrefMid.TypeLazy ?? tbrefMid.Type); + read.Consturctor = read.CsType.InternalGetTypeConstructor0OrFirst(); + read.IsEntity = true; read.Table = tbrefMid; foreach (var col in tbrefMid.Columns.Values) { diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select2Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select2Provider.cs index beaa1d50..d8ed2fe8 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select2Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select2Provider.cs @@ -86,8 +86,8 @@ namespace FreeSql.Internal.CommonProvider List ISelect.ToList() => (this as ISelect).ToList(GetToListDtoSelector()); Expression> GetToListDtoSelector() { - var ctor = typeof(TDto).GetConstructor(new Type[0]); - return Expression.Lambda>(Expression.New(ctor), + return Expression.Lambda>( + typeof(TDto).InternalNewExpression(), _tables[0].Parameter ?? Expression.Parameter(typeof(T1), "a"), Expression.Parameter(typeof(T2), "b")); } diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select3Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select3Provider.cs index 5f49d8cf..03cf62e3 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select3Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select3Provider.cs @@ -88,8 +88,8 @@ namespace FreeSql.Internal.CommonProvider List ISelect.ToList() => (this as ISelect).ToList(GetToListDtoSelector()); Expression> GetToListDtoSelector() { - var ctor = typeof(TDto).GetConstructor(new Type[0]); - return Expression.Lambda>(Expression.New(ctor), + return Expression.Lambda>( + typeof(TDto).InternalNewExpression(), _tables[0].Parameter ?? Expression.Parameter(typeof(T1), "a"), Expression.Parameter(typeof(T2), "b"), Expression.Parameter(typeof(T3), "c")); diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select4Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select4Provider.cs index 075397f7..e006c78b 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select4Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select4Provider.cs @@ -90,8 +90,8 @@ namespace FreeSql.Internal.CommonProvider List ISelect.ToList() => (this as ISelect).ToList(GetToListDtoSelector()); Expression> GetToListDtoSelector() { - var ctor = typeof(TDto).GetConstructor(new Type[0]); - return Expression.Lambda>(Expression.New(ctor), + return Expression.Lambda>( + typeof(TDto).InternalNewExpression(), _tables[0].Parameter ?? Expression.Parameter(typeof(T1), "a"), Expression.Parameter(typeof(T2), "b"), Expression.Parameter(typeof(T3), "c"), diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select5Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select5Provider.cs index d21e16a2..76e9ddbc 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select5Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select5Provider.cs @@ -92,8 +92,8 @@ namespace FreeSql.Internal.CommonProvider List ISelect.ToList() => (this as ISelect).ToList(GetToListDtoSelector()); Expression> GetToListDtoSelector() { - var ctor = typeof(TDto).GetConstructor(new Type[0]); - return Expression.Lambda>(Expression.New(ctor), + return Expression.Lambda>( + typeof(TDto).InternalNewExpression(), _tables[0].Parameter ?? Expression.Parameter(typeof(T1), "a"), Expression.Parameter(typeof(T2), "b"), Expression.Parameter(typeof(T3), "c"), diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select6Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select6Provider.cs index 5669598d..81fe63cf 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select6Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select6Provider.cs @@ -94,8 +94,8 @@ namespace FreeSql.Internal.CommonProvider List ISelect.ToList() => (this as ISelect).ToList(GetToListDtoSelector()); Expression> GetToListDtoSelector() { - var ctor = typeof(TDto).GetConstructor(new Type[0]); - return Expression.Lambda>(Expression.New(ctor), + return Expression.Lambda>( + typeof(TDto).InternalNewExpression(), _tables[0].Parameter ?? Expression.Parameter(typeof(T1), "a"), Expression.Parameter(typeof(T2), "b"), Expression.Parameter(typeof(T3), "c"), diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select7Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select7Provider.cs index a8f94ac3..f3a953e6 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select7Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select7Provider.cs @@ -96,8 +96,8 @@ namespace FreeSql.Internal.CommonProvider List ISelect.ToList() => (this as ISelect).ToList(GetToListDtoSelector()); Expression> GetToListDtoSelector() { - var ctor = typeof(TDto).GetConstructor(new Type[0]); - return Expression.Lambda>(Expression.New(ctor), + return Expression.Lambda>( + typeof(TDto).InternalNewExpression(), _tables[0].Parameter ?? Expression.Parameter(typeof(T1), "a"), Expression.Parameter(typeof(T2), "b"), Expression.Parameter(typeof(T3), "c"), diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select8Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select8Provider.cs index f85d2df9..79e5f4af 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select8Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select8Provider.cs @@ -99,8 +99,8 @@ namespace FreeSql.Internal.CommonProvider Expression> GetToListDtoSelector() { - var ctor = typeof(TDto).GetConstructor(new Type[0]); - return Expression.Lambda>(Expression.New(ctor), + return Expression.Lambda>( + typeof(TDto).InternalNewExpression(), _tables[0].Parameter ?? Expression.Parameter(typeof(T1), "a"), Expression.Parameter(typeof(T2), "b"), Expression.Parameter(typeof(T3), "c"), diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select9Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select9Provider.cs index d03d4ba0..ebc99041 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select9Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select9Provider.cs @@ -99,8 +99,8 @@ namespace FreeSql.Internal.CommonProvider List ISelect.ToList() => (this as ISelect).ToList(GetToListDtoSelector()); Expression> GetToListDtoSelector() { - var ctor = typeof(TDto).GetConstructor(new Type[0]); - return Expression.Lambda>(Expression.New(ctor), + return Expression.Lambda>( + typeof(TDto).InternalNewExpression(), _tables[0].Parameter ?? Expression.Parameter(typeof(T1), "a"), Expression.Parameter(typeof(T2), "b"), Expression.Parameter(typeof(T3), "c"), diff --git a/FreeSql/Internal/Model/ReadAnonymousTypeInfo.cs b/FreeSql/Internal/Model/ReadAnonymousTypeInfo.cs index 3ca01e00..d252db75 100644 --- a/FreeSql/Internal/Model/ReadAnonymousTypeInfo.cs +++ b/FreeSql/Internal/Model/ReadAnonymousTypeInfo.cs @@ -13,10 +13,9 @@ namespace FreeSql.Internal.Model public Type MapType { get; set; } public string DbField { get; set; } public ConstructorInfo Consturctor { get; set; } - public ReadAnonymousTypeInfoConsturctorType ConsturctorType { get; set; } public List Childs = new List(); public TableInfo Table { get; set; } public bool IsEntity { get; set; } + public bool IsDefaultCtor { get; set; } } - public enum ReadAnonymousTypeInfoConsturctorType { Arguments, Properties } } diff --git a/FreeSql/Internal/UtilsExpressionTree.cs b/FreeSql/Internal/UtilsExpressionTree.cs index c8b1b92f..83002513 100644 --- a/FreeSql/Internal/UtilsExpressionTree.cs +++ b/FreeSql/Internal/UtilsExpressionTree.cs @@ -72,7 +72,7 @@ namespace FreeSql.Internal var columnsList = new List(); foreach (var p in trytb.Properties.Values) { - var setMethod = p.GetSetMethod(); //trytb.Type.GetMethod($"set_{p.Name}"); + var setMethod = p.GetSetMethod(true); //trytb.Type.GetMethod($"set_{p.Name}"); var colattr = common.GetEntityColumnAttribute(entity, p); var tp = common.CodeFirst.GetDbInfo(colattr?.MapType ?? p.PropertyType); if (setMethod == null || (tp == null && p.PropertyType.IsValueType)) // 属性没有 set自动忽略 @@ -1200,7 +1200,7 @@ namespace FreeSql.Internal this.Value = value; this.DataIndex = dataIndex; } - public static ConstructorInfo Constructor = typeof(RowInfo).GetConstructor(new[] { typeof(object), typeof(int) }); + public static ConstructorInfo Constructor = typeof(RowInfo). GetConstructor(new[] { typeof(object), typeof(int) }); public static PropertyInfo PropertyValue = typeof(RowInfo).GetProperty("Value"); public static PropertyInfo PropertyDataIndex = typeof(RowInfo).GetProperty("DataIndex"); } @@ -1342,14 +1342,15 @@ namespace FreeSql.Internal var readpkvalExp = Expression.Variable(typeof(object), "isnull3val"); var indexesLengthExp = Expression.Variable(typeof(int), "indexesLength"); var blockExp = new List(); - var ctor = type.GetConstructor(new Type[0]) ?? type.GetConstructors().First(); - var ctorParms = ctor.GetParameters(); - if (ctorParms.Length > 0) + var newExp = type.InternalNewExpression(); + if (false && newExp.Arguments.Count > 0) { + #region 按构造参数读取数据,此功能暂时关闭 + /* blockExp.AddRange(new Expression[] { - Expression.Assign(readpknullExp, Expression.Constant(false)) - }); - foreach (var ctorParm in ctorParms) + Expression.Assign(readpknullExp, Expression.Constant(false)) + }); + foreach (var ctorParm in newExp.Constructor.GetParameters()) { if (typetb.ColumnsByCsIgnore.ContainsKey(ctorParm.Name)) continue; var readType = typetb.ColumnsByCs.TryGetValue(ctorParm.Name, out var trycol) ? trycol.Attribute.MapType : ctorParm.ParameterType; @@ -1419,33 +1420,35 @@ namespace FreeSql.Internal ); blockExp.AddRange(new Expression[] { - Expression.Assign(tryidxExp, dataIndexExp), - readVal, - Expression.Assign(readExp, readExpAssign), - Expression.IfThen(Expression.GreaterThan(readExpDataIndex, dataIndexExp), - Expression.Assign(dataIndexExp, readExpDataIndex) - ), - Expression.Block(ispkExp) - }); + Expression.Assign(tryidxExp, dataIndexExp), + readVal, + Expression.Assign(readExp, readExpAssign), + Expression.IfThen(Expression.GreaterThan(readExpDataIndex, dataIndexExp), + Expression.Assign(dataIndexExp, readExpDataIndex) + ), + Expression.Block(ispkExp) + }); } blockExp.Add( Expression.IfThen( Expression.IsFalse(readpknullExp), - Expression.Assign(retExp, Expression.New(ctor, readExpValueParms)) + Expression.Assign(retExp, Expression.New(newExp.Constructor, readExpValueParms)) ) ); + */ + #endregion } else { blockExp.AddRange(new Expression[] { - Expression.Assign(retExp, Expression.New(ctor)), - Expression.Assign(indexesLengthExp, Expression.Constant(0)), - Expression.IfThen( - Expression.NotEqual(indexesExp, Expression.Constant(null)), - Expression.Assign(indexesLengthExp, Expression.ArrayLength(indexesExp)) - ), - Expression.Assign(readpknullExp, Expression.Constant(false)) - }); + Expression.Assign(retExp, newExp), + Expression.Assign(indexesLengthExp, Expression.Constant(0)), + Expression.IfThen( + Expression.NotEqual(indexesExp, Expression.Constant(null)), + Expression.Assign(indexesLengthExp, Expression.ArrayLength(indexesExp)) + ), + Expression.Assign(readpknullExp, Expression.Constant(false)) + }); var props = type.GetPropertiesDictIgnoreCase().Values; var propIndex = 0; @@ -1459,7 +1462,7 @@ namespace FreeSql.Internal var readType = typetb.ColumnsByCs.TryGetValue(prop.Name, out var trycol) ? trycol.Attribute.MapType : prop.PropertyType; var ispkExp = new List(); - var propGetSetMethod = prop.GetSetMethod(); + var propGetSetMethod = prop.GetSetMethod(true); Expression readVal = Expression.Assign(readpkvalExp, Expression.Call(rowExp, MethodDataReaderGetValue, tryidxExp)); Expression readExpAssign = null; //加速缓存 if (readType.IsArray) readExpAssign = Expression.New(RowInfo.Constructor, @@ -1524,30 +1527,30 @@ namespace FreeSql.Internal ) ); blockExp.AddRange(new Expression[] { - //以下注释部分为【严格读取】,会损失一点性能,使用 select * from xxx 与属性映射赋值 - Expression.IfThenElse( - Expression.LessThan(Expression.Constant(propIndex), indexesLengthExp), - Expression.Assign(tryidxExp, Expression.ArrayAccess(indexesExp, Expression.Constant(propIndex))), - Expression.Assign(tryidxExp, dataIndexExp) - ), - Expression.IfThen( - Expression.GreaterThanOrEqual(tryidxExp, Expression.Constant(0)), - Expression.Block( - readVal, - Expression.Assign(readExp, readExpAssign), - Expression.IfThen(Expression.GreaterThan(readExpDataIndex, dataIndexExp), - Expression.Assign(dataIndexExp, readExpDataIndex)), - Expression.Block(ispkExp) + //以下注释部分为【严格读取】,会损失一点性能,使用 select * from xxx 与属性映射赋值 + Expression.IfThenElse( + Expression.LessThan(Expression.Constant(propIndex), indexesLengthExp), + Expression.Assign(tryidxExp, Expression.ArrayAccess(indexesExp, Expression.Constant(propIndex))), + Expression.Assign(tryidxExp, dataIndexExp) + ), + Expression.IfThen( + Expression.GreaterThanOrEqual(tryidxExp, Expression.Constant(0)), + Expression.Block( + readVal, + Expression.Assign(readExp, readExpAssign), + Expression.IfThen(Expression.GreaterThan(readExpDataIndex, dataIndexExp), + Expression.Assign(dataIndexExp, readExpDataIndex)), + Expression.Block(ispkExp) + ) ) - ) - }); + }); ++propIndex; } } blockExp.AddRange(new Expression[] { - Expression.Return(returnTarget, Expression.New(RowInfo.Constructor, retExp, dataIndexExp)), - Expression.Label(returnTarget, Expression.Default(typeof(RowInfo))) - }); + Expression.Return(returnTarget, Expression.New(RowInfo.Constructor, retExp, dataIndexExp)), + Expression.Label(returnTarget, Expression.Default(typeof(RowInfo))) + }); return Expression.Lambda>( Expression.Block(new[] { retExp, readExp, tryidxExp, readpknullExp, readpkvalExp, readExpsIndex, indexesLengthExp }.Concat(readExpValueParms), blockExp), new[] { typeExp, indexesExp, rowExp, dataIndexExp, commonUtilExp }).Compile(); }); @@ -1616,7 +1619,7 @@ namespace FreeSql.Internal static MethodInfo MethodBigIntegerParse = typeof(Utils).GetMethod("ToBigInteger", BindingFlags.NonPublic | BindingFlags.Static, null, new[] { typeof(string) }, null); static PropertyInfo PropertyDateTimeOffsetDateTime = typeof(DateTimeOffset).GetProperty("DateTime", BindingFlags.Instance | BindingFlags.Public); static PropertyInfo PropertyDateTimeTicks = typeof(DateTime).GetProperty("Ticks", BindingFlags.Instance | BindingFlags.Public); - static ConstructorInfo CtorDateTimeOffsetArgsTicks = typeof(DateTimeOffset).GetConstructor(new[] { typeof(long), typeof(TimeSpan) }); + static ConstructorInfo CtorDateTimeOffsetArgsTicks = typeof(DateTimeOffset). GetConstructor(new[] { typeof(long), typeof(TimeSpan) }); public static ConcurrentBag> GetDataReaderValueBlockExpressionSwitchTypeFullName = new ConcurrentBag>(); public static ConcurrentBag> GetDataReaderValueBlockExpressionObjectToStringIfThenElse = new ConcurrentBag>();