예제 #1
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, null));
    }
예제 #2
0
    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));
    }
예제 #3
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);
        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);
        }
    }
예제 #4
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 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));
    }