JonPSmith / EfCore.TestSupport

Tools for helping in unit testing applications that use Entity Framework Core
https://www.thereformedprogrammer.net/new-features-for-unit-testing-your-entity-framework-core-5-code/
Other
352 stars 53 forks source link

CreateEmptyViaWipe is throwing this error: LocalDB is not supported on this platform #5

Closed Alleno closed 6 years ago

Alleno commented 6 years ago

I am getting this error:

System.PlatformNotSupportedException : LocalDB is not supported on this platform.

from the CreateEmptyViaWipe method on my Linux development machine, or simply by using context.Database.EnsureCreated(). Is this a setting that can be changed in CreateUniqueClassOptions?

JonPSmith commented 6 years ago

Hi @Alleno

The CreateEmptyViaWipe method doesn't reference LocalDB (The DeleteAllUnitTestDatabases method does refer to localDB, which I need to fix). Can you try a EF Core-only approach to wiping the database and check that works first. The code would be

context.Database.EnsureDeleted();
context.Database.EnsureCreated();

If that works then I do have a problem, but I really can't see what it is.

PS. The error suggests that you are trying to use a database with Server=(localdb)\\mssqllocaldb; in your connection string, and its saying that LocalDB is not supported on Linux.

Alleno commented 6 years ago

I love your book btw, it's really well done!

On Thu, Mar 29, 2018, 3:35 AM Jon P Smith notifications@github.com wrote:

Hi @Alleno https://github.com/Alleno,

Yes, you are right. I needed a empty connection string and I foolishly assumed localdb. I will have a look and get back to you.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/JonPSmith/EfCore.TestSupport/issues/5#issuecomment-377149602, or mute the thread https://github.com/notifications/unsubscribe-auth/AJPK3j5YR9nT4_9Eea7IhaIzFqfXIlMgks5tjI7XgaJpZM4S_sWb .

JonPSmith commented 6 years ago

HI @Alleno,

I have fixed the DeleteAllUnitTestDatabases problem - which it turns out isn't related to your problem. Before I issue a new NuGet package I wanted to check if the EnsureDeleted/EnsureCreated approach has the same problem as CreateEmptyViaWipe?

If both methods fail then its because Linux doesn't support LocalDB. If the EnsureDeleted/EnsureCreated works I have a problem, but I have no idea what it is!

Alleno commented 6 years ago

Hi Jon,

EnsureCreated is also throwing the problem. You're right, linux apparently doesn't support localdb. I guess I need to specify a different connection string in my appsettings.json? Is there a default connection string name (is it "DefaultConnection"?) that CreateUniqueClassOptions uses?

Best,

Allen

On Sat, Mar 31, 2018 at 4:57 AM, Jon P Smith notifications@github.com wrote:

HI @Alleno https://github.com/Alleno,

I have fixed the DeleteAllUnitTestDatabases problem - which it turns out isn't related to your problem. Before I issue a new NuGet package I wanted to check if the EnsureDeleted/EnsureCreated approach has the same problem as CreateEmptyViaWipe?

If both methods fail then its because Linux doesn't support LocalDB. If the EnsureDeleted/EnsureCreated works I have a problem, but I have no idea what it is!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/JonPSmith/EfCore.TestSupport/issues/5#issuecomment-377678146, or mute the thread https://github.com/notifications/unsubscribe-auth/AJPK3sCmHEyTY1gQfQB07hL0OfdjNDSqks5tj0USgaJpZM4S_sWb .

JonPSmith commented 6 years ago

Hi @Alleno,

OK, that is what I thought it would be, but I wanted to check. Yes, you will need to use some sort of server on Linux (LocalDB is a specialised SQL Server that Visual Studio installs on Windows). You should use database server are you using in your application.

The appsettings.json file needs a connection string called UnitTestConnection, which CreateUniqueClassOptions and other methods use. (see the note in the Wiki that the database name must end with Test - its a safety measure).

If you are just playing around you might like to use the in-memory SQLite database, as you don't need to install anything. I created an ASP.NET Core test application using an in-memory database, and it works well. Ping me if that might be useful and I can give you the code.

JonPSmith commented 6 years ago

PS. Thanks for your comments on the book. I'm currently working with Manning's production people to get it to print - it has 21 steps in that process!!

Alleno commented 6 years ago

Could you share your test application code? It would be helpful to see something that works. I've been having some trouble with the SQLite database and async methods. I'm pretty new to this, so it's probably something obvious I'm overlooking.

Thanks for your help,

Allen

On Sat, Mar 31, 2018 at 10:47 AM, Jon P Smith notifications@github.com wrote:

