public void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree, string sourceAlias, bool userInnerJoin = false) { var join = tree.TreeBuilder.Dot( tree.TreeBuilder.Ident(sourceAlias), tree.TreeBuilder.Ident(resultOperator.RelationMember.Name)); string alias = queryModelVisitor.Model.GetNewName("_"); if (userInnerJoin) { tree.AddFromClause(tree.TreeBuilder.FetchJoin(join, tree.TreeBuilder.Alias(alias))); } else { tree.AddFromClause(tree.TreeBuilder.LeftFetchJoin(join, tree.TreeBuilder.Alias(alias))); } tree.AddDistinctRootOperator(); foreach (var innerFetch in resultOperator.InnerFetchRequests) { if (innerFetch is InnerFetchOneRequest || innerFetch is InnerFetchManyRequest) { Process(innerFetch, queryModelVisitor, tree, alias, true); } else { Process(innerFetch, queryModelVisitor, tree, alias); } } }
private IRelationEndPointDefinition GetEagerFetchRelationEndPointDefinition(FetchRequestBase fetchRequest, ClassDefinition classDefinition) { var propertyInfo = fetchRequest.RelationMember as PropertyInfo; if (propertyInfo == null) { var message = string.Format( "The member '{0}' is a '{1}', which cannot be fetched by this LINQ provider. Only properties can be fetched.", fetchRequest.RelationMember.Name, fetchRequest.RelationMember.MemberType); throw new NotSupportedException(message); } var propertyInfoAdapter = PropertyInfoAdapter.Create(propertyInfo); var endPoint = classDefinition.ResolveRelationEndPoint(propertyInfoAdapter) ?? classDefinition.GetAllDerivedClasses() .Select(cd => cd.ResolveRelationEndPoint(propertyInfoAdapter)) .FirstOrDefault(ep => ep != null); if (endPoint == null) { Assertion.IsNotNull(propertyInfo.DeclaringType); var message = string.Format( "The property '{0}.{1}' is not a relation end point. Fetching it is not supported by this LINQ provider.", propertyInfo.DeclaringType.FullName, propertyInfo.Name); throw new NotSupportedException(message); } return(endPoint); }
private void CheckFetchQueryModelBuilder( FetchQueryModelBuilder builder, FetchRequestBase expectedFetchRequest, QueryModel expectedQueryModel, int expectedResultOperatorPosition) { Assert.That(builder.FetchRequest, Is.SameAs(expectedFetchRequest)); Assert.That(builder.SourceItemQueryModel, Is.SameAs(expectedQueryModel)); Assert.That(builder.ResultOperatorPosition, Is.EqualTo(expectedResultOperatorPosition)); }
public void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree, string sourceAlias) { var memberPath = tree.TreeBuilder.Dot( tree.TreeBuilder.Ident(sourceAlias), tree.TreeBuilder.Ident(resultOperator.RelationMember.Name)); Process(resultOperator, queryModelVisitor, tree, memberPath, null); }
public void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree) { var querySource = QuerySourceLocator.FindQuerySource( queryModelVisitor.Model, resultOperator.RelationMember.DeclaringType); Process(resultOperator, queryModelVisitor, tree, querySource.ItemName); }
/// <summary> /// Initializes a new instance of the <see cref="FetchQueryModelBuilder"/> class. /// </summary> /// <param name="fetchRequest">The fetch request.</param> /// <param name="queryModel">The query model for which the <paramref name="fetchRequest"/> was originally defined.</param> /// <param name="resultOperatorPosition">The result operator position where the <paramref name="fetchRequest"/> was originally located. /// The <see cref="FetchQueryModelBuilder"/> will include all result operators prior to this position into the fetch <see cref="SourceItemQueryModel"/>, /// but it will not include any result operators occurring after (or at) that position.</param> public FetchQueryModelBuilder (FetchRequestBase fetchRequest, QueryModel queryModel, int resultOperatorPosition) { ArgumentUtility.CheckNotNull ("fetchRequest", fetchRequest); ArgumentUtility.CheckNotNull ("queryModel", queryModel); FetchRequest = fetchRequest; SourceItemQueryModel = queryModel; ResultOperatorPosition = resultOperatorPosition; }
/// <summary> /// Gets or adds an eager-fetch request to this <see cref="FetchRequestCollection"/>. /// </summary> /// <param name="fetchRequest">The <see cref="FetchRequestBase"/> to be added.</param> /// <returns> /// <paramref name="fetchRequest"/> or, if another <see cref="FetchRequestBase"/> for the same relation member already existed, /// the existing <see cref="FetchRequestBase"/>. /// </returns> public FetchRequestBase GetOrAddFetchRequest (FetchRequestBase fetchRequest) { ArgumentUtility.CheckNotNull ("fetchRequest", fetchRequest); FetchRequestBase existingFetchRequest; if (_fetchRequests.TryGetValue (fetchRequest.RelationMember, out existingFetchRequest)) return existingFetchRequest; else { _fetchRequests.Add (fetchRequest.RelationMember, fetchRequest); return fetchRequest; } }
private void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree, HqlDot memberPath, IType propType) { if (resultOperator is FetchOneRequest) { if (propType == null) { var metadata = queryModelVisitor.VisitorParameters.SessionFactory .GetClassMetadata(resultOperator.RelationMember.ReflectedType); propType = metadata?.GetPropertyType(resultOperator.RelationMember.Name); } if (propType != null && !propType.IsAssociationType) { tree.AddFromLastChildClause(tree.TreeBuilder.Fetch()); tree.AddFromLastChildClause(memberPath); ComponentType componentType = null; foreach (var innerFetch in resultOperator.InnerFetchRequests) { if (componentType == null) { componentType = propType as ComponentType; if (componentType == null) { throw new InvalidOperationException( $"Property {innerFetch.RelationMember.Name} cannot be fetched from a non component type property {resultOperator.RelationMember.Name}."); } } var subTypeIndex = componentType.GetPropertyIndex(innerFetch.RelationMember.Name); memberPath = tree.TreeBuilder.Dot( memberPath, tree.TreeBuilder.Ident(innerFetch.RelationMember.Name)); Process(innerFetch, queryModelVisitor, tree, memberPath, componentType.Subtypes[subTypeIndex]); } return; } } var alias = queryModelVisitor.Model.GetNewName("_"); tree.AddFromClause(tree.TreeBuilder.LeftFetchJoin(memberPath, tree.TreeBuilder.Alias(alias))); tree.AddDistinctRootOperator(); foreach (var innerFetch in resultOperator.InnerFetchRequests) { Process(innerFetch, queryModelVisitor, tree, alias); } }
public void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree, string sourceAlias) { var join = tree.TreeBuilder.Dot( tree.TreeBuilder.Ident(sourceAlias), tree.TreeBuilder.Ident(resultOperator.RelationMember.Name)); string alias = queryModelVisitor.Model.GetNewName("_"); tree.AddFromClause(tree.TreeBuilder.LeftFetchJoin(join, tree.TreeBuilder.Alias(alias))); tree.AddDistinctRootOperator(); foreach (var innerFetch in resultOperator.InnerFetchRequests) { Process(innerFetch, queryModelVisitor, tree, alias); } }
private void ProcessFetchRequest(FetchRequestBase fetchRequest, QueryModel queryModel) { var declaringType = fetchRequest.RelationMember.DeclaringType; // TODO: // INNER JOIN Vs LEFT JOIN (Perhaps use a FetchRequired for optimized INNER JOIN. // Look at Required flag on Entity. // AutoMapper can use entity prefix underscore to map related entities from fetch. // How to update the SELECT for the fetched entity = use a join test to see how it works. // Want something like below: const string sql = @"SELECT tc.[ContactID] as ContactID, tc.[ContactName] as ContactName ,tp.[PhoneId] AS TestPhones_PhoneId ,tp.[ContactId] AS TestPhones_ContactId ,tp.[Number] AS TestPhones_Number FROM TestContact tc INNER JOIN TestPhone tp ON tc.ContactId = tp.ContactId"; }
public void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree) { var querySource = QuerySourceLocator.FindQuerySource(queryModelVisitor.Model, resultOperator.RelationMember.DeclaringType); Process(resultOperator, queryModelVisitor, tree, querySource.ItemName); }
private void Process( FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree, HqlDot memberPath, HqlTreeNode currentNode, IType propType) { string alias = null; if (resultOperator is FetchOneRequest) { if (propType == null) { var metadata = queryModelVisitor.VisitorParameters.SessionFactory .GetClassMetadata(resultOperator.RelationMember.ReflectedType); propType = metadata?.GetPropertyType(resultOperator.RelationMember.Name); } if (propType != null && !propType.IsAssociationType) { if (currentNode == null) { currentNode = tree.GetFromRangeClause() ?? throw new InvalidOperationException($"Property {resultOperator.RelationMember.Name} cannot be fetched for this type of query."); } currentNode.AddChild(tree.TreeBuilder.Fetch()); currentNode.AddChild(memberPath); ComponentType componentType = null; foreach (var innerFetch in resultOperator.InnerFetchRequests) { if (componentType == null) { componentType = propType as ComponentType; if (componentType == null) { throw new InvalidOperationException( $"Property {innerFetch.RelationMember.Name} cannot be fetched from a non component type property {resultOperator.RelationMember.Name}."); } } var subTypeIndex = componentType.GetPropertyIndex(innerFetch.RelationMember.Name); memberPath = tree.TreeBuilder.Dot( memberPath, tree.TreeBuilder.Ident(innerFetch.RelationMember.Name)); Process(innerFetch, queryModelVisitor, tree, memberPath, currentNode, componentType.Subtypes[subTypeIndex]); } return; } var relatedJoin = queryModelVisitor.RelatedJoinFetchRequests.FirstOrDefault(o => o.Value == resultOperator).Key; if (relatedJoin != null) { alias = queryModelVisitor.VisitorParameters.QuerySourceNamer.GetName(relatedJoin); } } if (alias == null) { alias = queryModelVisitor.Model.GetNewName("_"); currentNode = tree.TreeBuilder.LeftFetchJoin(memberPath, tree.TreeBuilder.Alias(alias)); tree.AddFromClause(currentNode); } tree.AddDistinctRootOperator(); foreach (var innerFetch in resultOperator.InnerFetchRequests) { Process(innerFetch, queryModelVisitor, tree, currentNode, alias); } }
public void Process(FetchRequestBase resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree, string sourceAlias) { Process(resultOperator, queryModelVisitor, tree, null, sourceAlias); }