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

Better experience/support for migrations in class library #3879

Closed
f0rt opened this issue Nov 24, 2015 · 9 comments
Closed

Better experience/support for migrations in class library #3879

f0rt opened this issue Nov 24, 2015 · 9 comments
Assignees
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Milestone

Comments

@f0rt
Copy link

f0rt commented Nov 24, 2015

Hi team,
I'm trying to create a library project(Data) that contains DBContext consumed by ASP.NET 5 application and Console Application (package). I have this definitions in my project.json:
"commands": {
"ef": "EntityFramework.Commands"
},
"dependencies": {
"EntityFramework.Commands": "7.0.0-rc1-final",
"EntityFramework.Core": "7.0.0-rc1-final",
"EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
"Microsoft.AspNet.Identity.EntityFramework": "3.0.0-rc1-final",
"SonarFish.Configuration": "1.0.0-*",
"System.Runtime.Serialization.Primitives": "4.1.0-beta-23516"
}

When I run "dnx ef migrations add m1" on my Data project I'm getting the error:
"System.InvalidOperationException: No database providers are configured. Configure a database provider by overriding OnConfiguring in your DbContext class or in the AddDbContext method when setting up services."

I've added the following implementation to OnConfiguring but the error is still the same:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("");
base.OnConfiguring(optionsBuilder);
}

What am I doing wrong?
What is the best way to implement if I have 2 projects that have to consume a single DBContext?

Thanks in advance! :)

@stevejgordon
Copy link

I managed to get this working although I am still facing issues after trying to change to the recommended dotnet5.4 framework naming. What frameworks are you targeting in project.json?

Have you added anything in your Startup.cs to handle setting up ef? I copied in the appsettings file from an MVC6 project (which contains the connection string) as well as adding the following in my startup.cs

public class Startup
{
    public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
    {
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json");

        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; set; }
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
    }

    public void Configure(IApplicationBuilder app)
    {
    }
}

After this I was able to use the commands correctly to add a migration and update the database.

@f0rt
Copy link
Author

f0rt commented Nov 25, 2015

Thanks for the reply @stevejgordon.

Q: What frameworks are you targeting in project.json?
A: dnxcore50. Is this the correct string or some of the VS templates are not updated?

Q: Have you added anything in your Startup.cs to handle setting up ef?
A: As I said I'm trying to create a library project to handle all DB operations. Should I add appsettings.json and Startup.cs to it?

@stevejgordon
Copy link

I'd seen that the new RC1 template for a Class Library (Package) defaults to dotnet5.4 which I understood throuhg limited reading was the new preferred naming to target the core platform. However I have just opened an issue on this since the EF libraries seemed not to like this. I'm currently targeting dnx46 and dnxcore50. So you should be okay there.

On the startup.cs front I understand that this is needed in the class library project also if you want to use the EF commands. The reason is that something needs to bootstrap the services in order to be able to run commands to the database. I suspect this isn't needed when you have a web project referencing the data class library since the startup there will bootstrap the required services and configuration.However you will need it for ef commands.

That's at least what I'e understood so far after a few days playing with it all. Certainly for now my DAL has an appsettings and startup.cs added in the root. App settings is only needed if you want to load the connection string from a settings file. You could of course hard code that directly in the startup.cs

@f0rt
Copy link
Author

f0rt commented Nov 25, 2015

Works like a charm!! Thank you again for your efforts. :)

@stevejgordon
Copy link

You're welcome.

@rowanmiller rowanmiller added this to the 7.0.0-rc2 milestone Dec 1, 2015
@rowanmiller rowanmiller changed the title Question: How to enable migrations in Class Library (Package) project. Better experience/support for migrations in class library Dec 2, 2015
@bricelam
Copy link
Contributor

bricelam commented Dec 3, 2015

Thoughts I've had on how to help this:

  • Override migrations assembly to the target project at design-time
  • Warn if it's different from the configured migrations assembly

@ryancole
Copy link

ryancole commented Dec 4, 2015

I tried following the suggestion in #3840, by @bricelam, but I don't think it's working how I expected. I've got the same configuration as the creator of #3840, with my DbContext defined in a seperate project within the same solution as my ASP.NET project. I adjusted the code, in the ASP.NET project's Startup.cs file, to call MigrationsAssembly in the ConfigureServices method. Here's that code ...

public void ConfigureServices(IServiceCollection services)
{
    var connection = @"Server=(localdb)\mssqllocaldb;Database=League;Trusted_Connection=True;";

    // register mvc server
    services.AddMvc();

    // register entity framework services
    services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<LeagueContext>(options =>
            {
                options.UseSqlServer(connection)
                       .MigrationsAssembly("League.Data");
            });
}

The assembly that has the DbContext is League.Data. This seems to be finding the assembly, because if I change it to something that doesn't exist, like League.Datafoo, it throws an error, but does not throw an error when using the correct name.

So, with this setup, if I change directories into the ASP.NET project's directory, here's the output of the various dnx ef commands ...

C:\Users\Ryan\Projects\League\League.Web>dnx ef dbcontext list
League.Data.Context.LeagueContext

C:\Users\Ryan\Projects\League\League.Web>dnx ef migrations add First
Done. To undo this action, use 'ef migrations remove'

C:\Users\Ryan\Projects\League\League.Web>dnx ef migrations list
No migrations were found

@bricelam
Copy link
Contributor

bricelam commented Dec 5, 2015

MigrationsAssembly Should point to the one with the Migration classes in it. That's League.Web in your usage above.

@ryancole
Copy link

ryancole commented Dec 6, 2015

Ah, that does it! Makes sense. 👍 Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Projects
None yet
Development

No branches or pull requests

6 participants