efcore: Migrate does not create initial database with tables

Create a net core 5 console application CoreMigration. Add the following nuget packages version 5.0.12 where appropriate:

Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore.Design Microsoft.EntityFrameworkCore.Tools Microsoft.EntityFrameworkCore.Sqlite Microsoft.EntityFrameworkCore.Sqlite.Design Microsoft.EntityFrameworkCore.SqlServer

Add the files shown below. Then open command prompt where dotnet is available and execute commands to generate migrations:

dotnet-ef migrations add InitialCreate --project CoreMigration --context SqliteGtContext --output-dir Migrations/Sqlite

dotnet-ef migrations add InitialCreate --project CoreMigration --context MsSqlGtContext --output-dir Migrations/MsSql

You can then run program, and it will create a sqlite database with only migrations table. I think this is a bug, from what I have read about Migrate I thought this would produce the database I needed. I know EnsureCreated work but it does not produce a database that can be migrated. If this is not a bug what am I doing wrong?

Program.cs

using System;
using System.IO;
using System.Linq;


using Microsoft.EntityFrameworkCore;

namespace CoreMigration
{
    public enum DatabaseType
    {
        Unknown = 0,
        MsSql,
        SQLite
    }

    public enum DatabaseOperation
    {
        Create,
        Migrate
    }

    internal class Program
    {
        private static DatabaseOperation DatabaseOperation
        { get; set; }


        private static DatabaseType DatabaseType
        { get; set; }


        private static void Main ()
        {
            DatabaseOperation = DatabaseOperation.Create;

            DatabaseType = DatabaseType.SQLite;

            string connStr = null;

            if ( DatabaseType == DatabaseType.SQLite )
                connStr = GtContextFactory.SqliteConnString;
            else
                connStr = GtContextFactory.MsSqlConnString;


            if ( connStr == null )
                throw new InvalidOperationException ( "No connection string" );




            using ( var context = GtContextFactory.Create ( connStr ) )
            {

                if ( DatabaseOperation == DatabaseOperation.Create )
                    Create ( context );
                else
                    Migrate ( context );
            }
        }

        private static void Migrate ( GtContext context )
        {

            context.Database.Migrate ();
        }

        private static void Create ( GtContext context )
        {
            if ( DatabaseType == DatabaseType.SQLite )
            {
                var dbPath = GtContextFactory.DbPath;
                if ( File.Exists ( dbPath ) )
                    File.Delete ( dbPath );
            }

            context.Database.Migrate ();

            Console.WriteLine ( "Inserting a new blog" );

            var blog = new Blog ();
            blog.Url = "https://foo.com/MyBlog";

            blog.Posts.Add (
                new Post { Title = "First Entry", Content = "Today is Foo day!" } );


            blog.Posts.Add (
                new Post { Title = "Second Entry", Content = "Today is NOT Foo day!" } );


            context.Blogs.Add ( blog );
            context.SaveChanges ();

            blog = null;

            // Read
            Console.WriteLine ( "Querying for a blog" );
            blog = context.Blogs.
                        Include ( c => c.Posts )
                .OrderBy ( b => b.BlogId )
                .First ();

        }
    }
}

GtContext.cs

using System;
using System.Collections.Generic;
using System.Linq;


using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.SqlServer;



namespace CoreMigration
{
    public partial class GtContext : DbContext
    {
        public GtContext ()
        {}


        public GtContext ( DbContextOptions<GtContext> options, bool supportsSchema ) :
            base ( options )
        {
            SupportsSchema = supportsSchema;
            OnCreated ();
        }

        protected GtContext ( DbContextOptions options ) : 
            base ( options )
        {
        }


        public bool SupportsSchema
        { get; set; }


        public DatabaseType DatabaseType
        { get; set; }




        protected override void OnConfiguring ( DbContextOptionsBuilder optionsBuilder )
        {
            CustomizeConfiguration ( ref optionsBuilder );

            optionsBuilder.EnableSensitiveDataLogging ( true );

            base.OnConfiguring ( optionsBuilder );
        }

        partial void CustomizeConfiguration ( ref DbContextOptionsBuilder optionsBuilder );

        partial void OnConfiguring ( ref DbContextOptionsBuilder optionsBuilder );

        protected override void OnModelCreating ( ModelBuilder modelBuilder )
        {
            if ( SupportsSchema )
                modelBuilder.HasDefaultSchema ( "FOO" );


        }

        partial void OnCreated ();


        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }


    }
}

