From 5482474175e03139e8406ec61dd1cc7903408a15 Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Fri, 10 Apr 2026 11:04:33 -0700 Subject: [PATCH] Rename Catalog Extensions --- .../ServiceCollectionExtensions.cs | 67 ++++++++ .../docs/core/data-storage.md | 20 +-- .../docs/core/getting-started-aspnet.md | 2 +- .../YesSqlServiceCollectionExtensions.cs | 22 +-- .../ServiceCollectionExtensions.cs | 144 +++--------------- .../ServiceCollectionExtensions.cs | 89 ++++++----- .../EntityCoreStoreTests.cs | 2 +- 7 files changed, 157 insertions(+), 189 deletions(-) create mode 100644 src/Abstractions/CrestApps.Core.Abstractions/ServiceCollectionExtensions.cs diff --git a/src/Abstractions/CrestApps.Core.Abstractions/ServiceCollectionExtensions.cs b/src/Abstractions/CrestApps.Core.Abstractions/ServiceCollectionExtensions.cs new file mode 100644 index 00000000..99814365 --- /dev/null +++ b/src/Abstractions/CrestApps.Core.Abstractions/ServiceCollectionExtensions.cs @@ -0,0 +1,67 @@ +using CrestApps.Core.Models; +using CrestApps.Core.Services; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace CrestApps.Core; + +public static class ServiceCollectionExtensions +{ + public static IServiceCollection AddDocumentCatalog(this IServiceCollection services) + where TModel : CatalogItem + where T : class, ICatalog + { + services.RemoveAll>(); + + services.AddScoped(); + services.AddScoped>(sp => sp.GetRequiredService()); + + return services; + } + + public static IServiceCollection AddNamedDocumentCatalog(this IServiceCollection services) + where TModel : CatalogItem, INameAwareModel + where T : class, INamedCatalog + { + services.RemoveAll>(); + services.RemoveAll>(); + + services.AddScoped(); + services.AddScoped>(sp => sp.GetRequiredService()); + services.AddScoped>(sp => sp.GetRequiredService()); + + return services; + } + + public static IServiceCollection AddSourceDocumentCatalog(this IServiceCollection services) + where TModel : CatalogItem, ISourceAwareModel + where T : class, ISourceCatalog + { + services.RemoveAll>(); + services.RemoveAll>(); + + services.AddScoped(); + services.AddScoped>(sp => sp.GetRequiredService()); + services.AddScoped>(sp => sp.GetRequiredService()); + + return services; + } + + public static IServiceCollection AddNamedSourceDocumentCatalog(this IServiceCollection services) + where TModel : CatalogItem, INameAwareModel, ISourceAwareModel + where T : class, INamedSourceCatalog + { + services.RemoveAll>(); + services.RemoveAll>(); + services.RemoveAll>(); + services.RemoveAll>(); + + services.AddScoped(); + services.AddScoped>(sp => sp.GetRequiredService()); + services.AddScoped>(sp => sp.GetRequiredService()); + services.AddScoped>(sp => sp.GetRequiredService()); + services.AddScoped>(sp => sp.GetRequiredService()); + + return services; + } +} diff --git a/src/CrestApps.Core.Docs/docs/core/data-storage.md b/src/CrestApps.Core.Docs/docs/core/data-storage.md index cc4dfbe8..7a3b91db 100644 --- a/src/CrestApps.Core.Docs/docs/core/data-storage.md +++ b/src/CrestApps.Core.Docs/docs/core/data-storage.md @@ -18,15 +18,15 @@ builder.Services.AddCrestAppsCore(crestApps => crestApps .UseSqLite("Data Source=app.db;Cache=Shared") .SetTablePrefix("CA_"))); -builder.Services.AddNamedSourceDocumentCatalog(); +builder.Services.AddYesSqlNamedSourceDocumentCatalog(); // Entity Framework Core + SQLite builder.Services.AddCrestAppsCore(crestApps => crestApps .AddEntityCoreSqliteDataStore("Data Source=app.db")); -builder.Services.AddCoreEntityCoreStores(); +builder.Services.AddEntityCoreStores(); ``` -`AddYesSqlDataStore(...)` on the root CrestApps builder maps to `AddCoreYesSqlDataStore(...)`, while `AddEntityCoreSqliteDataStore(...)` maps to `AddCoreEntityCoreSqliteDataStore(...)`. The YesSql and Entity Framework Core packages are both optional: consumers can register either flavor or replace them with their own persistence layer entirely. +`AddYesSqlDataStore(...)` on the root CrestApps builder maps to `AddCoreYesSqlDataStore(...)`, while `AddEntityCoreSqliteDataStore(...)` maps to `AddCoreEntityCoreSqliteDataStore(...)`. The YesSql and Entity Framework Core packages are both optional: consumers can register either flavor or replace them with their own persistence layer entirely. After configuring the EF Core data store, call `AddEntityCoreStores()` to register the built-in CrestApps stores and catalog services. Reusable AI-related YesSql index models, `IndexProvider` types, and schema helpers now live in `CrestApps.Core.Data.YesSql` as well, so hosts can register the shared AI storage surface without copying provider implementations out of the sample app. Within that project, feature assets are grouped directly under `Indexes/{Feature}`, their namespaces follow the same `CrestApps.Core.Data.YesSql.Indexes.{Feature}` shape, each shared schema-helper file is scoped to a single index type, and each shared index file now keeps the index model beside its matching `IndexProvider` for easier maintenance. @@ -105,10 +105,10 @@ public interface INamedSourceCatalog : INamedCatalog, ISourceCatalog | Method | Registers | Requires | |--------|-----------|----------| -| `AddDocumentCatalog()` | `ICatalog` | `CatalogItem` + `CatalogItemIndex` | -| `AddNamedDocumentCatalog()` | `ICatalog` + `INamedCatalog` | + `INameAwareModel` + `INameAwareIndex` | -| `AddSourceDocumentCatalog()` | `ICatalog` + `ISourceCatalog` | + `ISourceAwareModel` + `ISourceAwareIndex` | -| `AddNamedSourceDocumentCatalog()` | All four interfaces | Both `INameAware*` + `ISourceAware*` | +| `AddYesSqlDocumentCatalog()` | `ICatalog` | `CatalogItem` + `CatalogItemIndex` | +| `AddYesSqlNamedDocumentCatalog()` | `ICatalog` + `INamedCatalog` | + `INameAwareModel` + `INameAwareIndex` | +| `AddYesSqlSourceDocumentCatalog()` | `ICatalog` + `ISourceCatalog` | + `ISourceAwareModel` + `ISourceAwareIndex` | +| `AddYesSqlNamedSourceDocumentCatalog()` | All four interfaces | Both `INameAware*` + `ISourceAware*` | The Entity Framework Core package exposes the same service-registration shape without YesSql indexes: @@ -119,7 +119,7 @@ The Entity Framework Core package exposes the same service-registration shape wi | `AddSourceDocumentCatalog()` | `ICatalog` + `ISourceCatalog` | `CatalogItem` + `ISourceAwareModel` | | `AddNamedSourceDocumentCatalog()` | All four interfaces | `CatalogItem` + both awareness interfaces | -`AddCoreEntityCoreStores()` registers the built-in CrestApps store interfaces (`IAIChatSessionManager`, prompt stores, document stores, memory stores, search index profile store, and related catalog registrations) against the Entity Framework Core package. +`AddEntityCoreStores()` registers the built-in CrestApps store interfaces (`IAIChatSessionManager`, prompt stores, document stores, memory stores, search index profile store, and related catalog registrations) against the Entity Framework Core package. ## Catalog Entry Handlers @@ -204,7 +204,7 @@ The `CrestApps.Core.Data.EntityCore` package gives you a ready-made alternative builder.Services.AddCoreEntityCoreSqliteDataStore( $"Data Source={Path.Combine(builder.Environment.ContentRootPath, "App_Data", "crestapps.db")}"); -builder.Services.AddCoreEntityCoreStores(); +builder.Services.AddEntityCoreStores(); ``` Create the schema during startup: @@ -313,7 +313,7 @@ Register additional read-only sources alongside the primary catalog: ```csharp // Primary writable catalog (YesSql-backed) -builder.Services.AddNamedSourceDocumentCatalog(); +builder.Services.AddYesSqlNamedSourceDocumentCatalog(); // Additional read-only source (e.g., code-defined defaults) builder.Services.AddScoped, DefaultProfilesCatalog>(); diff --git a/src/CrestApps.Core.Docs/docs/core/getting-started-aspnet.md b/src/CrestApps.Core.Docs/docs/core/getting-started-aspnet.md index 6d31463a..0963f4a5 100644 --- a/src/CrestApps.Core.Docs/docs/core/getting-started-aspnet.md +++ b/src/CrestApps.Core.Docs/docs/core/getting-started-aspnet.md @@ -164,7 +164,7 @@ For local SQLite-backed EF Core development: builder.Services.AddCoreEntityCoreSqliteDataStore( $"Data Source={Path.Combine(builder.Environment.ContentRootPath, "App_Data", "crestapps.db")}"); -builder.Services.AddCoreEntityCoreStores(); +builder.Services.AddEntityCoreStores(); ``` For YesSql, keep using `AddCoreYesSqlDataStore(...)` plus the YesSql catalog registrations. If you already use another ORM or storage model, implement the same catalog/store abstractions against your preferred backend. diff --git a/src/Startup/CrestApps.Core.Mvc.Web/Services/YesSqlServiceCollectionExtensions.cs b/src/Startup/CrestApps.Core.Mvc.Web/Services/YesSqlServiceCollectionExtensions.cs index 95c963dd..c8e89fa8 100644 --- a/src/Startup/CrestApps.Core.Mvc.Web/Services/YesSqlServiceCollectionExtensions.cs +++ b/src/Startup/CrestApps.Core.Mvc.Web/Services/YesSqlServiceCollectionExtensions.cs @@ -66,13 +66,13 @@ public static IServiceCollection AddCoreYesSqlDataStore(this IServiceCollection Data.YesSql.ServiceCollectionExtensions.AddCoreYesSqlDataStore(services, configuration => configuration.UseSqLite(connectionStringBuilder.ToString()).SetTablePrefix("CA_")); // YesSql-backed catalogs and managers. - services.AddNamedSourceDocumentCatalog() - .AddNamedSourceDocumentCatalog() - .AddDocumentCatalog() - .AddSourceDocumentCatalog() - .AddNamedDocumentCatalog() - .AddSourceDocumentCatalog() - .AddNamedSourceDocumentCatalog() + services.AddYesSqlNamedSourceDocumentCatalog() + .AddYesSqlNamedSourceDocumentCatalog() + .AddYesSqlDocumentCatalog() + .AddYesSqlSourceDocumentCatalog() + .AddYesSqlNamedDocumentCatalog() + .AddYesSqlSourceDocumentCatalog() + .AddYesSqlNamedSourceDocumentCatalog() .AddScoped() .AddScoped(sp => sp.GetRequiredService()) .AddScoped>(sp => sp.GetRequiredService()) @@ -105,18 +105,18 @@ public static IServiceCollection AddCoreYesSqlDataStore(this IServiceCollection .AddScoped() .AddScoped() .AddScoped() - .AddDocumentCatalog() + .AddYesSqlDocumentCatalog() .AddScoped() - .AddDocumentCatalog() + .AddYesSqlDocumentCatalog() .AddScoped, AIDataSourceIndexingHandler>() .AddScoped, ArticleIndexingHandler>() .AddScoped(); services.AddKeyedScoped, NamedSourceDocumentCatalog>(ConfigurationAIProviderConnectionCatalog.PersistedCatalogKey) - .AddNamedSourceDocumentCatalog(); + .AddYesSqlNamedSourceDocumentCatalog(); services.AddKeyedScoped, NamedSourceDocumentCatalog>(ConfigurationAIDeploymentCatalog.PersistedCatalogKey) - .AddNamedSourceDocumentCatalog(); + .AddYesSqlNamedSourceDocumentCatalog(); return services; } diff --git a/src/Stores/CrestApps.Core.Data.EntityCore/ServiceCollectionExtensions.cs b/src/Stores/CrestApps.Core.Data.EntityCore/ServiceCollectionExtensions.cs index ace44bee..4b5196f1 100644 --- a/src/Stores/CrestApps.Core.Data.EntityCore/ServiceCollectionExtensions.cs +++ b/src/Stores/CrestApps.Core.Data.EntityCore/ServiceCollectionExtensions.cs @@ -2,19 +2,18 @@ using CrestApps.Core.AI.A2A.Models; using CrestApps.Core.AI.Chat; using CrestApps.Core.AI.DataSources; -using CrestApps.Core.AI.Mcp.Models; using CrestApps.Core.AI.Memory; +using CrestApps.Core.AI.Mcp.Models; using CrestApps.Core.AI.Models; using CrestApps.Core.AI.Services; +using CrestApps.Core; using CrestApps.Core.Builders; using CrestApps.Core.Data.EntityCore.Services; using CrestApps.Core.Infrastructure.Indexing; using CrestApps.Core.Infrastructure.Indexing.Models; -using CrestApps.Core.Models; using CrestApps.Core.Services; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; namespace CrestApps.Core.Data.EntityCore; @@ -24,146 +23,39 @@ public static IServiceCollection AddCoreEntityCoreDataStore(this IServiceCollect { ArgumentNullException.ThrowIfNull(services); ArgumentNullException.ThrowIfNull(configure); + services.AddOptions(); + if (configureStore is not null) { services.Configure(configureStore); } services.AddDbContext(configure); + return services; } public static IServiceCollection AddCoreEntityCoreSqliteDataStore(this IServiceCollection services, string connectionString, string tablePrefix = "CA_") { ArgumentException.ThrowIfNullOrEmpty(connectionString); - return services.AddCoreEntityCoreDataStore(options => options.UseSqlite(connectionString), store => store.TablePrefix = tablePrefix); - } - - public static IServiceCollection AddDocumentCatalogs(this IServiceCollection services) - { - services.TryAddScoped(typeof(ICatalog<>), typeof(DocumentCatalog<>)); - services.TryAddScoped(typeof(INamedCatalog<>), typeof(NamedDocumentCatalog<>)); - services.TryAddScoped(typeof(ISourceCatalog<>), typeof(SourceDocumentCatalog<>)); - services.TryAddScoped(typeof(INamedSourceCatalog<>), typeof(NamedSourceDocumentCatalog<>)); - - return services; - } - - public static IServiceCollection AddDocumentCatalog(this IServiceCollection services) - where TModel : CatalogItem - { - services.RemoveAll>(); - services.AddScoped, DocumentCatalog>(); - return services; - } - - public static IServiceCollection AddNamedDocumentCatalog(this IServiceCollection services) - where TModel : CatalogItem, INameAwareModel - { - services.RemoveAll>(); - services.RemoveAll>(); - services.AddScoped, NamedDocumentCatalog>(); - services.AddScoped>(sp => (INamedCatalog)sp.GetRequiredService>()); - return services; - } - - public static IServiceCollection AddSourceDocumentCatalog(this IServiceCollection services) - where TModel : CatalogItem, ISourceAwareModel - { - services.RemoveAll>(); - services.RemoveAll>(); - services.AddScoped, SourceDocumentCatalog>(); - services.AddScoped>(sp => (ISourceCatalog)sp.GetRequiredService>()); - return services; - } - public static IServiceCollection AddNamedSourceDocumentCatalog(this IServiceCollection services) - where TModel : CatalogItem, INameAwareModel, ISourceAwareModel - { - services.RemoveAll>(); - services.RemoveAll>(); - services.RemoveAll>(); - services.RemoveAll>(); - services.AddScoped, NamedSourceDocumentCatalog>(); - services.AddScoped>(sp => (INamedCatalog)sp.GetRequiredService>()); - services.AddScoped>(sp => (ISourceCatalog)sp.GetRequiredService>()); - services.AddScoped>(sp => (INamedSourceCatalog)sp.GetRequiredService>()); - return services; - } - - public static IServiceCollection AddDocumentCatalog(this IServiceCollection services, string collection = null) - where TModel : CatalogItem - where T : class, ICatalog - { - _ = collection; - - services.RemoveAll>(); - services.AddScoped(); - services.AddScoped>(sp => sp.GetRequiredService()); - return services; - } - - public static IServiceCollection AddNamedDocumentCatalog(this IServiceCollection services, string collection = null) - where TModel : CatalogItem, INameAwareModel - where T : class, INamedCatalog - { - _ = collection; - - services.RemoveAll>(); - services.RemoveAll>(); - services.AddScoped(); - services.AddScoped>(sp => sp.GetRequiredService()); - services.AddScoped>(sp => sp.GetRequiredService()); - return services; - } - - public static IServiceCollection AddSourceDocumentCatalog(this IServiceCollection services, string collection = null) - where TModel : CatalogItem, ISourceAwareModel - where T : class, ISourceCatalog - { - _ = collection; - - services.RemoveAll>(); - services.RemoveAll>(); - services.AddScoped(); - services.AddScoped>(sp => sp.GetRequiredService()); - services.AddScoped>(sp => sp.GetRequiredService()); - return services; - } - - public static IServiceCollection AddNamedSourceDocumentCatalog(this IServiceCollection services, string collection = null) - where TModel : CatalogItem, INameAwareModel, ISourceAwareModel - where T : class, INamedSourceCatalog - { - _ = collection; - - services.RemoveAll>(); - services.RemoveAll>(); - services.RemoveAll>(); - services.RemoveAll>(); - services.AddScoped(); - services.AddScoped>(sp => sp.GetRequiredService()); - services.AddScoped>(sp => sp.GetRequiredService()); - services.AddScoped>(sp => sp.GetRequiredService()); - services.AddScoped>(sp => sp.GetRequiredService()); - - return services; + return services.AddCoreEntityCoreDataStore(options => options.UseSqlite(connectionString), store => store.TablePrefix = tablePrefix); } - public static IServiceCollection AddCoreEntityCoreStores(this IServiceCollection services) + public static IServiceCollection AddEntityCoreStores(this IServiceCollection services) { - services.AddCatalogManagers(); + services + .AddCatalogManagers(); // Catalog registrations - services.AddNamedSourceDocumentCatalog(); - services.AddNamedSourceDocumentCatalog(); - services.AddDocumentCatalog(); - services.AddSourceDocumentCatalog(); - services.AddNamedDocumentCatalog(); - services.AddSourceDocumentCatalog(); - services.AddNamedSourceDocumentCatalog(); - services.AddDocumentCatalog(); + services.AddNamedSourceDocumentCatalog>(); + services.AddDocumentCatalog>(); + services.AddSourceDocumentCatalog>(); + services.AddNamedDocumentCatalog>(); + services.AddSourceDocumentCatalog>(); + services.AddNamedSourceDocumentCatalog>(); + services.AddDocumentCatalog>(); // Chat session stores services.AddScoped(); @@ -191,10 +83,10 @@ public static IServiceCollection AddCoreEntityCoreStores(this IServiceCollection services.AddScoped>(sp => sp.GetRequiredService()); services.AddKeyedScoped, NamedSourceDocumentCatalog>(ConfigurationAIProviderConnectionCatalog.PersistedCatalogKey); - services.AddNamedSourceDocumentCatalog(); + services.AddNamedSourceDocumentCatalog(); services.AddKeyedScoped, NamedSourceDocumentCatalog>(ConfigurationAIDeploymentCatalog.PersistedCatalogKey); - services.AddNamedSourceDocumentCatalog(); + services.AddNamedSourceDocumentCatalog(); return services; } diff --git a/src/Stores/CrestApps.Core.Data.YesSql/ServiceCollectionExtensions.cs b/src/Stores/CrestApps.Core.Data.YesSql/ServiceCollectionExtensions.cs index ed4f14c7..96c8f37a 100644 --- a/src/Stores/CrestApps.Core.Data.YesSql/ServiceCollectionExtensions.cs +++ b/src/Stores/CrestApps.Core.Data.YesSql/ServiceCollectionExtensions.cs @@ -29,7 +29,7 @@ public static CrestAppsCoreBuilder AddYesSqlDataStore(this CrestAppsCoreBuilder return builder; } - public static IServiceCollection AddDocumentCatalogs(this IServiceCollection services) + public static IServiceCollection AddYesSqlDocumentCatalogs(this IServiceCollection services) { services.TryAddScoped(typeof(ICatalog<>), typeof(DocumentCatalog<,>)); services.TryAddScoped(typeof(INamedCatalog<>), typeof(NamedDocumentCatalog<,>)); @@ -39,7 +39,7 @@ public static IServiceCollection AddDocumentCatalogs(this IServiceCollection ser return services; } - public static IServiceCollection AddDocumentCatalog(this IServiceCollection services, string collection = null) + public static IServiceCollection AddYesSqlDocumentCatalog(this IServiceCollection services, string collection = null) where TModel : CatalogItem where TIndex : CatalogItemIndex { @@ -54,7 +54,7 @@ public static IServiceCollection AddDocumentCatalog(this IServic return services; } - public static IServiceCollection AddNamedDocumentCatalog(this IServiceCollection services, string collection = null) + public static IServiceCollection AddYesSqlNamedDocumentCatalog(this IServiceCollection services, string collection = null) where TModel : CatalogItem, INameAwareModel where TIndex : CatalogItemIndex, INameAwareIndex { @@ -73,7 +73,7 @@ public static IServiceCollection AddNamedDocumentCatalog(this IS return services; } - public static IServiceCollection AddSourceDocumentCatalog(this IServiceCollection services, string collection = null) + public static IServiceCollection AddYesSqlSourceDocumentCatalog(this IServiceCollection services, string collection = null) where TModel : CatalogItem, ISourceAwareModel where TIndex : CatalogItemIndex, ISourceAwareIndex { @@ -92,7 +92,7 @@ public static IServiceCollection AddSourceDocumentCatalog(this I return services; } - public static IServiceCollection AddNamedSourceDocumentCatalog(this IServiceCollection services, string collection = null) + public static IServiceCollection AddYesSqlNamedSourceDocumentCatalog(this IServiceCollection services, string collection = null) where TModel : CatalogItem, INameAwareModel, ISourceAwareModel where TIndex : CatalogItemIndex, INameAwareIndex, ISourceAwareIndex { @@ -115,64 +115,73 @@ public static IServiceCollection AddNamedSourceDocumentCatalog(t return services; } - public static IServiceCollection AddDocumentCatalog(this IServiceCollection services, string collection = null) - where TModel : CatalogItem - where TIndex : CatalogItemIndex - where T : class, ICatalog + public static IServiceCollection AddYesSqlNamedDocumentCatalog(this IServiceCollection services) + where TModel : CatalogItem, INameAwareModel + where TIndex : CatalogItemIndex, INameAwareIndex + where TService : class, ICatalog { - services.RemoveAll>(); + services + .RemoveAll>(); + + services.TryAddScoped(); - services.AddScoped(); - services.AddScoped>(sp => sp.GetRequiredService()); + services + .AddScoped>(sp => sp.GetRequiredService()); return services; } - public static IServiceCollection AddNamedDocumentCatalog(this IServiceCollection services) - where TModel : CatalogItem, INameAwareModel - where TIndex : CatalogItemIndex, INameAwareIndex - where T : class, INamedCatalog + public static IServiceCollection AddYesSqlDocumentCatalog(this IServiceCollection services) + where TModel : CatalogItem + where TIndex : CatalogItemIndex + where TService : class, ICatalog { - services.RemoveAll>(); - services.RemoveAll>(); + services + .RemoveAll>(); + + services.TryAddScoped(); - services.AddScoped(); - services.AddScoped>(sp => sp.GetRequiredService()); - services.AddScoped>(sp => sp.GetRequiredService()); + services.AddScoped>(sp => sp.GetRequiredService()); return services; } - public static IServiceCollection AddSourceDocumentCatalog(this IServiceCollection services) + public static IServiceCollection AddYesSqlSourceDocumentCatalog(this IServiceCollection services) where TModel : CatalogItem, ISourceAwareModel where TIndex : CatalogItemIndex, ISourceAwareIndex - where T : class, ISourceCatalog + where TService : class, ISourceCatalog { - services.RemoveAll>(); - services.RemoveAll>(); + services + .RemoveAll>() + .RemoveAll>(); + + services.TryAddScoped(); - services.AddScoped(); - services.AddScoped>(sp => sp.GetRequiredService()); - services.AddScoped>(sp => sp.GetRequiredService()); + services + .AddScoped>(sp => sp.GetRequiredService()) + .AddScoped>(sp => sp.GetRequiredService()); return services; } - public static IServiceCollection AddNamedSourceDocumentCatalog(this IServiceCollection services) + public static IServiceCollection AddYesSqlNamedSourceDocumentCatalog(this IServiceCollection services) where TModel : CatalogItem, INameAwareModel, ISourceAwareModel where TIndex : CatalogItemIndex, INameAwareIndex, ISourceAwareIndex - where T : class, INamedSourceCatalog + where TService : class, INamedSourceCatalog { - services.RemoveAll>(); - services.RemoveAll>(); - services.RemoveAll>(); - services.RemoveAll>(); - - services.AddScoped(); - services.AddScoped>(sp => sp.GetRequiredService()); - services.AddScoped>(sp => sp.GetRequiredService()); - services.AddScoped>(sp => sp.GetRequiredService()); - services.AddScoped>(sp => sp.GetRequiredService()); + services + .RemoveAll>() + .RemoveAll>() + .RemoveAll>() + .RemoveAll>(); + + services.TryAddScoped(); + + services + .AddScoped>(sp => sp.GetRequiredService()) + .AddScoped>(sp => sp.GetRequiredService()) + .AddScoped>(sp => sp.GetRequiredService()) + .AddScoped>(sp => sp.GetRequiredService()); return services; } diff --git a/tests/CrestApps.Core.Tests/EntityCoreStoreTests.cs b/tests/CrestApps.Core.Tests/EntityCoreStoreTests.cs index 5f7bcf6a..10ec86b4 100644 --- a/tests/CrestApps.Core.Tests/EntityCoreStoreTests.cs +++ b/tests/CrestApps.Core.Tests/EntityCoreStoreTests.cs @@ -211,7 +211,7 @@ public static async Task CreateAsync() services.AddHttpContextAccessor(); services.AddSingleton(TimeProvider.System); services.AddCoreEntityCoreSqliteDataStore($"Data Source={databasePath}"); - services.AddCoreEntityCoreStores(); + services.AddEntityCoreStores(); var provider = services.BuildServiceProvider(); await provider.InitializeEntityCoreSchemaAsync();