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)); } } }
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)); }