private void AddPropertiesToFetchTree <T>( ref int aliasCounter, ref int numberCollectionFetches, Stack <string> entityNames, FetchNode currentNode, FetchNode rootNode) { while (entityNames.Count > 0) { var propName = entityNames.Pop(); // don't add duplicates if (!currentNode.Children.ContainsKey(propName)) { var column = this.configuration.GetMap( currentNode == rootNode ? typeof(T) : (currentNode.Column.Relationship == RelationshipType.OneToMany ? currentNode.Column.Type.GetGenericArguments().First() : currentNode.Column.Type)).Columns[propName]; if (column.IsIgnored) { //TODO we should probably warn at this point continue; } if (column.Relationship == RelationshipType.OneToMany) { ++numberCollectionFetches; } // add to tree currentNode = currentNode.AddChild(column, true); } else { currentNode = currentNode.Children[propName]; } } }
protected override void VisitMember(Context context, MemberExpression node) { FetchNode fetchNode = null; this.VisitMember(node, x => fetchNode = x); if (!context.Parent.IsExpressionOf(ExpressionType.MemberAccess)) { // we're at the end var map = ReferenceEquals(this.rootNode, fetchNode) ? this.configuration.GetMap <TBase>() : (fetchNode.Column.Relationship == RelationshipType.ManyToOne ? fetchNode.Column.ParentMap : (fetchNode.Column.Relationship == RelationshipType.OneToOne ? fetchNode.Column.OppositeColumn.Map : throw new NotSupportedException("Include/Exclude clauses can only use Many to One and One to One relationships"))); if (map.Columns.TryGetValue(node.Member.Name, out var column)) { if (column.Relationship == RelationshipType.None) { // add to the included columns for this node if (fetchNode.IncludedColumns == null) { fetchNode.IncludedColumns = new List <IColumn>(); } fetchNode.IncludedColumns.Add(column); } else if (column.Relationship == RelationshipType.ManyToOne || column.Relationship == RelationshipType.OneToOne) { // add a new fetch node for this column if (!fetchNode.Children.ContainsKey(column.Name)) { fetchNode.AddChild(column, true); } } else { throw new NotSupportedException($"Unable to project OneToMany relationships - {column.Name}"); } } else { throw new InvalidOperationException($"Unable to find column {node.Member.Name} in projection"); } } else { // we're not at the end of the member access var declaringType = node.Member.DeclaringType; if (!this.configuration.HasMap(declaringType)) { throw new InvalidOperationException($"Type not mapped: {declaringType.FullName}"); } var map = this.configuration.GetMap(declaringType); if (!fetchNode.Children.ContainsKey(node.Member.Name)) { context.State(fetchNode.AddChild(map.Columns[node.Member.Name], true)); } else { context.State(fetchNode.Children[node.Member.Name]); } } }