@@ -43,13 +43,13 @@ protected override Expression VisitTypeIs(TypeBinaryExpression tb)
4343
4444 // Structure
4545 var memberType = expression . GetMemberType ( ) ;
46- if ( memberType == MemberType . Structure
47- && typeof ( Structure ) . IsAssignableFrom ( operandType ) )
46+ if ( memberType == MemberType . Structure
47+ && typeof ( Structure ) . IsAssignableFrom ( operandType ) )
4848 return Expression . Constant ( false ) ;
4949
5050 // Entity
51- if ( memberType == MemberType . Entity
52- && typeof ( IEntity ) . IsAssignableFrom ( operandType ) ) {
51+ if ( memberType == MemberType . Entity
52+ && typeof ( IEntity ) . IsAssignableFrom ( operandType ) ) {
5353 TypeInfo type = context . Model . Types [ operandType ] ;
5454 IEnumerable < int > typeIds = type . GetDescendants ( true )
5555 . Union ( type . GetImplementors ( true ) )
@@ -73,10 +73,12 @@ protected override Expression VisitTypeIs(TypeBinaryExpression tb)
7373
7474 protected override Expression Visit ( Expression e )
7575 {
76- if ( e == null )
76+ if ( e == null )
7777 return null ;
7878 if ( e . IsProjection ( ) )
7979 return e ;
80+ if ( state . NonVisitableExpressions . Contains ( e ) )
81+ return e ;
8082 if ( context . Evaluator . CanBeEvaluated ( e ) ) {
8183 if ( typeof ( IQueryable ) . IsAssignableFrom ( e . Type ) )
8284 return base . Visit ( ExpressionEvaluator . Evaluate ( e ) ) ;
@@ -231,6 +233,11 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression)
231233 left = Visit ( Expression . Convert ( rightNoCasts , typeToCast ) ) ;
232234 right = Visit ( Expression . Convert ( binaryExpression . Left , typeToCast ) ) ;
233235 }
236+ else if ( state . NonVisitableExpressions . Contains ( leftNoCasts )
237+ || state . NonVisitableExpressions . Contains ( rightNoCasts ) ) {
238+ left = binaryExpression . Left ;
239+ right = binaryExpression . Right ;
240+ }
234241 else {
235242 left = Visit ( binaryExpression . Left ) ;
236243 right = Visit ( binaryExpression . Right ) ;
@@ -1045,7 +1052,7 @@ private IList<Expression> GetStructureFields(
10451052
10461053 switch ( fieldExpression . GetMemberType ( ) ) {
10471054 case MemberType . Entity :
1048- IEnumerable < Type > keyFieldTypes = context
1055+ var keyFieldTypes = context
10491056 . Model
10501057 . Types [ fieldExpression . Type ]
10511058 . Key
@@ -1066,39 +1073,48 @@ private IList<Expression> GetStructureFields(
10661073 return result ;
10671074 }
10681075
1069- private static IList < Expression > GetEntityFields ( Expression expression , IEnumerable < Type > keyFieldTypes )
1076+ private IList < Expression > GetEntityFields ( Expression expression , IReadOnlyList < Type > keyFieldTypes )
10701077 {
10711078 expression = expression . StripCasts ( ) ;
1072- if ( expression is IEntityExpression )
1073- return GetKeyFields ( ( ( IEntityExpression ) expression ) . Key , null ) ;
1074-
1075-
1076- Expression keyExpression ;
1077-
1078- if ( expression . IsNull ( ) )
1079- keyExpression = Expression . Constant ( null , KeyType ) ;
1080- else if ( IsConditionalOrWellknown ( expression ) )
1079+ if ( expression is IEntityExpression iEntityExpression ) {
1080+ return GetKeyFields ( iEntityExpression . Key , null ) ;
1081+ }
1082+ if ( expression . IsNull ( ) ) {
1083+ return GetKeyFields ( Expression . Constant ( null , KeyType ) , keyFieldTypes ) ;
1084+ }
1085+ if ( IsConditionalOrWellknown ( expression ) ) {
10811086 return keyFieldTypes
10821087 . Select ( ( type , index ) => GetConditionalKeyField ( expression , type , index ) )
1083- . ToList ( ) ;
1084- else
1085- {
1086- ConstantExpression nullEntityExpression = Expression . Constant ( null , expression . Type ) ;
1087- BinaryExpression isNullExpression = Expression . Equal ( expression , nullEntityExpression ) ;
1088- if ( ! typeof ( IEntity ) . IsAssignableFrom ( expression . Type ) )
1089- expression = Expression . Convert ( expression , typeof ( IEntity ) ) ;
1090- keyExpression = Expression . Condition (
1088+ . ToList ( keyFieldTypes . Count ) ;
1089+ }
1090+
1091+ var nullEntityExpression = Expression . Constant ( null , expression . Type ) ;
1092+ var isNullExpression = Expression . Equal ( expression , nullEntityExpression ) ;
1093+ if ( ! typeof ( IEntity ) . IsAssignableFrom ( expression . Type ) )
1094+ expression = Expression . Convert ( expression , typeof ( IEntity ) ) ;
1095+
1096+ var resultList = new List < Expression > ( keyFieldTypes . Count ) ;
1097+ for ( int i = 0 , count = keyFieldTypes . Count ; i < count ; i ++ ) {
1098+ var keyFieldType = keyFieldTypes [ i ] ;
1099+ var baseType = keyFieldType . StripNullable ( ) ;
1100+ var fieldType = ( baseType . IsEnum ? Enum . GetUnderlyingType ( baseType ) : baseType ) . ToNullable ( ) ;
1101+ var keyTupleExpression = Expression . MakeMemberAccess (
1102+ Expression . MakeMemberAccess ( expression , WellKnownMembers . IEntityKey ) , WellKnownMembers . Key . Value ) ;
1103+ var tupleAccess = ( Expression ) keyTupleExpression . MakeTupleAccess ( fieldType , i ) ;
1104+
1105+ var entityNullCheck = Expression . Condition (
10911106 isNullExpression ,
1092- Expression . Constant ( null , KeyType ) ,
1093- Expression . MakeMemberAccess ( expression , WellKnownMembers . IEntityKey ) ) ;
1107+ Expression . Constant ( null , keyFieldType . ToNullable ( ) ) ,
1108+ tupleAccess ) ;
1109+ resultList . Add ( entityNullCheck ) ;
1110+ _ = state . NonVisitableExpressions . Add ( entityNullCheck ) ;
10941111 }
1095- return GetKeyFields ( keyExpression , keyFieldTypes ) ;
1112+ return resultList ;
10961113 }
10971114
10981115 private static Expression GetConditionalKeyField ( Expression expression , Type keyFieldType , int index )
10991116 {
1100- var ce = expression as ConditionalExpression ;
1101- if ( ce != null )
1117+ if ( expression is ConditionalExpression ce )
11021118 return Expression . Condition (
11031119 ce . Test ,
11041120 GetConditionalKeyField ( ce . IfTrue , keyFieldType , index ) ,
@@ -1109,16 +1125,16 @@ private static Expression GetConditionalKeyField(Expression expression, Type key
11091125 return ee . Key . KeyFields [ index ] . LiftToNullable ( ) ;
11101126 }
11111127
1112- private static IList < Expression > GetKeyFields ( Expression expression , IEnumerable < Type > keyFieldTypes )
1128+ private IList < Expression > GetKeyFields ( Expression expression , IEnumerable < Type > keyFieldTypes )
11131129 {
11141130 expression = expression . StripCasts ( ) ;
11151131
1116- var keyExpression = expression as KeyExpression ;
1117- if ( keyExpression != null )
1132+ if ( expression is KeyExpression keyExpression ) {
11181133 return keyExpression
11191134 . KeyFields
1120- . Select ( fieldExpression => ( Expression ) fieldExpression )
1121- . ToList ( ) ;
1135+ . Cast < Expression > ( )
1136+ . ToList ( keyExpression . KeyFields . Count ) ;
1137+ }
11221138
11231139 if ( expression . IsNull ( ) )
11241140 return keyFieldTypes
@@ -1137,7 +1153,9 @@ private static IList<Expression> GetKeyFields(Expression expression, IEnumerable
11371153 var tupleAccess = ( Expression ) keyTupleExpression . MakeTupleAccess ( fieldType , index ) ;
11381154 if ( fieldType != resultType )
11391155 tupleAccess = Expression . Convert ( tupleAccess , resultType ) ;
1140- return ( Expression ) Expression . Condition ( isNullExpression , Expression . Constant ( null , resultType ) , tupleAccess ) ;
1156+ var checkForNulls = ( Expression ) Expression . Condition ( isNullExpression , Expression . Constant ( null , resultType ) , tupleAccess ) ;
1157+ _ = state . NonVisitableExpressions . Add ( checkForNulls ) ;
1158+ return checkForNulls ;
11411159 } )
11421160 . ToList ( ) ;
11431161 }
0 commit comments