@@ -46,7 +46,7 @@ internal static void CopyData(Select0Provider<TSelect, T1> from, object to, Read
4646 //toType.GetField("_tables", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new List<SelectTableInfo>(from._tables.ToArray()));
4747 var _multiTables = toType . GetField ( "_tables" , BindingFlags . Instance | BindingFlags . NonPublic ) . GetValue ( to ) as List < SelectTableInfo > ;
4848 _multiTables [ 0 ] = from . _tables [ 0 ] ;
49- for ( var a = 1 ; a < lambParms . Count ; a ++ ) {
49+ for ( var a = 1 ; a < lambParms . Count ; a ++ ) {
5050 var tb = from . _tables . Where ( b => b . Alias == lambParms [ a ] . Name && b . Table . Type == lambParms [ a ] . Type ) . FirstOrDefault ( ) ;
5151 if ( tb != null ) _multiTables [ a ] = tb ;
5252 else {
@@ -108,7 +108,7 @@ public TSelect Caching(int seconds, string key = null) {
108108 }
109109 public long Count ( ) => this . ToList < int > ( "count(1)" ) . FirstOrDefault ( ) ;
110110 async public Task < long > CountAsync ( ) => ( await this . ToListAsync < int > ( "count(1)" ) ) . FirstOrDefault ( ) ;
111-
111+
112112 public TSelect Count ( out long count ) {
113113 count = this . Count ( ) ;
114114 return this as TSelect ;
@@ -235,7 +235,7 @@ public List<TTuple> ToList<TTuple>(string field) {
235235 Type type = typeof ( TTuple ) ;
236236 _orm . Ado . ExecuteReader ( _connection , _transaction , dr => {
237237 var read = Utils . ExecuteArrayRowReadClassOrTuple ( type , null , dr , 0 , _commonUtils ) ;
238- ret . Add ( ( TTuple ) read . Value ) ;
238+ ret . Add ( ( TTuple ) read . Value ) ;
239239 } , CommandType . Text , sql , _params . ToArray ( ) ) ;
240240 _orm . Aop . ToList ? . Invoke ( this , new AopToListEventArgs ( ret ) ) ;
241241 _trackToList ? . Invoke ( ret ) ;
@@ -251,7 +251,7 @@ public Task<List<TTuple>> ToListAsync<TTuple>(string field) {
251251 Type type = typeof ( TTuple ) ;
252252 await _orm . Ado . ExecuteReaderAsync ( _connection , _transaction , dr => {
253253 var read = Utils . ExecuteArrayRowReadClassOrTuple ( type , null , dr , 0 , _commonUtils ) ;
254- ret . Add ( ( TTuple ) read . Value ) ;
254+ ret . Add ( ( TTuple ) read . Value ) ;
255255 return Task . CompletedTask ;
256256 } , CommandType . Text , sql , _params . ToArray ( ) ) ;
257257 _orm . Aop . ToList ? . Invoke ( this , new AopToListEventArgs ( ret ) ) ;
@@ -311,7 +311,7 @@ protected List<TReturn> ToListMapReader<TReturn>((ReadAnonymousTypeInfo map, str
311311 Type type = typeof ( TReturn ) ;
312312 _orm . Ado . ExecuteReader ( _connection , _transaction , dr => {
313313 var index = - 1 ;
314- ret . Add ( ( TReturn ) _commonExpression . ReadAnonymous ( af . map , dr , ref index , false ) ) ;
314+ ret . Add ( ( TReturn ) _commonExpression . ReadAnonymous ( af . map , dr , ref index , false ) ) ;
315315 } , CommandType . Text , sql , _params . ToArray ( ) ) ;
316316 _orm . Aop . ToList ? . Invoke ( this , new AopToListEventArgs ( ret ) ) ;
317317 _trackToList ? . Invoke ( ret ) ;
@@ -327,7 +327,7 @@ async protected Task<List<TReturn>> ToListMapReaderAsync<TReturn>((ReadAnonymous
327327 Type type = typeof ( TReturn ) ;
328328 await _orm . Ado . ExecuteReaderAsync ( _connection , _transaction , dr => {
329329 var index = - 1 ;
330- ret . Add ( ( TReturn ) _commonExpression . ReadAnonymous ( af . map , dr , ref index , false ) ) ;
330+ ret . Add ( ( TReturn ) _commonExpression . ReadAnonymous ( af . map , dr , ref index , false ) ) ;
331331 return Task . CompletedTask ;
332332 } , CommandType . Text , sql , _params . ToArray ( ) ) ;
333333 _orm . Aop . ToList ? . Invoke ( this , new AopToListEventArgs ( ret ) ) ;
@@ -350,6 +350,126 @@ public class GetAllFieldExpressionTreeInfo {
350350 public Func < IFreeSql , DbDataReader , T1 > Read { get ; set ; }
351351 }
352352 protected GetAllFieldExpressionTreeInfo GetAllFieldExpressionTree ( ) {
353+ return _dicGetAllFieldExpressionTree . GetOrAdd ( string . Join ( "+" , _tables . Select ( a => $ "{ _orm . Ado . DataType } -{ a . Table . DbName } -{ a . Alias } -{ a . Type } ") ) , s => {
354+ var type = _tables . First ( ) . Table . TypeLazy ?? _tables . First ( ) . Table . Type ;
355+ var ormExp = Expression . Parameter ( typeof ( IFreeSql ) , "orm" ) ;
356+ var rowExp = Expression . Parameter ( typeof ( DbDataReader ) , "row" ) ;
357+ var returnTarget = Expression . Label ( type ) ;
358+ var retExp = Expression . Variable ( type , "ret" ) ;
359+ var dataIndexExp = Expression . Variable ( typeof ( int ) , "dataIndex" ) ;
360+ var readExp = Expression . Variable ( typeof ( Utils . RowInfo ) , "read" ) ;
361+ var readExpValue = Expression . MakeMemberAccess ( readExp , Utils . RowInfo . PropertyValue ) ;
362+ var readExpDataIndex = Expression . MakeMemberAccess ( readExp , Utils . RowInfo . PropertyDataIndex ) ;
363+ var blockExp = new List < Expression > ( ) ;
364+ var ctor = type . GetConstructor ( new Type [ 0 ] ) ?? type . GetConstructors ( ) . First ( ) ;
365+ blockExp . AddRange ( new Expression [ ] {
366+ Expression . Assign ( retExp , Expression . New ( ctor , ctor . GetParameters ( ) . Select ( a => Expression . Default ( a . ParameterType ) ) ) ) ,
367+ Expression . Assign ( dataIndexExp , Expression . Constant ( 0 ) )
368+ } ) ;
369+ //typeof(Topic).GetMethod("get_Type").IsVirtual
370+
371+ var field = new StringBuilder ( ) ;
372+ var dicfield = new Dictionary < string , bool > ( ) ;
373+ var tb = _tables . First ( ) ;
374+ var index = 0 ;
375+
376+ var tbiindex = 0 ;
377+ foreach ( var tbi in _tables . ToArray ( ) . OrderBy ( a => a . Alias ) ) {
378+ if ( tbiindex > 0 && tbi . Type == SelectTableInfoType . From ) continue ;
379+ if ( tbiindex > 0 && tbi . Alias . StartsWith ( $ "{ tb . Alias } __") == false ) continue ;
380+
381+ var typei = tbi . Table . TypeLazy ?? tbi . Table . Type ;
382+ if ( tbiindex == 0 )
383+ blockExp . AddRange ( new Expression [ ] {
384+ Expression . Assign ( readExp , Expression . Call ( Utils . MethodExecuteArrayRowReadClassOrTuple , new Expression [ ] { Expression . Constant ( typei ) , Expression . Constant ( null , typeof ( int [ ] ) ) , rowExp , dataIndexExp , Expression . Constant ( _commonUtils ) } ) ) ,
385+ Expression . IfThen (
386+ Expression . GreaterThan ( readExpDataIndex , dataIndexExp ) ,
387+ Expression . Assign ( dataIndexExp , readExpDataIndex )
388+ ) ,
389+ Expression . IfThen (
390+ Expression . NotEqual ( readExpValue , Expression . Constant ( null ) ) ,
391+ Expression . Assign ( retExp , Expression . Convert ( readExpValue , typei ) )
392+ )
393+ } ) ;
394+ else {
395+ Expression curExpIfNotNull = Expression . IsTrue ( Expression . Constant ( true ) ) ;
396+ Expression curExp = retExp ;
397+ var curTb = tb ;
398+ var parentNameSplits = tbi . Alias . Split ( new [ ] { "__" } , StringSplitOptions . None ) ;
399+ var iscontinue = false ;
400+ for ( var k = 1 ; k < parentNameSplits . Length ; k ++ ) {
401+ var curPropName = parentNameSplits [ k ] ;
402+ if ( curTb . Table . Properties . TryGetValue ( parentNameSplits [ k ] , out var tryprop ) == false ) {
403+ k ++ ;
404+ curPropName = $ "{ curPropName } __{ parentNameSplits [ k ] } ";
405+ if ( curTb . Table . Properties . TryGetValue ( parentNameSplits [ k ] , out tryprop ) == false ) {
406+ iscontinue = true ;
407+ break ;
408+ }
409+ }
410+ curExp = Expression . MakeMemberAccess ( curExp , tryprop ) ;
411+ if ( k + 1 < parentNameSplits . Length )
412+ curExpIfNotNull = Expression . AndAlso ( curExpIfNotNull , Expression . NotEqual ( curExp , Expression . Default ( tryprop . PropertyType ) ) ) ;
413+ curTb = _tables . Where ( a => a . Alias == $ "{ curTb . Alias } __{ curPropName } " && a . Table . Type == tryprop . PropertyType ) . FirstOrDefault ( ) ;
414+ if ( curTb == null ) {
415+ iscontinue = true ;
416+ break ;
417+ }
418+ }
419+ if ( iscontinue ) continue ;
420+
421+ blockExp . Add (
422+ Expression . IfThen (
423+ curExpIfNotNull ,
424+ Expression . Block ( new Expression [ ] {
425+ Expression . Assign ( readExp , Expression . Call ( Utils . MethodExecuteArrayRowReadClassOrTuple , new Expression [ ] { Expression . Constant ( typei ) , Expression . Constant ( null , typeof ( int [ ] ) ) , rowExp , dataIndexExp , Expression . Constant ( _commonUtils ) } ) ) ,
426+ Expression . IfThen (
427+ Expression . GreaterThan ( readExpDataIndex , dataIndexExp ) ,
428+ Expression . Assign ( dataIndexExp , readExpDataIndex )
429+ ) ,
430+ Expression . IfThen (
431+ Expression . NotEqual ( readExpValue , Expression . Constant ( null ) ) ,
432+ Expression . Assign ( curExp , Expression . Convert ( readExpValue , typei ) )
433+ )
434+ } )
435+ )
436+ ) ;
437+ }
438+ if ( tbi . Table . TypeLazy != null )
439+ blockExp . Add (
440+ Expression . IfThen (
441+ Expression . NotEqual ( readExpValue , Expression . Constant ( null ) ) ,
442+ Expression . Call ( retExp , tbi . Table . TypeLazySetOrm , ormExp )
443+ )
444+ ) ; //将 orm 传递给 lazy
445+
446+ var colidx = 0 ;
447+ foreach ( var col in tbi . Table . Columns . Values ) {
448+ if ( index > 0 ) {
449+ field . Append ( ", " ) ;
450+ if ( tbiindex > 0 && colidx == 0 ) field . Append ( "\r \n " ) ;
451+ }
452+ var quoteName = _commonUtils . QuoteSqlName ( col . Attribute . Name ) ;
453+ field . Append ( _commonUtils . QuoteReadColumn ( col . CsType , $ "{ tbi . Alias } .{ quoteName } ") ) ;
454+ ++ index ;
455+ if ( dicfield . ContainsKey ( quoteName ) ) field . Append ( " as" ) . Append ( index ) ;
456+ else dicfield . Add ( quoteName , true ) ;
457+ ++ colidx ;
458+ }
459+ tbiindex ++ ;
460+ }
461+
462+ blockExp . AddRange ( new Expression [ ] {
463+ Expression . Return ( returnTarget , retExp ) ,
464+ Expression . Label ( returnTarget , Expression . Default ( type ) )
465+ } ) ;
466+ return new GetAllFieldExpressionTreeInfo {
467+ Field = field . ToString ( ) ,
468+ Read = Expression . Lambda < Func < IFreeSql , DbDataReader , T1 > > ( Expression . Block ( new [ ] { retExp , dataIndexExp , readExp } , blockExp ) , new [ ] { ormExp , rowExp } ) . Compile ( )
469+ } ;
470+ } ) ;
471+ }
472+ protected GetAllFieldExpressionTreeInfo GetAllFieldExpressionTreeLevel2 ( ) {
353473 return _dicGetAllFieldExpressionTree . GetOrAdd ( string . Join ( "+" , _tables . Select ( a => $ "{ _orm . Ado . DataType } -{ a . Table . DbName } -{ a . Alias } -{ a . Type } ") ) , s => {
354474 var tb1 = _tables . First ( ) . Table ;
355475 var type = tb1 . TypeLazy ?? tb1 . Type ;
@@ -387,12 +507,14 @@ protected GetAllFieldExpressionTreeInfo GetAllFieldExpressionTree() {
387507 if ( dicfield . ContainsKey ( quoteName ) ) field . Append ( " as" ) . Append ( index ) ;
388508 else dicfield . Add ( quoteName , true ) ;
389509 } else {
390- var tb2 = _tables . Where ( ( a , b ) => b > 0 &&
391- ( a . Type == SelectTableInfoType . InnerJoin || a . Type == SelectTableInfoType . LeftJoin || a . Type == SelectTableInfoType . RightJoin ) &&
510+ var tb2 = _tables . Where ( ( a , b ) => b > 0 &&
511+ ( a . Type == SelectTableInfoType . InnerJoin || a . Type == SelectTableInfoType . LeftJoin || a . Type == SelectTableInfoType . RightJoin ) &&
392512 string . IsNullOrEmpty ( a . On ) == false &&
393- a . Alias . Contains ( prop . Name ) ) . FirstOrDefault ( ) ; //判断 b > 0 防止 parent 递归关系
513+ a . Alias . StartsWith ( $ "{ tb . Alias } __") && //开头结尾完全匹配
514+ a . Alias . EndsWith ( $ "__{ prop . Name } ") //不清楚会不会有其他情况 求大佬优化
515+ ) . FirstOrDefault ( ) ; //判断 b > 0 防止 parent 递归关系
394516 if ( tb2 == null && props . Where ( pw => pw . Value . PropertyType == prop . PropertyType ) . Count ( ) == 1 )
395- tb2 = _tables . Where ( ( a , b ) => b > 0 &&
517+ tb2 = _tables . Where ( ( a , b ) => b > 0 &&
396518 ( a . Type == SelectTableInfoType . InnerJoin || a . Type == SelectTableInfoType . LeftJoin || a . Type == SelectTableInfoType . RightJoin ) &&
397519 string . IsNullOrEmpty ( a . On ) == false &&
398520 a . Table . Type == prop . PropertyType ) . FirstOrDefault ( ) ;
@@ -501,7 +623,8 @@ protected GetAllFieldExpressionTreeInfo GetAllFieldExpressionTree() {
501623 else dicfield . Add ( quoteName , true ) ;
502624 child . Childs . Add ( new ReadAnonymousTypeInfo {
503625 Property = tb2 . Table . Type . GetProperty ( col2 . CsName , BindingFlags . Public | BindingFlags . IgnoreCase | BindingFlags . Instance ) ,
504- CsName = col2 . CsName } ) ;
626+ CsName = col2 . CsName
627+ } ) ;
505628 }
506629 }
507630 map . Childs . Add ( child ) ;
0 commit comments