Exemplo n.º 1
0
        private Expression GetEntity(bool isLite, IColumn column, Type type)
        {
            Expression id = GetTupleProperty(column);

            if (isLite)
            {
                Expression lite;
                switch (CacheLogic.GetCacheType(type))
                {
                case CacheType.Cached:
                {
                    lite = Expression.Call(retriever, miRequestLite.MakeGenericMethod(type),
                                           Lite.NewExpression(type, NewPrimaryKey(id.UnNullify()), Expression.Constant(null, typeof(string))));

                    lite = Expression.Call(retriever, miModifiablePostRetrieving.MakeGenericMethod(typeof(LiteImp)), lite.TryConvert(typeof(LiteImp))).TryConvert(lite.Type);

                    break;
                }

                case CacheType.Semi:
                {
                    string lastPartialJoin = CreatePartialInnerJoin(column);

                    CachedTableBase ctb = ciCachedSemiTable.GetInvoker(type)(cachedTable.controller, aliasGenerator !, lastPartialJoin, remainingJoins);

                    if (cachedTable.subTables == null)
                    {
                        cachedTable.subTables = new List <CachedTableBase>();
                    }

                    cachedTable.subTables.Add(ctb);

                    ctb.ParentColumn = column;

                    lite = Expression.Call(Expression.Constant(ctb), ctb.GetType().GetMethod("GetLite"), NewPrimaryKey(id.UnNullify()), retriever);

                    break;
                }

                default: throw new InvalidOperationException("{0} should be cached at this stage".FormatWith(type));
                }

                if (!id.Type.IsNullable())
                {
                    return(lite);
                }

                return(Expression.Condition(Expression.Equal(id, NullId), Expression.Constant(null, Lite.Generate(type)), lite));
            }
            else
            {
                switch (CacheLogic.GetCacheType(type))
                {
                case CacheType.Cached: return(Expression.Call(retriever, miRequest.MakeGenericMethod(type), WrapPrimaryKey(id.Nullify())));

                case CacheType.Semi:
                {
                    string lastPartialJoin = CreatePartialInnerJoin(column);

                    CachedTableBase ctb = ciCachedTable.GetInvoker(type)(cachedTable.controller, aliasGenerator, lastPartialJoin, remainingJoins);

                    if (cachedTable.subTables == null)
                    {
                        cachedTable.subTables = new List <CachedTableBase>();
                    }

                    cachedTable.subTables.Add(ctb);

                    ctb.ParentColumn = column;

                    var entity = Expression.Parameter(type);
                    LambdaExpression lambda = Expression.Lambda(typeof(Action <>).MakeGenericType(type),
                                                                Expression.Call(Expression.Constant(ctb), ctb.GetType().GetMethod("Complete"), entity, retriever),
                                                                entity);

                    return(Expression.Call(retriever, miComplete.MakeGenericMethod(type), WrapPrimaryKey(id.Nullify()), lambda));
                }

                default: throw new InvalidOperationException("{0} should be cached at this stage".FormatWith(type));
                }
            }
        }
Exemplo n.º 2
0
        public Expression MaterializeField(Field field)
        {
            if (field is FieldValue)
            {
                var value = GetTupleProperty((IColumn)field);
                return(value.Type == field.FieldType ? value : Expression.Convert(value, field.FieldType));
            }

            if (field is FieldEnum)
            {
                return(Expression.Convert(GetTupleProperty((IColumn)field), field.FieldType));
            }

            if (field is IFieldReference)
            {
                var  nullRef = Expression.Constant(null, field.FieldType);
                bool isLite  = ((IFieldReference)field).IsLite;

                if (field is FieldReference)
                {
                    IColumn column = (IColumn)field;

                    return(GetEntity(isLite, column, field.FieldType.CleanType()));
                }

                if (field is FieldImplementedBy ib)
                {
                    var call = ib.ImplementationColumns.Aggregate((Expression)nullRef, (acum, kvp) =>
                    {
                        IColumn column = (IColumn)kvp.Value;

                        Expression entity = GetEntity(isLite, column, kvp.Key);

                        return(Expression.Condition(Expression.NotEqual(WrapPrimaryKey(GetTupleProperty(column)), NullId),
                                                    Expression.Convert(entity, field.FieldType),
                                                    acum));
                    });

                    return(call);
                }

                if (field is FieldImplementedByAll iba)
                {
                    Expression id     = GetTupleProperty(iba.Column);
                    Expression typeId = GetTupleProperty(iba.ColumnType);

                    if (isLite)
                    {
                        var liteCreate = Expression.Call(miGetIBALite.MakeGenericMethod(field.FieldType.CleanType()),
                                                         Expression.Constant(Schema.Current),
                                                         NewPrimaryKey(typeId.UnNullify()),
                                                         id.UnNullify());

                        var liteRequest = Expression.Call(retriever, miRequestLite.MakeGenericMethod(Lite.Extract(field.FieldType) !), liteCreate);

                        return(Expression.Condition(Expression.NotEqual(WrapPrimaryKey(id), NullId), liteRequest, nullRef));
                    }
                    else
                    {
                        return(Expression.Call(retriever, miRequestIBA.MakeGenericMethod(field.FieldType), typeId, id));
                    }
                }
            }

            if (field is FieldEmbedded fe)
            {
                Expression ctor = Expression.MemberInit(Expression.New(fe.FieldType),
                                                        fe.EmbeddedFields.Values.Select(f => Expression.Bind(f.FieldInfo, MaterializeField(f.Field))));

                var result = Expression.Call(retriever, miModifiablePostRetrieving.MakeGenericMethod(ctor.Type), ctor);

                if (fe.HasValue == null)
                {
                    return(result);
                }

                return(Expression.Condition(
                           Expression.Equal(GetTupleProperty(fe.HasValue), Expression.Constant(true)),
                           result,
                           Expression.Constant(null, field.FieldType)));
            }


            if (field is FieldMList mListField)
            {
                var idColumn = table.Columns.Values.OfType <FieldPrimaryKey>().First();

                string lastPartialJoin = CreatePartialInnerJoin(idColumn);

                Type elementType = field.FieldType.ElementType() !;

                CachedTableBase ctb = ciCachedTableMList.GetInvoker(elementType)(cachedTable.controller, mListField.TableMList, aliasGenerator, lastPartialJoin, remainingJoins);

                if (cachedTable.subTables == null)
                {
                    cachedTable.subTables = new List <CachedTableBase>();
                }

                cachedTable.subTables.Add(ctb);

                return(Expression.Call(Expression.Constant(ctb), ctb.GetType().GetMethod("GetMList"), NewPrimaryKey(GetTupleProperty(idColumn)), retriever));
            }

            throw new InvalidOperationException("Unexpected {0}".FormatWith(field.GetType().Name));
        }