GtContextFactory.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Common;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;

using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.SqlServer;



namespace CoreMigration
{
    public static class GtContextFactory
    {
        #region Constants


        public const string DbPath = @"C:\Repository\CoreMigration\CoreMigrationMs\bin\Debug\Blog.db3";

        public const string MsSqlConnString = @"Data Source=localhost;Initial Catalog=Blog;Integrated Security=False;Persist Security Info=True;User ID=sa;Password=foo";
        public const string SqliteConnString = @"Data Source=C:\Repository\CoreMigrationMs\CoreMigration\bin\Debug\Blog.db3";

        public const string MigrateMsSqlConnString = @"Data Source=localhost;Initial Catalog=;Integrated Security=False;Persist Security Info=True;User ID=sa;Password=foo";
        public const string MigrateSqliteConnString = @"Data Source=";

        #endregion

        #region Create Methods

        public static DatabaseType GetDatabaseType ( string connStr )
        {
            if ( string.IsNullOrEmpty ( connStr ) )
                return DatabaseType.Unknown;

            if ( connStr.Contains ( "Initial Catalog" ) )
                return DatabaseType.MsSql;
            else if ( connStr.Contains ( "Data Source" ) )
                return DatabaseType.SQLite;

            return DatabaseType.Unknown;
        }



        public static GtContext Create ( string connStr )
        {
            if ( string.IsNullOrEmpty ( connStr ) )
                throw new InvalidOperationException ( "connection string is required" );

            var optionsBuilder = new DbContextOptionsBuilder<GtContext> ();
            if ( optionsBuilder == null )
                throw new NullReferenceException ( "Failed to create db context options builder" );

            var supportsSchema = true;
            var databaseType = GetDatabaseType ( connStr );

            switch ( databaseType )
            {

                case DatabaseType.MsSql:
                    {
                        optionsBuilder.UseSqlServer ( connStr, b => b.MigrationsAssembly ( Assembly.GetExecutingAssembly ().GetName ().Name ) );
                        break;

                    }

                case DatabaseType.SQLite:
                    {
                        optionsBuilder.UseSqlite ( connStr, b => b.MigrationsAssembly ( Assembly.GetExecutingAssembly ().GetName ().Name ) );

                        break;

                    }


            }

            var context = new GtContext ( optionsBuilder.Options, supportsSchema ) { DatabaseType = databaseType };
            if ( context == null )
                throw new NullReferenceException ( "Failed to create context" );


            return context;
        }





        #endregion

    }
}

Model.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CoreMigration
{
    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }

        public List<Post> Posts { get; } = new List<Post>();


        public override string ToString ()
        {
            return "BlogId: " + BlogId + " Url: " + Url;
        }


    }

    public class Post
    {
        public int PostId { get; set; }

        public string Title { get; set; }
        public string Content { get; set; }


        public int BlogId { get; set; }
        public Blog Blog { get; set; }


        public override string ToString ()
        {
            return "PostId: " + PostId + " Title: " + Title + " Content: " + Content;
        }
    }

}

MsSqlGtContext.cs

using System;
using System.Collections.Generic;
using System.Linq;


using Microsoft.EntityFrameworkCore;

namespace CoreMigration
{
    class MsSqlGtContext : GtContext
    {
        public MsSqlGtContext ()
        { }


        public MsSqlGtContext ( DbContextOptions<MsSqlGtContext> options ) :
            base ( options )
        {}

        protected override void OnConfiguring ( DbContextOptionsBuilder options )
        {
            options.UseSqlServer ( GtContextFactory.MigrateMsSqlConnString );
        }



    }
}

SqliteGtContext.cs

using System;
using System.Collections.Generic;
using System.Linq;

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Sqlite;


namespace CoreMigration
{
    class SqliteGtContext : GtContext
    {
        public SqliteGtContext () 
        {}


        public SqliteGtContext ( DbContextOptions<SqliteGtContext> options ) : 
            base ( options )
        {}


        protected override void OnConfiguring ( DbContextOptionsBuilder options )
        {
            options.UseSqlite ( GtContextFactory.MigrateSqliteConnString );
        }



    }
}

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 19 (4 by maintainers)

Most upvoted comments

CoreMigrationMs.zip

I wanted to leave a working migration example in case anyone stumbles across this link. CoreData is the model for the project and CoreMigration has the code to do migrations in code. CoreData has one GtContext derived context for each provider, and there is a design time factory to construct the appropriate context the command line is using.