public static EntityExpression Create(EntityFieldExpression entityFieldExpression, int offset) { var typeInfo = entityFieldExpression.PersistentType; var fields = new List <PersistentFieldExpression>(); var keyExpression = KeyExpression.Create(typeInfo, offset); fields.Add(keyExpression); foreach (var nestedField in typeInfo.Fields) { fields.Add(BuildNestedFieldExpression(nestedField, offset)); } var result = new EntityExpression(typeInfo, keyExpression, null, entityFieldExpression.DefaultIfEmpty) { Fields = fields }; if (entityFieldExpression.OuterParameter == null) { return(result); } return((EntityExpression)result.BindParameter(entityFieldExpression.OuterParameter, new Dictionary <Expression, Expression>())); }
public Expression Remap(int offset, Dictionary <Expression, Expression> processedExpressions) { if (!CanRemap) { return(this); } Expression value; if (processedExpressions.TryGetValue(this, out value)) { return(value); } var keyExpression = (KeyExpression)Key.Remap(offset, processedExpressions); var result = new EntityExpression(PersistentType, keyExpression, OuterParameter, DefaultIfEmpty); processedExpressions.Add(this, result); result.IsNullable = IsNullable; result.Fields = Fields .Select(f => f.Remap(offset, processedExpressions)) .Cast <PersistentFieldExpression>() .ToList(); return(result); }
public ItemProjectorExpression EnsureEntityIsJoined() { var dataSource = DataSource; var newItem = new ExtendedExpressionReplacer(e => { if (e is EntityExpression) { var entityExpression = (EntityExpression)e; var typeInfo = entityExpression.PersistentType; if (typeInfo.Fields.All(fieldInfo => entityExpression.Fields.Any(entityField => entityField.Name == fieldInfo.Name))) { return(entityExpression); } var joinedIndex = typeInfo.Indexes.PrimaryIndex; var joinedRs = joinedIndex.GetQuery().Alias(Context.GetNextAlias()); var keySegment = entityExpression.Key.Mapping; var keyPairs = keySegment.GetItems() .Select((leftIndex, rightIndex) => new Pair <int>(leftIndex, rightIndex)) .ToArray(); var offset = dataSource.Header.Length; var dataSourceAsJoin = dataSource as JoinProvider; dataSource = entityExpression.IsNullable || (dataSourceAsJoin != null && dataSourceAsJoin.JoinType == JoinType.LeftOuter) ? dataSource.LeftJoin(joinedRs, keyPairs) : dataSource.Join(joinedRs, keyPairs); EntityExpression.Fill(entityExpression, offset); return(entityExpression); } if (e is EntityFieldExpression) { var entityFieldExpression = (EntityFieldExpression)e; if (entityFieldExpression.Entity != null) { return(entityFieldExpression.Entity); } var typeInfo = entityFieldExpression.PersistentType; var joinedIndex = typeInfo.Indexes.PrimaryIndex; var joinedRs = joinedIndex.GetQuery().Alias(Context.GetNextAlias()); var keySegment = entityFieldExpression.Mapping; var keyPairs = keySegment.GetItems() .Select((leftIndex, rightIndex) => new Pair <int>(leftIndex, rightIndex)) .ToArray(); var offset = dataSource.Header.Length; var dataSourceAsJoin = dataSource as JoinProvider; dataSource = entityFieldExpression.IsNullable || (dataSourceAsJoin != null && dataSourceAsJoin.JoinType == JoinType.LeftOuter) ? dataSource.LeftJoin(joinedRs, keyPairs) : dataSource.Join(joinedRs, keyPairs); entityFieldExpression.RegisterEntityExpression(offset); return(entityFieldExpression.Entity); } if (e is FieldExpression) { var fe = (FieldExpression)e; if (fe.ExtendedType == ExtendedExpressionType.Field) { return(fe.RemoveOwner()); } } return(null); }) .Replace(Item); return(new ItemProjectorExpression(newItem, dataSource, Context)); }
public void RegisterEntityExpression(int offset) { Entity = EntityExpression.Create(this, offset); Entity.IsNullable = IsNullable; }
public ItemProjectorExpression EnsureEntityIsJoined() { var dataSource = DataSource; var newItem = new ExtendedExpressionReplacer(e => { if (e is EntityExpression entityExpression) { var typeInfo = entityExpression.PersistentType; // Converted from LINQ to get rid of 2 closure allocations var all = true; foreach (var fieldInfo in typeInfo.Fields) { var isUsedInEntityExpression = false; foreach (var entityField in entityExpression.Fields) { if (string.Equals(entityField.Name, fieldInfo.Name, StringComparison.Ordinal)) { isUsedInEntityExpression = true; break; } } if (!isUsedInEntityExpression) { all = false; break; } } if (all) { return(entityExpression); } var joinedIndex = typeInfo.Indexes.PrimaryIndex; var joinedRs = joinedIndex.GetQuery().Alias(Context.GetNextAlias()); var keySegment = entityExpression.Key.Mapping; var keyPairs = new Pair <int> [keySegment.Length]; var rightIndex = 0; foreach (var leftIndex in keySegment.GetItems()) { keyPairs[rightIndex] = new Pair <int>(leftIndex, rightIndex); rightIndex++; } var offset = dataSource.Header.Length; dataSource = entityExpression.IsNullable || (dataSource is JoinProvider dataSourceAsJoin && dataSourceAsJoin.JoinType == JoinType.LeftOuter) ? dataSource.LeftJoin(joinedRs, keyPairs) : dataSource.Join(joinedRs, keyPairs); EntityExpression.Fill(entityExpression, offset); return(entityExpression); } if (e is EntityFieldExpression entityFieldExpression) { if (entityFieldExpression.Entity != null) { return(entityFieldExpression.Entity); } var typeInfo = entityFieldExpression.PersistentType; var joinedIndex = typeInfo.Indexes.PrimaryIndex; var joinedRs = joinedIndex.GetQuery().Alias(Context.GetNextAlias()); var keySegment = entityFieldExpression.Mapping; var keyPairs = new Pair <int> [keySegment.Length]; var rightIndex = 0; foreach (var leftIndex in keySegment.GetItems()) { keyPairs[rightIndex] = new Pair <int>(leftIndex, rightIndex); rightIndex++; } var offset = dataSource.Header.Length; dataSource = entityFieldExpression.IsNullable || (dataSource is JoinProvider dataSourceAsJoin && dataSourceAsJoin.JoinType == JoinType.LeftOuter) ? dataSource.LeftJoin(joinedRs, keyPairs) : dataSource.Join(joinedRs, keyPairs); entityFieldExpression.RegisterEntityExpression(offset); return(entityFieldExpression.Entity); } if (e is FieldExpression fe && fe.ExtendedType == ExtendedExpressionType.Field) { return(fe.RemoveOwner()); } return(null); }) .Replace(Item); return(new ItemProjectorExpression(newItem, dataSource, Context)); }