/// <summary> /// Default constructor /// </summary> /// <param name="table">The main table</param> /// <param name="principleKeyColumn">The principle key column of the <see cref="Table"/></param> /// <param name="referencedTable">The referenced table</param> /// <param name="foreignKeyColumn">The foreign key column of the <see cref="ReferencedTable"/></param> /// <param name="index"> /// The index level of the join. /// NOTE: If the index is set to zero, then the <see cref="Table"/> is the root table! /// </param> /// <param name="isRightJoin"> /// A flag indicating whether we have a foreign key to primary key join (right join) or not. /// NOTE: When this is set to <see cref="false"/> a left join is applied (the navigation property of the root type is an <see cref="IEnumerable{T}"/>)! /// NOTE: When this is set to <see cref="true"/> a right join is applied (the navigation property of the root type is an object)! /// </param> public JoinMap(IDbProviderTable table, IDbProviderColumn principleKeyColumn, IDbProviderTable referencedTable, IDbProviderColumn foreignKeyColumn, int index, bool isRightJoin) : base() { Table = table ?? throw new ArgumentNullException(nameof(table)); PrincipleKeyColumn = principleKeyColumn ?? throw new ArgumentNullException(nameof(principleKeyColumn)); ReferencedTable = referencedTable ?? throw new ArgumentNullException(nameof(referencedTable)); ForeignKeyColumn = foreignKeyColumn ?? throw new ArgumentNullException(nameof(foreignKeyColumn)); Index = index; IsRightJoin = isRightJoin; }
/// <summary> /// Performs the required includes on the specified <paramref name="queryable"/> /// </summary> /// <param name="queryable">The queryable</param> /// <param name="initialTable">The initial table</param> /// <returns></returns> private IQueryable PerformIncludes(IQueryable queryable, IDbProviderTable initialTable) { // For every join... foreach (var join in Joins) { var joinsPath = ComputePath(join); // For every related join... foreach (var j in joinsPath) { // Get the type of the model var modelType = queryable.GetType().GetGenericArguments()[0]; // If it's the first join... if (joinsPath.ElementAt(0) == j) { // Get the navigation property name var navigationPropertyName = CeidDiplomatikiHelpers.GetPluralForm(j.ReferencedTable.TableName); // Get the navigation property var navigationProperty = modelType.GetProperty(navigationPropertyName); // Create the expression var expression = ExpressionHelpers.CreatePropertySelectorExpression(modelType, navigationProperty); // Get the Include<TEntity, TProperty> method var includeMethod = typeof(EntityFrameworkQueryableExtensions).GetMethods().First(x => x.Name == nameof(EntityFrameworkQueryableExtensions.Include) && x.GetParameters()[1].ParameterType != typeof(string)); // Set the generic arguments (TEntity and TProperty) includeMethod = includeMethod.MakeGenericMethod(modelType, navigationProperty.PropertyType); // Call the Include method queryable = (IQueryable)includeMethod.Invoke(null, new object[] { queryable, expression }); // Continue continue; } queryable = PerformThenInclude(queryable, j); } } // Return the queryable return(queryable); }