Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider adding AddInMemoryDatabase sugar #25487

Closed
ajcvickers opened this issue Aug 11, 2021 · 1 comment
Closed

Consider adding AddInMemoryDatabase sugar #25487

ajcvickers opened this issue Aug 11, 2021 · 1 comment
Labels
closed-out-of-scope This is not something that will be fixed/implemented and the issue is closed.

Comments

@ajcvickers
Copy link
Member

Split off from #25451.

Pros: Might be helpful when getting started.
Cons: Use of in-memory database is discouraged--see #18457

Implementation:

        /// <summary>
        ///     <para>
        ///         Registers the given Entity Framework <see cref="DbContext" /> as a service in the <see cref="IServiceCollection" />
        ///         and configures it to use the Entity Framework in-memory database.
        ///     </para>
        ///     <para>
        ///         This method is a shortcut for configuring a <see cref="DbContext" /> to use the in-memory database. It does not support
        ///         all options. Use <see cref="M:EntityFrameworkServiceCollectionExtensions.AddDbContext"/> and related methods for full
        ///         control of this process.
        ///     </para>
        ///     <para>
        ///         Use this method when using dependency injection in your application, such as with ASP.NET Core.
        ///         For applications that don't use dependency injection, consider creating <see cref="DbContext" />
        ///         instances directly with its constructor. The <see cref="DbContext.OnConfiguring" /> method can then be
        ///         overridden to configure the in-memory database provider.
        ///     </para>
        ///     <para>
        ///         To configure the <see cref="DbContextOptions{TContext}" /> for the context, either override the
        ///         <see cref="DbContext.OnConfiguring" /> method in your derived context, or supply 
        ///         an optional action to configure the <see cref="DbContextOptions" /> for the context. 
        ///     </para>
        ///     <para>
        ///         For more information on how to use this method, see the Entity Framework Core documentation at https://aka.ms/efdocs.
        ///         For more information on using dependency injection, see https://go.microsoft.com/fwlink/?LinkId=526890.
        ///     </para>
        /// </summary>
        /// <typeparam name="TContext"> The type of context to be registered. </typeparam>
        /// <param name="serviceCollection"> The <see cref="IServiceCollection" /> to add services to. </param>
        /// <param name="databaseName">
        ///     The name of the in-memory database. This allows the scope of the in-memory database to be controlled
        ///     independently of the context. The in-memory database is shared anywhere the same name is used.
        /// </param>
        /// <param name="inMemoryOptionsAction"> An optional action to allow additional in-memory database specific configuration. </param>
        /// <param name="optionsAction"> An optional action to configure the <see cref="DbContextOptions" /> for the context. </param>
        /// <returns> The same service collection so that multiple calls can be chained. </returns>
        public static IServiceCollection AddInMemoryDatabase<TContext>(
            this IServiceCollection serviceCollection,
            string databaseName,
            Action<InMemoryDbContextOptionsBuilder>? inMemoryOptionsAction = null,
            Action<DbContextOptionsBuilder>? optionsAction = null)
            where TContext : DbContext
        {
            Check.NotNull(serviceCollection, nameof(serviceCollection));
            Check.NotEmpty(databaseName, nameof(databaseName));

            return serviceCollection.AddDbContext<TContext>(
                (serviceProvider, options) =>
                {
                    optionsAction?.Invoke(options);
                    options.UseInMemoryDatabase(databaseName, inMemoryOptionsAction);
                });
        }

Test:

using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.InMemory.Infrastructure.Internal;
using Microsoft.Extensions.DependencyInjection;
using Xunit;

namespace Microsoft.EntityFrameworkCore
{
    public class InMemoryDbContextOptionsBuilderExtensionsTest
    {
        [ConditionalFact]
        public void Service_collection_extension_method_can_configure_InMemory_options()
        {
            var serviceCollection = new ServiceCollection();
            serviceCollection.AddInMemoryDatabase<ApplicationDbContext>(
                "Crunchie",
                inMemoryOptions =>
                {
                    inMemoryOptions.EnableNullabilityCheck(false);
                },
                dbContextOption =>
                {
                    dbContextOption.EnableDetailedErrors();
                });

            var services = serviceCollection.BuildServiceProvider(validateScopes: true);

            using (var serviceScope = services
                .GetRequiredService<IServiceScopeFactory>()
                .CreateScope())
            {
                var coreOptions = serviceScope.ServiceProvider
                    .GetRequiredService<DbContextOptions<ApplicationDbContext>>().GetExtension<CoreOptionsExtension>();

                Assert.True(coreOptions.DetailedErrorsEnabled);

                var inMemoryOptions = serviceScope.ServiceProvider
                    .GetRequiredService<DbContextOptions<ApplicationDbContext>>().GetExtension<InMemoryOptionsExtension>();

                Assert.False(inMemoryOptions.IsNullabilityCheckEnabled);
                Assert.Equal("Crunchie", inMemoryOptions.StoreName);
            }
        }

        private class ApplicationDbContext : DbContext
        {
            public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
                : base(options)
            {
            }
        }
    }
}
@ajcvickers
Copy link
Member Author

We recommend against using the in-memory provider for testing--see Testing EF Core Applications. While we have no plans to remove the in-memory provider, we will not be adding any new features to this provider because we believe valuable development time is better spent in other areas. When feasible, we plan to still fix regressions in existing behavior.

@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 26, 2022
@ajcvickers ajcvickers removed this from the Backlog milestone Oct 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-out-of-scope This is not something that will be fixed/implemented and the issue is closed.
Projects
None yet
Development

No branches or pull requests

1 participant