예제 #1
0
        static void CheckFilterFunc(Type expectedType, Type filterType, MappingSchema mappingSchema)
        {
            var propType = expectedType;

            if (EagerLoading.IsEnumerableType(expectedType, mappingSchema))
            {
                propType = EagerLoading.GetEnumerableElementType(expectedType, mappingSchema);
            }
            var itemType = typeof(Expression <>).IsSameOrParentOf(filterType) ?
                           filterType.GetGenericArguments()[0].GetGenericArguments()[0].GetGenericArguments()[0] :
                           filterType.GetGenericArguments()[0].GetGenericArguments()[0];

            if (propType != itemType)
            {
                throw new LinqException("Invalid filter function usage.");
            }
        }
예제 #2
0
        public static Expression EnrichLoadWith(IDataContext dataContext, Expression table, Type entityType, List <LoadWithInfo[]> loadWith, MappingSchema mappingSchema)
        {
            var args       = new List <Expression>(2);
            var currentObj = table;

            foreach (var members in loadWith)
            {
                var  currentEntityType = entityType;
                var  isPrevEnumerable  = false;
                Type?prevMemberType    = null;

                foreach (var member in members)
                {
                    args.Clear();
                    args.Add(currentObj);

                    var memberType         = member.MemberInfo.GetMemberType();
                    var isEnumerableMember =
                        EagerLoading.IsEnumerableType(memberType, mappingSchema);

                    var desiredType = member.MemberInfo.IsMethodEx() ? currentEntityType : member.MemberInfo.DeclaringType;

                    var entityParam = Expression.Parameter(currentEntityType, "e");
                    var loadBody    = desiredType == currentEntityType
                                                ? (Expression)entityParam
                                                : Expression.Convert(entityParam, desiredType);

                    loadBody = Expression.MakeMemberAccess(loadBody, member.MemberInfo);
                    if (member.MemberFilter != null)
                    {
                        loadBody = member.MemberFilter.GetBody(loadBody);
                    }

                    var hasFilterFunc = member.FilterFunc != null;

                    if (isEnumerableMember && hasFilterFunc)
                    {
                        var propType       = EagerLoading.GetEnumerableElementType(memberType, mappingSchema);
                        var enumerableType = typeof(IEnumerable <>).MakeGenericType(propType);
                        if (loadBody.Type != enumerableType)
                        {
                            loadBody = Expression.Convert(loadBody, enumerableType);
                        }
                    }

                    args.Add(Expression.Quote(Expression.Lambda(loadBody, entityParam)));

                    if (hasFilterFunc)
                    {
                        args.Add(member.FilterFunc !);
                    }

                    MethodInfo method;
                    if (prevMemberType == null)
                    {
                        method = !hasFilterFunc
                                                        ? Methods.LinqToDB.LoadWith
                                                        : isEnumerableMember
                                                                ? Methods.LinqToDB.LoadWithManyFilter
                                                                : Methods.LinqToDB.LoadWithSingleFilter;


                        var propType = memberType;
                        if (hasFilterFunc && isEnumerableMember)
                        {
                            propType = EagerLoading.GetEnumerableElementType(propType, mappingSchema);
                        }
                        method = method.MakeGenericMethod(entityType, propType);
                    }
                    else
                    {
                        if (isPrevEnumerable)
                        {
                            if (!hasFilterFunc)
                            {
                                method = Methods.LinqToDB.ThenLoadFromMany;
                            }
                            else if (isEnumerableMember)
                            {
                                method = Methods.LinqToDB.ThenLoadFromManyManyFilter;
                            }
                            else
                            {
                                method = Methods.LinqToDB.ThenLoadFromManySingleFilter;
                            }
                        }
                        else
                        {
                            if (!hasFilterFunc)
                            {
                                method = Methods.LinqToDB.ThenLoadFromSingle;
                            }
                            else if (isEnumerableMember)
                            {
                                method = Methods.LinqToDB.ThenLoadFromSingleManyFilter;
                            }
                            else
                            {
                                method = Methods.LinqToDB.ThenLoadFromSingleSingleFilter;
                            }
                        }

                        var propType = memberType;
                        if (hasFilterFunc && isEnumerableMember)
                        {
                            propType = EagerLoading.GetEnumerableElementType(propType, mappingSchema);
                        }
                        method = method.MakeGenericMethod(entityType, prevMemberType, propType);
                    }

                    currentObj = Expression.Call(method, args);

                    isPrevEnumerable = isEnumerableMember && !hasFilterFunc;

                    if (isEnumerableMember)
                    {
                        memberType = EagerLoading.GetEnumerableElementType(memberType, mappingSchema);
                    }

                    prevMemberType    = memberType;
                    currentEntityType = memberType;
                }
            }

            return(currentObj);
        }