예제 #1
0
        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;
        }
예제 #2
0
        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);
        }
예제 #3
0
        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));
        }
예제 #4
0
        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));
        }
예제 #6
0
        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();
                }
            }
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
            }
        }