public IList <ProductAttribute> GetByProductId(int productId, bool onlyVariantSpecific = false) { var q = Repository.Where(x => x.ProductId == productId) .Join <AvailableAttribute>("AvailableAttributeId", "Id", joinType: JoinType.LeftOuter) //.Join<Product>("ProductId", "Id") .Join <ProductAttributeValue>("Id", "ProductAttributeId", SourceColumn.Parent, joinType: JoinType.LeftOuter) .Join <AvailableAttributeValue>("AvailableAttributeValueId", "Id", joinType: JoinType.LeftOuter); //should we restrict to only variant specific attributes if (onlyVariantSpecific) { var allowedInputTypes = VariantHelper.GetVariantSpecificFieldTypes(); Expression <Func <ProductAttribute, bool> > variantWhere = attribute => allowedInputTypes.Contains(attribute.InputFieldType); q.Where(variantWhere); } return(q .Relate(RelationTypes.OneToMany <ProductAttribute, ProductAttributeValue>()) .Relate <AvailableAttributeValue>((productAttribute, availableAttributeValue) => { if (productAttribute.Tag == null) { productAttribute.Tag = new List <AvailableAttributeValue>(); } var attributeList = (List <AvailableAttributeValue>)productAttribute.Tag; if (!attributeList.Contains(availableAttributeValue)) { attributeList.Add(availableAttributeValue); } var pav = productAttribute.ProductAttributeValues.FirstOrDefault( x => x.AvailableAttributeValueId == availableAttributeValue.Id); if (pav != null) { pav.AvailableAttributeValue = availableAttributeValue; } }) .Relate <AvailableAttribute>((productAttribute, availableAttribute) => { availableAttribute.AvailableAttributeValues = (List <AvailableAttributeValue>)productAttribute.Tag; productAttribute.AvailableAttribute = availableAttribute; }) .OrderBy(x => x.DisplayOrder) .SelectNested() .ToList()); }