private T _GetContext <T>(AsyncLocal <int> asyncLocal) where T : class, ICoreXTDBContext { lock (_Contexts) { var contextIndex = asyncLocal.Value - 1; // (since AsyncLocal defaults to 0, treat that as -1 [unset index]) if (contextIndex < 0) { contextIndex = _Contexts.Count; asyncLocal.Value = 1 + contextIndex; _Contexts.Add(null); } var ctx = _Contexts[contextIndex]; if (ctx != null) { try { // ... test if it was disposed ... var test = ctx.ConnectionString; } catch (ObjectDisposedException) { // ... was disposed (normally the user should not be disposing these), so we need a new one ... ctx = null; } } if (ctx == null) { _Contexts[contextIndex] = ctx = _ServiceProvider.GetService <T>(); } return((T)ctx); } }
// -------------------------------------------------------------------------------------------------------------------- /// <summary> /// Dynamically configures a CoreXT based DBContext object, and optionally tests that a connection can be made using the given connection string. /// </summary> /// <typeparam name="TContextProvider">The type of provider to use to get the DBContext instances.</typeparam> /// <param name="sp">The CoreXT service provider.</param> /// <param name="isReadonly">True of the context should be read-only.</param> /// <param name="onConfiguring">An function expression to execute if a new context is created (in order to setup the context, such as setting a connection string).</param> /// <param name="commandTimeout">The number of seconds to wait before a command executed against the context times out. If not specified the system default is used, or whatever is specified via the connection string.</param> /// <param name="createNew">If true, a new instance is returned and not the per-request cached instance. Default is false.</param> /// <param name="testConnectingBeforeReturning">If true (default) calls 'ExecuteSqlCommand()' on the context to make sure the connection is valid.</param> /// <returns></returns> public static ICoreXTDBContext ConfigureCoreXTDBContext <TContextProvider>(this ICoreXTServiceProvider sp, bool isReadonly, Action <DbContextOptionsBuilder> onConfiguring = null, int?commandTimeout = null, bool createNew = false, bool testConnectingBeforeReturning = true) where TContextProvider : class, IContextProvider { var contextProvider = sp.GetService <TContextProvider>(); var context = isReadonly ? contextProvider.GetReadonlyContext(createNew) : contextProvider.GetContext(createNew); if (context == null) { throw new InvalidOperationException("There is no " + typeof(TContextProvider).Name + " service object registered."); } if (context.Database == null) { throw new InvalidOperationException("The 'Database' property is null for DBContext type " + typeof(TContextProvider).Name + "."); } if (commandTimeout != null) { context.Database.SetCommandTimeout(TimeSpan.FromSeconds(commandTimeout.Value)); } var logger = sp.GetService <ILoggerFactory>()?.CreateLogger <TContextProvider>(); try { if (onConfiguring != null) { context.Configuring += onConfiguring; } if (string.IsNullOrWhiteSpace(context.ConnectionString)) { throw new IOException("Cannot connect to any database - the connection string is empty."); } try { if (testConnectingBeforeReturning) { context.Database.ExecuteSqlCommand("SELECT 1"); // (test the connection now) } return(context); } catch (Exception ex) { logger?.LogError(new EventId(-1, "CoreXT.Entities"), ex, "The database is not reachable."); throw; } } catch (Exception ex) { logger?.LogError(new EventId(-1, "CoreXT.Entities"), ex, "Error configuring the database context."); throw; } // -------------------------------------------------------------------------------------------------------------------- }
///// <summary> ///// The context for this component. The context is used to get services and access other information about the current ///// HTTP request. ///// <para>By default, this reads from 'Page.Context', unless a different context is set. </para> ///// </summary> //public HttpContext HttpContext => _HttpContext ?? (_HttpContext = _CoreXTServiceProvider.GetService<HttpContextAccessor>().HttpContext); //HttpContext _HttpContext; /// <summary> /// Derived types can use this convenience method to get services as required. /// <para>The 'Page' property </para> /// </summary> /// <typeparam name="T">The type of service object to get.</typeparam> /// <returns>The service object if found, or 'null' otherwise.</returns> protected T GetService <T>() where T : class { return(_CoreXTServiceProvider.GetService <T>()); }
/// <summary> Return a view by giving a specific file location. </summary> /// <param name="executingFilePath"> The absolute path to the currently-executing view, if any (sets a base path to locate the view by). </param> /// <param name="viewPath"> The relative path to the view (relative to 'executingFilePath', if given). </param> /// <param name="isMainPage"> Determines if the page being found is the main page for an action.. </param> /// <returns> The view. </returns> public ViewEngineResult GetView(string executingFilePath, string viewPath, bool isMainPage) { var result = _CompositeViewEngine.GetView(executingFilePath, viewPath, isMainPage); if (result.Success) { var newResult = ((result.View as RazorView)?.RazorPage as IViewPageRenderEvents)?.OnViewFound(_Services.GetService <IActionContextAccessor>()?.ActionContext, result); result = newResult ?? ViewEngineResult.Found(result.ViewName, new ViewResultProxy(result.View)); } return(result); }
public static CoreXTDemoAppSettings GetCoreXTDemoAppSettings(this ICoreXTServiceProvider sp) { return(sp.GetService <IOptions <CoreXTDemoAppSettings> >()?.Value); }
public ContextProvider(ICoreXTServiceProvider sp) { _ServiceProvider = sp; _HttpContext = _ServiceProvider.GetService <IHttpContextAccessor>().HttpContext; // (*** this is null if there is no current context, such as being called before and after a request ***) }