public CachedEntityExpression(Expression primaryKey, Type type, CachedTableConstructor constructor, FieldEmbedded?embedded) { if (primaryKey == null) { throw new ArgumentNullException(nameof(primaryKey)); } if (primaryKey.Type.UnNullify() != typeof(PrimaryKey)) { throw new InvalidOperationException("primaryKey should be a PrimaryKey"); } if (!type.IsEmbeddedEntity()) { if (((Table)constructor.table).Type != type.CleanType()) { throw new InvalidOperationException("Wrong type"); } } else { this.FieldEmbedded = embedded ?? throw new ArgumentNullException(nameof(embedded)); } this.PrimaryKey = primaryKey; this.type = type; this.Constructor = constructor; }
public MList <T> GetMList(PrimaryKey id, IRetriever retriever) { Interlocked.Increment(ref hits); MList <T> result; var dic = relationalRows.Value.TryGetC(id); if (dic == null) { result = new MList <T>(); } else { result = new MList <T>(dic.Count); var innerList = ((IMListPrivate <T>)result).InnerList; foreach (var obj in dic.Values) { innerList.Add(activator(obj, retriever)); } ((IMListPrivate)result).ExecutePostRetrieving(); } CachedTableConstructor.resetModifiedAction(retriever, result); return(result); }
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 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)); } if (field is FieldMList) { throw new NotImplementedException("FieldMList not supported in cached ToString"); } throw new InvalidOperationException("Unexpected {0}".FormatWith(field.GetType().Name)); }
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 !)); }
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 override void SchemaCompleted() { List <IColumn> columns = new List <IColumn> { table.PrimaryKey }; ParameterExpression reader = Expression.Parameter(typeof(FieldReader)); var expression = ToStringExpressionVisitor.GetToString(table, reader, columns); //Query using (ObjectName.OverrideOptions(new ObjectNameOptions { AvoidDatabaseName = true })) { string select = "SELECT {0}\r\nFROM {1} {2}\r\n".FormatWith( columns.ToString(c => currentAlias + "." + c.Name.SqlEscape(), ", "), table.Name.ToString(), currentAlias.ToString()); select += this.lastPartialJoin + currentAlias + "." + table.PrimaryKey.Name.SqlEscape() + "\r\n" + this.remainingJoins; query = new SqlPreCommandSimple(select); } //Reader { var kvpConstructor = Expression.New(CachedTableConstructor.ciKVPIntString, CachedTableConstructor.NewPrimaryKey(FieldReader.GetExpression(reader, 0, this.table.PrimaryKey.Type)), expression); rowReader = Expression.Lambda <Func <FieldReader, KeyValuePair <PrimaryKey, string> > >(kvpConstructor, reader).Compile(); } toStrings = new ResetLazy <Dictionary <PrimaryKey, string> >(() => { CacheLogic.AssertSqlDependencyStarted(); var connector = (SqlConnector)Connector.Current; var subConnector = connector.ForDatabase(table.Name.Schema?.Database); Dictionary <PrimaryKey, string> result = new Dictionary <PrimaryKey, string>(); using (MeasureLoad()) using (Connector.Override(subConnector)) using (Transaction tr = Transaction.ForceNew(IsolationLevel.ReadCommitted)) { if (CacheLogic.LogWriter != null) { CacheLogic.LogWriter.WriteLine("Load {0}".FormatWith(GetType().TypeName())); } ((SqlConnector)Connector.Current).ExecuteDataReaderOptionalDependency(query, OnChange, fr => { var kvp = rowReader(fr); result[kvp.Key] = kvp.Value; }); tr.Commit(); } return(result); }, mode: LazyThreadSafetyMode.ExecutionAndPublication); if (this.subTables != null) { foreach (var item in this.subTables) { item.SchemaCompleted(); } } }
public CachedTableMList(ICacheLogicController controller, TableMList table, AliasGenerator aliasGenerator, string lastPartialJoin, string remainingJoins) : base(controller) { this.table = table; CachedTableConstructor ctr = this.Constructor = new CachedTableConstructor(this, aliasGenerator); //Query using (ObjectName.OverrideOptions(new ObjectNameOptions { AvoidDatabaseName = true })) { string select = "SELECT\r\n{0}\r\nFROM {1} {2}\r\n".FormatWith( ctr.table.Columns.Values.ToString(c => ctr.currentAlias + "." + c.Name.SqlEscape(), ",\r\n"), table.Name.ToString(), ctr.currentAlias.ToString()); ctr.remainingJoins = lastPartialJoin + ctr.currentAlias + "." + table.BackReference.Name.SqlEscape() + "\r\n" + remainingJoins; query = new SqlPreCommandSimple(select); } //Reader { rowReader = ctr.GetRowReader(); } //Completer { List <Expression> instructions = new List <Expression> { Expression.Assign(ctr.origin, Expression.Convert(CachedTableConstructor.originObject, ctr.tupleType)), Expression.Assign(result, ctr.MaterializeField(table.Field)) }; var ci = typeof(MList <T> .RowIdElement).GetConstructor(new [] { typeof(T), typeof(PrimaryKey), typeof(int?) }); var order = table.Order == null?Expression.Constant(null, typeof(int?)) : ctr.GetTupleProperty(table.Order).Nullify(); instructions.Add(Expression.New(ci, result, CachedTableConstructor.NewPrimaryKey(ctr.GetTupleProperty(table.PrimaryKey)), order)); var block = Expression.Block(typeof(MList <T> .RowIdElement), new[] { ctr.origin, result }, instructions); activatorExpression = Expression.Lambda <Func <object, IRetriever, MList <T> .RowIdElement> >(block, CachedTableConstructor.originObject, CachedTableConstructor.retriever); activator = activatorExpression.Compile(); parentIdGetter = ctr.GetPrimaryKeyGetter(table.BackReference); rowIdGetter = ctr.GetPrimaryKeyGetter(table.PrimaryKey); } relationalRows = new ResetLazy <Dictionary <PrimaryKey, Dictionary <PrimaryKey, object> > >(() => { CacheLogic.AssertSqlDependencyStarted(); var connector = (SqlConnector)Connector.Current; var subConnector = connector.ForDatabase(table.Name.Schema?.Database); Dictionary <PrimaryKey, Dictionary <PrimaryKey, object> > result = new Dictionary <PrimaryKey, Dictionary <PrimaryKey, object> >(); using (MeasureLoad()) using (Connector.Override(subConnector)) using (Transaction tr = Transaction.ForceNew(IsolationLevel.ReadCommitted)) { if (CacheLogic.LogWriter != null) { CacheLogic.LogWriter.WriteLine("Load {0}".FormatWith(GetType().TypeName())); } ((SqlConnector)Connector.Current).ExecuteDataReaderOptionalDependency(query, OnChange, fr => { object obj = rowReader(fr); PrimaryKey parentId = parentIdGetter(obj); var dic = result.TryGetC(parentId); if (dic == null) { result[parentId] = dic = new Dictionary <PrimaryKey, object>(); } dic[rowIdGetter(obj)] = obj; }); tr.Commit(); } return(result); }, mode: LazyThreadSafetyMode.ExecutionAndPublication); }
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); //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(), ",\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> >(() => { CacheLogic.AssertSqlDependencyStarted(); var connector = (SqlConnector)Connector.Current; Table table = connector.Schema.Table(typeof(T)); var subConnector = connector.ForDatabase(table.Name.Schema?.Database); Dictionary <PrimaryKey, object> result = new Dictionary <PrimaryKey, object>(); using (MeasureLoad()) using (Connector.Override(subConnector)) using (Transaction tr = Transaction.ForceNew(IsolationLevel.ReadCommitted)) { if (CacheLogic.LogWriter != null) { CacheLogic.LogWriter.WriteLine("Load {0}".FormatWith(GetType().TypeName())); } ((SqlConnector)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); } }