Ejemplo n.º 1
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();
                }
            }
        }
Ejemplo n.º 2
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);
            }
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
0
        public static List <T> ToListWithInvalidation <T>(this IQueryable <T> simpleQuery, Type type, string exceptionContext, Action <SqlNotificationEventArgs> invalidation)
        {
            if (!WithSqlDependency)
            {
                throw new InvalidOperationException("ToListWithInvalidation requires SqlDependency");
            }

            ITranslateResult tr;

            using (ObjectName.OverrideOptions(new ObjectNameOptions {
                AvoidDatabaseName = true
            }))
                tr = ((DbQueryProvider)simpleQuery.Provider).GetRawTranslateResult(simpleQuery.Expression);

            OnChangeEventHandler onChange = (object sender, SqlNotificationEventArgs args) =>
            {
                try
                {
                    if (args.Type != SqlNotificationType.Change)
                    {
                        throw new InvalidOperationException(
                                  "Problems with SqlDependency (Type : {0} Source : {1} Info : {2}) on query: \r\n{3}"
                                  .FormatWith(args.Type, args.Source, args.Info, tr.MainCommand.PlainSql()));
                    }

                    if (args.Info == SqlNotificationInfo.PreviousFire)
                    {
                        throw new InvalidOperationException("The same transaction that loaded the data is invalidating it!")
                              {
                                  Data = { { "query", tr.MainCommand.PlainSql() } }
                              }
                    }
                    ;

                    if (CacheLogic.LogWriter != null)
                    {
                        CacheLogic.LogWriter.WriteLine("Change ToListWithInvalidations {0} {1}".FormatWith(typeof(T).TypeName()), exceptionContext);
                    }

                    invalidation(args);
                }
                catch (Exception e)
                {
                    e.LogException(c => c.ControllerName = exceptionContext);
                }
            };

            SimpleReader reader = null;

            Expression <Func <IProjectionRow, T> > projectorExpression = (Expression <Func <IProjectionRow, T> >)tr.GetMainProjector();
            Func <IProjectionRow, T> projector = projectorExpression.Compile();

            List <T> list = new List <T>();

            CacheLogic.AssertSqlDependencyStarted();

            Table        table = Schema.Current.Table(type);
            DatabaseName db    = table.Name.Schema?.Database;

            SqlConnector subConnector = ((SqlConnector)Connector.Current).ForDatabase(db);

            if (CacheLogic.LogWriter != null)
            {
                CacheLogic.LogWriter.WriteLine("Load ToListWithInvalidations {0} {1}".FormatWith(typeof(T).TypeName()), exceptionContext);
            }

            using (new EntityCache())
                using (var r = EntityCache.NewRetriever()) {
                    subConnector.ExecuteDataReaderDependency(tr.MainCommand, onChange, StartSqlDependencyAndEnableBrocker, fr =>
                    {
                        if (reader == null)
                        {
                            reader = new SimpleReader(fr, r);
                        }

                        list.Add(projector(reader));
                    }, CommandType.Text);

                    r.CompleteAll();
                }

            return(list);
        }