예제 #1
0
        public Task <object?> ExecuteAsync(CancellationToken token)
        {
            return(SqlServerRetry.RetryAsync(async() =>
            {
                using (new EntityCache())
                    using (Transaction tr = new Transaction())
                    {
                        object?result;
                        using (var retriever = EntityCache.NewRetriever())
                        {
                            var lookups = new Dictionary <LookupToken, IEnumerable>();

                            foreach (var child in EagerProjections)
                            {
                                await child.FillAsync(lookups, retriever, token);
                            }

                            using (HeavyProfiler.Log("SQL", () => MainCommand.sp_executesql()))
                                using (var reader = await Executor.UnsafeExecuteDataReaderAsync(MainCommand, token: token))
                                {
                                    ProjectionRowEnumerator <T> enumerator = new ProjectionRowEnumerator <T>(reader.Reader, ProjectorExpression, lookups, retriever, token);

                                    IEnumerable <T> enumerable = new ProjectionRowEnumerable <T>(enumerator);

                                    try
                                    {
                                        if (Unique == null)
                                        {
                                            result = enumerable.ToList();
                                        }
                                        else
                                        {
                                            result = UniqueMethod(enumerable, Unique.Value);
                                        }
                                    }
                                    catch (Exception ex) when(!(ex is OperationCanceledException))
                                    {
                                        FieldReaderException fieldEx = enumerator.Reader.CreateFieldReaderException(ex);
                                        fieldEx.Command = MainCommand;
                                        fieldEx.Row = enumerator.Row;
                                        fieldEx.Projector = ProjectorExpression;
                                        throw fieldEx;
                                    }
                                }

                            foreach (var child in LazyChildProjections)
                            {
                                await child.FillAsync(lookups, retriever, token);
                            }

                            retriever.CompleteAll();
                        }

                        return tr.Commit(result);
                    }
            }));
        }
예제 #2
0
        public static SqlServerVersion?Detect(string connectionString)
        {
            return(SqlServerRetry.Retry(() =>
            {
                using (SqlConnection con = new SqlConnection(connectionString))
                {
                    con.Open();
                    var sql =
                        @"SELECT
    SERVERPROPERTY ('ProductVersion') as ProductVersion,
    SERVERPROPERTY('ProductLevel') as ProductLevel,
    SERVERPROPERTY('Edition') as Edition,
    SERVERPROPERTY('EngineEdition') as EngineEdition";

                    using (SqlCommand cmd = new SqlCommand(sql, con))
                    {
                        SqlDataAdapter da = new SqlDataAdapter(cmd);

                        DataTable result = new DataTable();
                        da.Fill(result);

                        if ((int)result.Rows[0]["EngineEdition"] == (int)EngineEdition.Azure)
                        {
                            return SqlServerVersion.AzureSQL;
                        }

                        var version = (string)result.Rows[0]["ProductVersion"];

                        switch (version.Before("."))
                        {
                        case "8": throw new InvalidOperationException("SQL Server 2000 is not supported");

                        case "9": return SqlServerVersion.SqlServer2005;

                        case "10": return SqlServerVersion.SqlServer2008;

                        case "11": return SqlServerVersion.SqlServer2012;

                        case "12": return SqlServerVersion.SqlServer2014;

                        case "13": return SqlServerVersion.SqlServer2016;

                        case "14": return SqlServerVersion.SqlServer2017;

                        case "15": return SqlServerVersion.SqlServer2019;

                        default: return (SqlServerVersion?)null;
                        }
                    }
                }
            }));
        }
예제 #3
0
        T EnsureConnectionRetry <T>(Func <SqlConnection?, T> action)
        {
            if (Transaction.HasTransaction)
            {
                return(action(null));
            }

            return(SqlServerRetry.Retry(() =>
            {
                using (SqlConnection con = new SqlConnection(this.ConnectionString))
                {
                    con.Open();

                    return action(con);
                }
            }));
        }
예제 #4
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 (Transaction 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);
            }
        }
예제 #5
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);
            var isPostgres = Schema.Current.Settings.IsPostgres;

            //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(isPostgres), ", "),
                    table.Name.ToString(),
                    currentAlias.ToString());

                select += this.lastPartialJoin + currentAlias + "." + table.PrimaryKey.Name.SqlEscape(isPostgres) + "\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> >(() =>
            {
                return(SqlServerRetry.Retry(() =>
                {
                    CacheLogic.AssertSqlDependencyStarted();

                    Dictionary <PrimaryKey, string> result = new Dictionary <PrimaryKey, string>();

                    using (MeasureLoad())
                        using (Connector.Override(Connector.Current.ForDatabase(table.Name.Schema?.Database)))
                            using (Transaction tr = Transaction.ForceNew(IsolationLevel.ReadCommitted))
                            {
                                if (CacheLogic.LogWriter != null)
                                {
                                    CacheLogic.LogWriter.WriteLine("Load {0}".FormatWith(GetType().TypeName()));
                                }

                                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();
                }
            }
        }
예제 #6
0
        public CachedTableMList(ICacheLogicController controller, TableMList table, AliasGenerator?aliasGenerator, string lastPartialJoin, string?remainingJoins)
            : base(controller)
        {
            this.table = table;
            var isPostgres             = Schema.Current.Settings.IsPostgres;
            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(isPostgres), ",\r\n"),
                    table.Name.ToString(),
                    ctr.currentAlias !.ToString());

                ctr.remainingJoins = lastPartialJoin + ctr.currentAlias + "." + table.BackReference.Name.SqlEscape(isPostgres) + "\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> > >(() =>
            {
                return(SqlServerRetry.Retry(() =>
                {
                    CacheLogic.AssertSqlDependencyStarted();

                    Dictionary <PrimaryKey, Dictionary <PrimaryKey, object> > result = new Dictionary <PrimaryKey, Dictionary <PrimaryKey, object> >();

                    using (MeasureLoad())
                        using (Connector.Override(Connector.Current.ForDatabase(table.Name.Schema?.Database)))
                            using (Transaction 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);
                                    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);
        }