public void CannotFindForeignKeysWithoutIds()
        {
            var rightPi = ExpressionHelper.GetPropertyInfo <CustomerWithNoId>(x => x.Address);

            var result = ForeignKeyConventionHelper.GetForeignKeyPropertyInfos(rightPi);

            Assert.Null(result);
        }
        public void FindForeignKeysFromSourceOneDirection()
        {
            var rightPi = ExpressionHelper.GetPropertyInfo <TableI>(x => x.TableJ);
            var result  = ForeignKeyConventionHelper.GetForeignKeyPropertyInfos(rightPi);

            Assert.NotNull(result);

            Assert.Null(result.LeftNavPi);
            Assert.Equal(nameof(TableI.TableJId), result.LeftKeysToJoinOn[0].Name);

            Assert.Equal(rightPi, result.RightNavPi);
            Assert.Equal(nameof(TableJ.Id), result.RightKeysToJoinOn[0].Name);
        }
        public void FindForeignKeysWithNavigationPropertyHavingCompositeKey()
        {
            var rightPi = ExpressionHelper.GetPropertyInfo <CustomerWithThreeCompositePrimaryKey>(x => x.Address);

            var result = ForeignKeyConventionHelper.GetForeignKeyPropertyInfos(rightPi);

            var rightKeys = result.RightKeysToJoinOn;

            Assert.Equal(3, rightKeys.Length);
            Assert.Equal(nameof(CustomerAddressWithWithThreeCompositePrimaryKey.CustomerId1), rightKeys[0].Name);
            Assert.Equal(nameof(CustomerAddressWithWithThreeCompositePrimaryKey.CustomerId2), rightKeys[1].Name);
            Assert.Equal(nameof(CustomerAddressWithWithThreeCompositePrimaryKey.CustomerId3), rightKeys[2].Name);
        }
        /// <summary>
        /// Gets the default conventions.
        /// </summary>
        /// <typeparam name="TOwner">The type that owns this conventions.</typeparam>
        public static IRepositoryConventions Default <TOwner>() where TOwner : IRepositoryContext
        {
            var conventions = new RepositoryConventions(typeof(TOwner));

            conventions.PrimaryKeysCallback      = pi => PrimaryKeyConventionHelper.GetPrimaryKeyPropertyInfos(conventions, pi);
            conventions.ForeignKeysCallback      = (sourceType, foreignType) => ForeignKeyConventionHelper.GetForeignKeyPropertyInfos(conventions, sourceType, foreignType);
            conventions.TableNameCallback        = type => ModelConventionHelper.GetTableName(type);
            conventions.ColumnNameCallback       = pi => ModelConventionHelper.GetColumnName(pi);
            conventions.ColumnOrderCallback      = pi => ModelConventionHelper.GetColumnOrder(conventions, pi);
            conventions.IsColumnIdentityCallback = pi => ModelConventionHelper.IsColumnIdentity(conventions, pi);
            conventions.IsColumnMappedCallback   = pi => ModelConventionHelper.IsColumnMapped(pi);

            return(conventions);
        }
        public void FindForeignKeysFromSourceWithForeignKeyAttributeOnNavigationProperty()
        {
            var rightPi = ExpressionHelper.GetPropertyInfo <CustomerWithForeignKeyAttribute>(x => x.Address);
            var leftPi  = ExpressionHelper.GetPropertyInfo <CustomerAddressWithCustomerWithForeignKeyAttribute>(x => x.Customer);

            var result = ForeignKeyConventionHelper.GetForeignKeyPropertyInfos(rightPi);

            Assert.NotNull(result);

            Assert.Equal(leftPi, result.LeftNavPi);
            Assert.Equal(nameof(CustomerWithForeignKeyAttribute.AddressRefId), result.LeftKeysToJoinOn[0].Name);

            Assert.Equal(rightPi, result.RightNavPi);
            Assert.Equal(nameof(CustomerAddressWithCustomerWithForeignKeyAttribute.Id), result.RightKeysToJoinOn[0].Name);
        }
        public void FindForeignKeysFromSource()
        {
            var rightPi = ExpressionHelper.GetPropertyInfo <CustomerPhone>(x => x.Customer);
            var leftPi  = ExpressionHelper.GetPropertyInfo <Customer>(x => x.Phone);

            var result = ForeignKeyConventionHelper.GetForeignKeyPropertyInfos(rightPi);

            Assert.NotNull(result);

            Assert.Equal(leftPi, result.LeftNavPi);
            Assert.Equal(nameof(CustomerPhone.CustomerId), result.LeftKeysToJoinOn[0].Name);

            Assert.Equal(rightPi, result.RightNavPi);
            Assert.Equal(nameof(CustomerPhone.Id), result.RightKeysToJoinOn[0].Name);
        }
Example #7
0
        private static IEnumerable <JoinResult <TOuter, object> > Join <TOuter>(IEnumerable <TOuter> outer, Type outerType, IEnumerable <object> inner, Type innerType, string propertyName)
        {
            // Only do a join when the primary table has a foreign key property for the join table
            var innerDefaultType   = innerType.TryGetGenericTypeOrDefault(out bool isInnerTypeCollection);
            var fkConventionResult = ForeignKeyConventionHelper.GetForeignKeyPropertyInfos(outerType, innerDefaultType, propertyName);

            if (fkConventionResult != null)
            {
                var leftNavPi             = fkConventionResult.LeftNavPi;
                var leftKeysToJoinOn      = fkConventionResult.LeftKeysToJoinOn;
                var rightNavPi            = fkConventionResult.RightNavPi;
                var rightKeysToJoinOn     = fkConventionResult.RightKeysToJoinOn;
                var isRightTypeCollection = rightNavPi != null?rightNavPi.PropertyType.IsEnumerable() : isInnerTypeCollection;

                // key selector functions
                object[] outerKeySelectorFunc(TOuter o)
                {
                    return(leftKeysToJoinOn.Select(pi => pi.GetSafeValue(o)).ToArray());
                }

                object[] innerKeySelectorFunc(object i)
                {
                    return(rightKeysToJoinOn.Select(pi => pi.GetSafeValue(i)).ToArray());
                }

                if (isRightTypeCollection)
                {
                    return(outer.GroupJoin(
                               inner,
                               outerKeySelectorFunc,
                               innerKeySelectorFunc,
                               (o, i) =>
                    {
                        if (i != null)
                        {
                            // Cast collection
                            var items = ToList(i.Select(item =>
                            {
                                if (leftNavPi != null)
                                {
                                    // Sets the main table property in the join table
                                    leftNavPi.SetValue(item, o);
                                }

                                return item;
                            }), innerDefaultType);

                            if (rightNavPi != null)
                            {
                                // Sets the join table property in the main table
                                rightNavPi.SetValue(o, items);
                            }
                        }

                        return new JoinResult <TOuter, object>(o, i);
                    }, _comparer));
                }

                return(LeftJoin(
                           outer,
                           inner,
                           outerKeySelectorFunc,
                           innerKeySelectorFunc,
                           (o, i) =>
                {
                    if (i != null)
                    {
                        if (leftNavPi != null)
                        {
                            // Sets the main table property in the join table
                            leftNavPi.SetValue(i, o);
                        }

                        if (rightNavPi != null)
                        {
                            // Sets the join table property in the main table
                            rightNavPi.SetValue(o, i);
                        }
                    }

                    return new JoinResult <TOuter, object>(o, i);
                }, _comparer));
            }

            return(outer.Select(o => new JoinResult <TOuter, object>(o, null)));
        }