/// <summary> /// Initializes Orleans queries from the database. Orleans uses only these queries and the variables therein, nothing more. /// </summary> /// <param name="storage">The storage to use.</param> /// <returns>Orleans queries have been loaded to silo or client memory.</returns> /// <remarks>This is public only to be usable to the statistics providers. Not intended for public use otherwise.</remarks> public static async Task <QueryConstantsBag> InitializeOrleansQueriesAsync(this IRelationalStorage storage) { var queryConstants = new QueryConstantsBag(); var query = queryConstants.GetConstant(storage.InvariantName, QueryKeys.OrleansQueriesKey); var orleansQueries = await storage.ReadAsync(query, _ => { }, (selector, _) => { return(Tuple.Create(selector.GetValue <string>("QueryKey"), selector.GetValue <string>("QueryText"))); }).ConfigureAwait(continueOnCapturedContext: false); //The queries need to be added to be used later with a given key. foreach (var orleansQuery in orleansQueries) { queryConstants.AddOrModifyQueryConstant(storage.InvariantName, orleansQuery.Item1, orleansQuery.Item2); } //Check that all the required keys are loaded and throw an exception giving the keys expected but not loaded. var loadedQueriesKeys = queryConstants.GetAllConstants(storage.InvariantName).Keys; var missingQueryKeys = QueryKeys.Keys.Except(loadedQueriesKeys); if (missingQueryKeys.Any()) { throw new ArgumentException(string.Format("Not all required queries found when loading from the database. Missing are: {0}", string.Join(",", missingQueryKeys))); } return(await Task.FromResult(queryConstants)); }
/// <summary> /// Checks the existence of a database using the given <see paramref="storage"/> storage object. /// </summary> /// <param name="databaseName">The name of the database existence of which to check.</param> /// <returns><em>TRUE</em> if the given database exists. <em>FALSE</em> otherwise.</returns> private async Task <bool> ExistsDatabaseAsync(string databaseName) { var ret = await storage.ReadAsync(string.Format(ExistsDatabaseTemplate, databaseName), command => { }, (selector, resultSetCount) => { return(selector.GetBoolean(0)); }).ConfigureAwait(continueOnCapturedContext: false); return(ret.First()); }
private async Task <TAggregate> ReadAsync <TResult, TAggregate>(string query, Func <IDataRecord, TResult> selector, Func <IDbCommand, DbStoredQueries.Columns> parameterProvider, Func <IEnumerable <TResult>, TAggregate> aggregator) { var ret = await storage.ReadAsync(query, selector, command => parameterProvider(command)); return(aggregator(ret)); }
/// <summary> /// Uses <see cref="IRelationalStorage"/> with <see cref="DbExtensions.ReflectionParameterProvider{T}(IDbCommand, T, IReadOnlyDictionary{string, string})"/>. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <param name="storage">The storage to use.</param> /// <param name="query">Executes a given statement. Especially intended to use with <em>SELECT</em> statement, but works with other queries too.</param> /// <param name="parameters">Adds parameters to the query. Parameter names must match those defined in the query.</param> /// <returns>A list of objects as a result of the <see paramref="query"/>.</returns> /// <example>This uses reflection to read results and match the parameters. /// <code> /// //This struct holds the return value in this example. /// public struct Information /// { /// public string TABLE_CATALOG { get; set; } /// public string TABLE_NAME { get; set; } /// } /// /// //Here reflection (<seealso cref="DbExtensions.ReflectionParameterProvider{T}(IDbCommand, T, IReadOnlyDictionary{string, string})"/>) /// is used to match parameter names as well as to read back the results (<seealso cref="DbExtensions.ReflectionSelector{TResult}(IDataRecord)"/>). /// var query = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @tname;"; /// IEnumerable<Information> informationData = await db.ReadAsync<Information>(query, new { tname = 200000 }); /// </code> /// </example> public static async Task <IEnumerable <TResult> > ReadAsync <TResult>(this IRelationalStorage storage, string query, object parameters) { return(await storage.ReadAsync(query, command => { if (parameters != null) { command.ReflectionParameterProvider(parameters); } }, (selector, resultSetCount) => selector.ReflectionSelector <TResult>()).ConfigureAwait(continueOnCapturedContext: false)); }
/// <summary> /// Uses <see cref="IRelationalStorage"/> with <see cref="DbExtensions.ReflectionParameterProvider{T}(IDbCommand, T, IReadOnlyDictionary{string, string})"/>. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <param name="storage">The storage to use.</param> /// <param name="query">Executes a given statement. Especially intended to use with <em>SELECT</em> statement, but works with other queries too.</param> /// <param name="parameters">Adds parameters to the query. Parameter names must match those defined in the query.</param> /// <param name="cancellationToken">The cancellation token. Defaults to <see cref="CancellationToken.None"/>.</param> /// <returns>A list of objects as a result of the <see paramref="query"/>.</returns> /// <example>This uses reflection to read results and match the parameters. /// <code> /// //This struct holds the return value in this example. /// public struct Information /// { /// public string TABLE_CATALOG { get; set; } /// public string TABLE_NAME { get; set; } /// } /// /// //Here reflection (<seealso cref="DbExtensions.ReflectionParameterProvider{T}(IDbCommand, T, IReadOnlyDictionary{string, string})"/>) /// is used to match parameter names as well as to read back the results (<seealso cref="DbExtensions.ReflectionSelector{TResult}(IDataRecord)"/>). /// var query = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @tname;"; /// IEnumerable<Information> informationData = await db.ReadAsync<Information>(query, new { tname = 200000 }); /// </code> /// </example> public static Task <IEnumerable <TResult> > ReadAsync <TResult>(this IRelationalStorage storage, string query, object parameters, CancellationToken cancellationToken = default(CancellationToken)) { return(storage.ReadAsync(query, command => { if (parameters != null) { command.ReflectionParameterProvider(parameters); } }, (selector, resultSetCount, token) => Task.FromResult(selector.ReflectionSelector <TResult>()), cancellationToken)); }
/// <summary> /// Checks the existence of a database using the given <see paramref="storage"/> storage object. /// </summary> /// <param name="storage">The storage to use.</param> /// <param name="databaseName">The name of the database existence of which to check.</param> /// <returns><em>TRUE</em> if the given database exists. <em>FALSE</em> otherwise.</returns> public static async Task <bool> ExistsDatabaseAsync(this IRelationalStorage storage, string query, string databaseName) { var ret = await storage.ReadAsync(string.Format(query, databaseName), command => { var p = command.CreateParameter(); p.ParameterName = "databaseName"; p.Value = databaseName; command.Parameters.Add(p); }, (selector, resultSetCount) => { return(selector.GetBoolean(0)); }).ConfigureAwait(continueOnCapturedContext: false); return(ret.First()); }
/// <summary> /// Creates an instance of a database of type <see cref="RelationalOrleansQueries"/> and Initializes Orleans queries from the database. /// Orleans uses only these queries and the variables therein, nothing more. /// </summary> /// <param name="storage">the underlying storage instance</param> public static async Task<RelationalOrleansQueries> CreateInstance(IRelationalStorage storage) { //this will probably be the same for all relational dbs const string orleansQueriesSelectTemplate = "SELECT QueryKey, QueryText FROM OrleansQuery;"; var orleansQueries = new OrleansQueries(); var propertiesDictionary = typeof(OrleansQueries).GetFields().ToDictionary(p => p.Name, p => p); var populatedKeys = await storage.ReadAsync(orleansQueriesSelectTemplate, _ => { }, (selector, _) => { var queryKey = selector.GetValue<string>("QueryKey"); var queryText = selector.GetValue<string>("QueryText"); propertiesDictionary[queryKey].SetValue(orleansQueries, queryText); return queryKey; }).ConfigureAwait(continueOnCapturedContext: false); //Check that all the required keys are loaded and throw an exception giving the keys expected but not loaded. var missingQueryKeys = populatedKeys.Except(propertiesDictionary.Keys); if (missingQueryKeys.Any()) { throw new ArgumentException(string.Format("Not all required queries found when loading from the database. Missing are: {0}", string.Join(",", missingQueryKeys))); } return new RelationalOrleansQueries(storage, orleansQueries); }
/// <summary> /// A simplified version of <see cref="IRelationalStorage.ReadAsync{TResult}"/> /// </summary> /// <param name="storage"></param> /// <param name="query"></param> /// <param name="selector"></param> /// <param name="parameterProvider"></param> /// <typeparam name="TResult"></typeparam> /// <returns></returns> public static Task <IEnumerable <TResult> > ReadAsync <TResult>(this IRelationalStorage storage, string query, Func <IDataRecord, TResult> selector, Action <IDbCommand> parameterProvider) { return(storage.ReadAsync(query, parameterProvider, (record, i, cancellationToken) => Task.FromResult(selector(record)))); }