PS. Thanks for your comments on the book. I'm currently working with Manning's production people to get it to print - it has 21 steps in that process!!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/JonPSmith/EfCore.TestSupport/issues/5#issuecomment-377698087, or mute the thread https://github.com/notifications/unsubscribe-auth/AJPK3imAogLRu0og87o0b0RRvJ2dqE0zks5tj5cbgaJpZM4S_sWb .

JonPSmith commented 6 years ago

Hi @Alleno,

Not problem. First, I suggest you use the SQLiteInMemory.CreateOptions<T> method to try things out. (See listing 15.8 in chapter 15 of my book). That produces an empty database every time the unit test runs.

Here is the code to create an in-memory SQLite database in ASP.NET Core.

var connectionStringBuilder = new SqliteConnectionStringBuilder { DataSource = ":memory:" };
var connectionString = connectionStringBuilder.ToString();
var connection = new SqliteConnection(connectionString);
connection.Open();  //see https://github.com/aspnet/EntityFramework/issues/6968
services.AddDbContext<EfCoreContext>(options => options.UseSqlite(connection));

You do need to apply the context.Database.EnsureCreated and seed the database on startup. I use the process I show in my book in listing 5.9, and here is the code that goes instead of the .MigrateDatabase() line in listing 5.9.

public static class DatabaseStartupHelpers
{

    private static readonly string WwwRootDirectory = $"wwwroot{Path.DirectorySeparatorChar}";

    public static string GetWwwRootPath()
    {
        return Path.Combine(Directory.GetCurrentDirectory(), WwwRootDirectory);
    }

    public static IWebHost SetupDevelopmentDatabase(this IWebHost webHost)
    {
        using (var scope = webHost.Services.CreateScope())
        {
            var services = scope.ServiceProvider;
            using (var context = services.GetRequiredService<EfCoreContext>())
            {
                try
                {
                    context.DevelopmentEnsureCreated(); //This just calls Database.EnsureCreated
                    context.SeedDatabase(GetWwwRootPath());
                }
                catch (Exception ex)
                {
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "An error occurred while setting up or seeding the development database.");
                }
            }
        }

        return webHost;
    }
}

The method context.SeedDatabase(GetWwwRootPath()); reads in a json file from the root directory, but you could just call a method that generates some basic content in your database. Of course, every time you stop/restart the database it will rerun this and give you a fresh database.

Alleno commented 6 years ago

Hi Jon,

Thanks for the code, I got things to work with the sqllite inmemory database. :)

Good luck on finishing your book, I'll try and leave an Amazon review once it's out,

Allen

On Sat, Mar 31, 2018 at 2:37 PM, Jon P Smith notifications@github.com wrote:

Hi @Alleno https://github.com/Alleno,

Not problem. First, I suggest you use the SQLiteInMemory.CreateOptions method to try things out. (See listing 15.8 in chapter 15 of my book http://bit.ly/2m8KRAZ). That produces an empty database every time the unit test runs.

Here is the code to create an in-memory SQLite database in ASP.NET Core.

var connectionStringBuilder = new SqliteConnectionStringBuilder { DataSource = ":memory:" };var connectionString = connectionStringBuilder.ToString();var connection = new SqliteConnection(connectionString);connection.Open(); //see https://github.com/aspnet/EntityFramework/issues/6968services.AddDbContext(options => options.UseSqlite(connection));

You do need to apply the context.Database.EnsureCreated and seed the database on startup. I use the process I show in my book in listing 5.9, and here is the code that goes instead of the .MigrateDatabase() line in listing 5.9.

public static class DatabaseStartupHelpers {

private static readonly string WwwRootDirectory = $"wwwroot{Path.DirectorySeparatorChar}";

public static string GetWwwRootPath()
{
    return Path.Combine(Directory.GetCurrentDirectory(), WwwRootDirectory);
}

public static IWebHost SetupDevelopmentDatabase(this IWebHost webHost)
{
    using (var scope = webHost.Services.CreateScope())
    {
        var services = scope.ServiceProvider;
        using (var context = services.GetRequiredService<EfCoreContext>())
        {
            try
            {
                context.DevelopmentEnsureCreated();
                context.SeedDatabase(GetWwwRootPath());
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred while setting up or seeding the development database.");
            }
        }
    }

    return webHost;
}

}

The method context.SeedDatabase(GetWwwRootPath()); reads in a json file from the root directory, but you could just call a method that generates some basic content in your database. Of course, every time you stop/restart the database it will rerun this and give you a fresh database.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/JonPSmith/EfCore.TestSupport/issues/5#issuecomment-377714068, or mute the thread https://github.com/notifications/unsubscribe-auth/AJPK3jLNmxCs-ZmK8wQKlfCSCMC0avbXks5tj80GgaJpZM4S_sWb .