private Expression GetEntity(bool isLite, IColumn column, Type entityType, CachedTableConstructor constructor) { Expression id = constructor.GetTupleProperty(column); var pk = CachedTableConstructor.WrapPrimaryKey(id); CachedTableConstructor typeConstructor = CacheLogic.GetCacheType(entityType) == CacheType.Cached ? CacheLogic.GetCachedTable(entityType).Constructor : constructor.cachedTable.SubTables !.SingleEx(a => a.ParentColumn == column).Constructor; return(new CachedEntityExpression(pk, entityType, typeConstructor, null, null)); }
public static Expression <Func <PrimaryKey, string> > GetToString <T>(CachedTableConstructor constructor, Expression <Func <T, string> > lambda) { Table table = (Table)constructor.table; var param = lambda.Parameters.SingleEx(); if (param.Type != table.Type) { throw new InvalidOperationException("incorrect lambda paramer type"); } var pk = Expression.Parameter(typeof(PrimaryKey), "pk"); var root = new CachedEntityExpression(pk, typeof(T), constructor, null, null); var visitor = new ToStringExpressionVisitor(param, root); var result = visitor.Visit(lambda.Body); return(Expression.Lambda <Func <PrimaryKey, string> >(result, pk)); }
public CachedTable(ICacheLogicController controller, AliasGenerator?aliasGenerator, string?lastPartialJoin, string?remainingJoins) : base(controller) { this.table = Schema.Current.Table(typeof(T)); CachedTableConstructor ctr = this.Constructor = new CachedTableConstructor(this, aliasGenerator); var isPostgres = Schema.Current.Settings.IsPostgres; //Query using (ObjectName.OverrideOptions(new ObjectNameOptions { AvoidDatabaseName = true })) { string select = "SELECT\r\n{0}\r\nFROM {1} {2}\r\n".FormatWith( Table.Columns.Values.ToString(c => ctr.currentAlias + "." + c.Name.SqlEscape(isPostgres), ",\r\n"), table.Name.ToString(), ctr.currentAlias !.ToString()); ctr.remainingJoins = lastPartialJoin == null ? null : lastPartialJoin + ctr.currentAlias + ".Id\r\n" + remainingJoins; if (ctr.remainingJoins != null) { select += ctr.remainingJoins; } query = new SqlPreCommandSimple(select); } //Reader { rowReader = ctr.GetRowReader(); } //Completer { ParameterExpression me = Expression.Parameter(typeof(T), "me"); var block = ctr.MaterializeEntity(me, table); completerExpression = Expression.Lambda <Action <object, IRetriever, T> >(block, CachedTableConstructor.originObject, CachedTableConstructor.retriever, me); completer = completerExpression.Compile(); idGetter = ctr.GetPrimaryKeyGetter((IColumn)table.PrimaryKey); } rows = new ResetLazy <Dictionary <PrimaryKey, object> >(() => { return(SqlServerRetry.Retry(() => { CacheLogic.AssertSqlDependencyStarted(); Table table = Connector.Current.Schema.Table(typeof(T)); Dictionary <PrimaryKey, object> result = new Dictionary <PrimaryKey, object>(); using (MeasureLoad()) using (Connector.Override(Connector.Current.ForDatabase(table.Name.Schema?.Database))) using (var tr = Transaction.ForceNew(IsolationLevel.ReadCommitted)) { if (CacheLogic.LogWriter != null) { CacheLogic.LogWriter.WriteLine("Load {0}".FormatWith(GetType().TypeName())); } Connector.Current.ExecuteDataReaderOptionalDependency(query, OnChange, fr => { object obj = rowReader(fr); result[idGetter(obj)] = obj; //Could be repeated joins }); tr.Commit(); } return result; })); }, mode: LazyThreadSafetyMode.ExecutionAndPublication); if (!CacheLogic.WithSqlDependency && lastPartialJoin.HasText()) //Is semi { semiCachedController = new SemiCachedController <T>(this); } }
private Expression GetField(Field field, CachedTableConstructor constructor, Expression?previousPrimaryKey) { if (field is FieldValue) { var value = constructor.GetTupleProperty((IColumn)field); return(value.Type == field.FieldType ? value : Expression.Convert(value, field.FieldType)); } if (field is FieldEnum) { return(Expression.Convert(constructor.GetTupleProperty((IColumn)field), field.FieldType)); } if (field is FieldPrimaryKey) { return(constructor.GetTupleProperty((IColumn)field)); } if (field is IFieldReference) { bool isLite = ((IFieldReference)field).IsLite; if (field is FieldReference) { IColumn column = (IColumn)field; return(GetEntity(isLite, column, field.FieldType.CleanType(), constructor)); } if (field is FieldImplementedBy ib) { var nullRef = Expression.Constant(null, field.FieldType); var call = ib.ImplementationColumns.Aggregate((Expression)nullRef, (acum, kvp) => { IColumn column = (IColumn)kvp.Value; var entity = GetEntity(isLite, column, kvp.Key, constructor); return(Expression.Condition(Expression.NotEqual(constructor.GetTupleProperty(column), Expression.Constant(column.Type)), Expression.Convert(entity, field.FieldType), acum)); }); return(call); } if (field is FieldImplementedByAll) { throw new NotImplementedException("FieldImplementedByAll not supported in cached ToString"); } } if (field is FieldEmbedded fe) { return(new CachedEntityExpression(previousPrimaryKey !, fe.FieldType, constructor, fe, null)); } if (field is FieldMixin fm) { return(new CachedEntityExpression(previousPrimaryKey !, fm.FieldType, constructor, null, fm)); } if (field is FieldMList) { throw new NotImplementedException("FieldMList not supported in cached ToString"); } throw new InvalidOperationException("Unexpected {0}".FormatWith(field.GetType().Name)); }