Tools: Support .NET Core Class Library projects #5320

Closed
natemcmaster opened this Issue May 10, 2016 · 40 comments

Projects

None yet
@natemcmaster
Member
natemcmaster commented May 10, 2016 edited

Add support for running "dotnet ef" on a .NET Standard and desktop .NET class library project.

This is blocked by dotnet/cli#2645 and/or dotnet/cli#4005 (depending on our implementation approach).

Short explanation

If you cannot do dotnet run, you also cannot use dotnet ef on your project.

More explanation

.NET Core, unlike .NET Framework, does not have a globally installed framework. All .NET Core apps need to reference an app framework (e.g. Microsoft.NETCore.App) in order to run. .NET Core class library projects are built without a framework, so dotnet-ef cannot run on these projects.

Workarounds

See https://docs.efproject.net/en/latest/miscellaneous/cli/dotnet.html#targeting-class-library-projects-is-not-supported for workarounds.

@rowanmiller rowanmiller added this to the 1.0.0 milestone May 13, 2016
@Kurira
Kurira commented May 19, 2016

Hi,

Just to be sure, we can't use EF within a class library project (aka tests project) in RC2?

@natemcmaster
Member

@Kurira you can use EF within a class library. You can't use EF .NET Core CLI commands on a class library. See https://docs.efproject.net/en/latest/cli/dotnet.html more info

@Kurira
Kurira commented May 19, 2016 edited

So I would use tools from my web project and apply them to test context which resides in test project?
Your link talks about transforming it into an app, but I always get System.IO.FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json, Version=7.0.0.0, even then used from web project template.

@kjbetz
kjbetz commented May 24, 2016

I need to test this more, but here is my solution that seems to be working: #5460 (comment)

@natemcmaster natemcmaster referenced this issue May 24, 2016
Closed

CLI Commands: usability improvements #5188

5 of 7 tasks complete
@ToddThomson

Is there a published workaround for this issue? I've added:

"frameworks": {
    "net451": {
        "buildOptions": {
            "emitEntryPoint": true
        }
    },
    "netcoreapp1.0": {
        "imports": [ "portable-net451+win8" ],
        "buildOptions": {
            "emitEntryPoint": true
        },
        "dependencies": {
            "Microsoft.NETCore.App": {
                "type": "platform",
                "version": "1.0.0-*"
            }
        }
    }
},

and a main() in program.cs, but I still get the "..Entity Framework tools does not support targeting class library projects.." message.

@natemcmaster
Member

@ToddThomson you are probably hitting dotnet/cli#3164. Try setting the top-level emitEntryPoint build option to true.

@ToddThomson

@natemcmaster Yes. That was it.

@rowanmiller
Member

When we have this implemented we need to verify that the right-click->Publish migrations feature works when the context/migrations is in a class library - I suspect it is not going to work by default because it will likely need to specify some of the target/startup project parameters.

@ToddThomson
ToddThomson commented May 26, 2016 edited

Additionally, if your DbContext takes a parameter then you also need to add a simple startup.cs to the class library. I added:

    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices( IServiceCollection services )
    {
        // Add Identity framework services.
        services.AddDbContext<SecurityDbContext>( options =>
             options.UseSqlServer( Configuration.GetConnectionString( "DefaultConnection" ) ) );

    }

This was sufficient for me to add an initial migration for Identity services.

@divega divega modified the milestone: 1.0.1, 1.0.0 Jun 10, 2016
@arthot arthot pushed a commit to arthot/weather-archive that referenced this issue Jun 11, 2016
arthot Upgrade DAL to RC2
Notes:
* Temporary converted to console, as dotnet doesn't support class library yet. See [issue](aspnet/EntityFramework#5320)
* Table names now named like DbSets
9772116
@HamidMosalla

@natemcmaster Any change in this regard in latest tooling preview 2?

@natemcmaster
Member

We are still blocked on .NET Core CLI support for this. dotnet/cli#2645.

Preview 2 added --startup-project which may mitigate the limitation for some project setups (#5680).

@arielcloud

Hi, where can i use this "--startup-project" to fix that?
I'm trying install EntityFrameworkCore.Tools on class library and get "Package Microsoft.EntityFrameworkCore.Tools 1.0.0-preview2-final is not compatible with netstandard1.6"
10x!

@natemcmaster
Member

@arielcloud did you upgrade your version of .NET Core CLI to preview 2?

@arielcloud

@natemcmaster i dont sure I have CLI at all.

I downloaded .net core by "Visual Studio users: The best way to develop with .NET Core on Windows is using Visual Studio. You will need Visual Studio 2015 Update 3 and then download the .NET Core for Visual Studio official MSI Installer"
https://www.microsoft.com/net/core#windows

where can i see if i have CLI and it's version? 10x!

@natemcmaster
Member

@arielcloud execute dotnet.exe --version from the command line. Also, Microsoft.EntityFrameworkCore.Tools only supports "netcoreapp1.0". It cannot be installed into a class library. https://docs.efproject.net/en/latest/miscellaneous/cli/dotnet.html#targeting-class-library-projects-is-not-supported

@natemcmaster natemcmaster changed the title from CLI Commands: support targeting .NET Core class projects to CLI Commands: support targeting .NET Core class library projects Jun 29, 2016
@natemcmaster
Member

I've had lots of questions about this, so I've updated the original issue description above to provide a little more explanation about why this feature is blocked and how you can workaround it.

FWIW this is feature is not simple to fix. Class libraries are not "runnable" by design (i.e. that's what it means to be a library, not an app). dotnet-ef needs to run the code to inspect the model and migrations, which is why it requires the target project be "runnable". See dotnet/cli#2645 (comment)

@bjcull
bjcull commented Jun 29, 2016

I've written up how I worked around the issue for anyone who is curious. It's based on the link given in the OP, but with a couple of tweaks based on experience from my real life project.
http://benjii.me/2016/05/dotnet-ef-migrations-for-asp-net-core/

@arielcloud

@natemcmaster my version is 1.0.0-preview2-003121.
@bjcull please add create date / update date to your great blogs :)
i'll try use those workarounds. 10x!

@arielcloud

Works great, except that Resharper mark most of classLibrary-EF code in red... i noted them

@kjbetz
kjbetz commented Jun 30, 2016

Is there a problem with the way I went about doing this? #5460 (comment)

Seems to work pretty well. Migrations are in my Api project... but everything else is in the class library and class library doesn't have to be turned into an app.

@rowanmiller rowanmiller removed the pri0 label Jul 6, 2016
@pettechbytes

I'm hoping I have this wrong, but with EF6, I could have my DbContext in a separate class library from my ASP.NET MVC project and create migrations in my DbContext class library. Am I reading correctly that I can no longer do this? If this is the case, where do I go from here? Back to .NET 4.6/MVC5/EF6?

@jonsagara

Works for me. Lets say I have two assemblies:

  • MyProject, which contains ASP.NET MVC
  • MyProject.Entities, which contains DbContext and migrations

When working with dotnet, to add a migration, I just do this from a command line with MyProject as the working directory:

dotnet ef --project ../MyProject.Entities --startup-project . migrations add MyNewMigration

To update the database is similar:

dotnet ef --project ../MyProject.Entities --startup-project . database update

@pettechbytes

I'm using Visual Studio, so my preference is to use the Package Manager Console which does the same. So do I have to execute those two commands every time I want to create a migration script against my Data project?

@arielcloud

Just choose entities project in the drop-down on the top part of package manager console

@pettechbytes

I did get it to work, but not excited about the process I had to take. I had to reference my data project in my web project before a DLL was built so that migrations could execute.

@bricelam bricelam self-assigned this Aug 22, 2016
@natemcmaster natemcmaster removed their assignment Aug 22, 2016
@bricelam bricelam modified the milestone: 1.1.0, 1.1.0-preview1 Sep 29, 2016
@rowanmiller rowanmiller modified the milestone: 1.2.0, 1.1.0 Oct 6, 2016
@bricelam bricelam modified the milestone: 1.2.0, 1.1.0 Oct 27, 2016
@rowanmiller rowanmiller modified the milestone: 1.1.0, 1.2.0 Nov 2, 2016
@bricelam
Member
bricelam commented Nov 8, 2016

As far as I can tell, I'm able to make this scenario work in the Package Manager Console Tools (i.e. Add-Migration) for VS "15". I'll do some more testing, but I should also be able to use the same approach in the .NET Command Line Tools (i.e. dotnet ef).

@bricelam bricelam removed the blocked label Nov 8, 2016
@bricelam bricelam changed the title from CLI Commands: support targeting .NET Core class library projects to Tools: Support .NET Core Class Library projects Nov 8, 2016
@rahamohebbi

I would like to be able to have my repository (Entity Framework) classes in a separate class library. Is this possible right now ? if not, when should I expect this to be added to Entity Framework Core library ?

@bricelam
Member
bricelam commented Nov 20, 2016 edited

Yes, you can have your model or DbContext in a class library. This issue is about making the Migrations tooling experience a little better. Right now, you have to use an app (non-library) startup project for them to work at all.

I'm working on changes that will largely remove this restriction, although maybe not always for dotnet ef database update.

@mehmetilker

@bricelam Which means we still have to reference EF Core to the web project ?
Is there any open issue related with this problem we can follow ?
Lots of people are waiting to remove EF references from their web projects I guess...

@bricelam bricelam added a commit to bricelam/EntityFramework.Tools that referenced this issue Nov 28, 2016
@bricelam bricelam Update dotnet-ef
Notable changes:
- Removes project.json support (resolves aspnet/EntityFramework#6886)
- Enables class libraries (fixes aspnet/EntityFramework#5320)
- Don't require EFCore.Tools (aspnet/EntityFramework#7066)
5923332
@bricelam bricelam added a commit to bricelam/EntityFramework.Tools that referenced this issue Nov 28, 2016
@bricelam bricelam Update dotnet-ef
Notable changes:
- Removes project.json support (resolves aspnet/EntityFramework#6886)
- Enables class libraries (fixes aspnet/EntityFramework#5320)
- Don't require EFCore.Tools (aspnet/EntityFramework#7066)
9b495d6
@bricelam
Member
bricelam commented Nov 29, 2016 edited

So there's good news and bad news...

The good news is that I got it "working".

The bad news is that, in practice, it doesn't really "work" because the .NETStandard framework isn't intended for execution. It will work if everything down the execution path has a pure .NETStandard implementation that doesn't depend on a runtime. So basically the only command that will always work is:

  • dotnet ef dbcontext list

None of the other commands will work on SQL Server because SqlClient is too framework-and-runtime-specific. You get:

Could not load file or assembly 'System.Data.SqlClient, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.

SQLite is a little better because anything that doesn't actually open a connection will work:

  • dotnet ef migrations list
  • dotnet ef migrations add (& Add-Migration)
  • dotnet ef migrations script (& Script-Migration)
  • dotnet ef migrations remove --force (& Remove-Migration)

Anything else will throw:

Unable to load DLL 'sqlite3': The specified module could not be found. (Exception from HRESULT: 0x8007007E)

So, the question is, do we...

  1. Allow execution and warn:

    The project 'ClassLibrary1' targets .NETStandard. This framework is not intended for execution and may fail to find runtime dependencies. If so, specify a --startup-project that references this project and targets a different framework (e.g. .NETCoreApp).

  2. Prevent execution entirely and force you to use --startup-project.
@bricelam bricelam removed this from the 1.2.0 milestone Nov 29, 2016
@bricelam
Member
bricelam commented Nov 29, 2016 edited

If we do allow execution, we should consider automatically add -Force to Remove-Migration like we do on UWP. Although, it theoretically may be able to check the database if the provider is purely managed.

@rowanmiller rowanmiller added this to the 1.2.0 milestone Nov 29, 2016
@rowanmiller
Member

We'll go with the warning approach

@esargent

As a developer trying to use EFcore and having to deal with this issue because we are leveraging a common data model across multiple web portals and even a Xamarin project for Android - my team would prefer to have the option and the warning message.

It feels a lot more natural to do data modeling and schema work against the Data project, not the application.

@bricelam bricelam modified the milestone: 1.2.0, tools-1.0.0 Nov 29, 2016
@bricelam bricelam added a commit to bricelam/EntityFramework.Tools that referenced this issue Nov 29, 2016
@bricelam bricelam Update dotnet-ef
Notable changes:
- Removes project.json support (resolves aspnet/EntityFramework#6886)
- Enables class libraries (fixes aspnet/EntityFramework#5320)
- Don't require EFCore.Tools (aspnet/EntityFramework#7066)
6cdd2b0
@koenigsbier

@bricelam so you are saying there will be no issues with a .NET Core class library targeting only full .NET Framework instead of .NET Standard?

@bricelam
Member

Correct. Class libraries targeting .NET Framework or .NET Core App should work just fine without specifying a separate startup project.

@bricelam
Member
bricelam commented Nov 30, 2016 edited

To ellaborate, there are two projects when you invoke a command:

The target project that you are operating on. Files will be added to this project.

The startup project. This is the runtime environment we'll emulate at design time. This project's config will be loaded; it's Startup.ConfigureServices() will be used if it's an ASP.NET Core project; etc.

In PMC, the target project defaults to the selected Default project and can be overridden using -Project. The startup project defaults the the selected startup project (the one that runs when you click Start with debugging) and can be overridden using -StartupProject.

On CLI, the target project defaults to the one in the working directory and can be overridden using --project. The startup project defaults to the target project and can be overridden using --startup-project.

@ErikEJ
Contributor
ErikEJ commented Nov 30, 2016

For the first time I kind of understand this, how about adding this to the docs?

@rowanmiller
Member

@ErikEJ good idea. We don't really have any detailed docs on the commands at the moment, just a reference on what parameters are available etc.

@bricelam bricelam added a commit to bricelam/EntityFramework.Tools that referenced this issue Nov 30, 2016
@bricelam bricelam Update dotnet-ef
Notable changes:
- Removes project.json support (resolves aspnet/EntityFramework#6886)
- Enables class libraries (fixes aspnet/EntityFramework#5320)
- Don't require EFCore.Tools (aspnet/EntityFramework#7066)
9348b3a
@bricelam bricelam added a commit to bricelam/EntityFramework.Tools that referenced this issue Dec 1, 2016
@bricelam @bricelam bricelam + bricelam Update dotnet-ef
Notable changes:
- Removes project.json support (resolves aspnet/EntityFramework#6886)
- Enables class libraries (fixes aspnet/EntityFramework#5320)
- Don't require EFCore.Tools (aspnet/EntityFramework#7066)
94492d1
@bricelam bricelam referenced this issue in aspnet/EntityFramework.Tools Dec 1, 2016
Closed

Update dotnet-ef #28

@bricelam bricelam added a commit to bricelam/EntityFramework.Tools that referenced this issue Dec 2, 2016
@bricelam @bricelam bricelam + bricelam Update dotnet-ef
Notable changes:
- Removes project.json support (resolves aspnet/EntityFramework#6886)
- Enables class libraries (fixes aspnet/EntityFramework#5320)
- Don't require EFCore.Tools (aspnet/EntityFramework#7066)
6d9ddce
@bricelam bricelam added a commit to bricelam/EntityFramework.Tools that referenced this issue Dec 2, 2016
@bricelam @bricelam bricelam + bricelam Update dotnet-ef
Notable changes:
- Removes project.json support (resolves aspnet/EntityFramework#6886)
- Enables class libraries (fixes aspnet/EntityFramework#5320)
- Don't require EFCore.Tools (aspnet/EntityFramework#7066)
9c7b673
@bricelam bricelam added a commit to bricelam/EntityFramework.Tools that referenced this issue Dec 2, 2016
@bricelam @bricelam bricelam + bricelam Update dotnet-ef
Notable changes:
- Removes project.json support (resolves aspnet/EntityFramework#6886)
- Enables class libraries (fixes aspnet/EntityFramework#5320)
- Don't require EFCore.Tools (aspnet/EntityFramework#7066)
43fe84b
@bricelam bricelam added a commit to bricelam/EntityFramework.Tools that referenced this issue Dec 2, 2016
@bricelam @bricelam bricelam + bricelam Update dotnet-ef
Notable changes:
- Removes project.json support (resolves aspnet/EntityFramework#6886)
- Enables class libraries (fixes aspnet/EntityFramework#5320)
- Don't require EFCore.Tools (aspnet/EntityFramework#7066)
27d5ea0
@bricelam bricelam closed this Dec 2, 2016
@bricelam bricelam added a commit to bricelam/EntityFramework.Tools that referenced this issue Dec 6, 2016
@bricelam bricelam Update dotnet-ef
Notable changes:
- Removes project.json support (resolves aspnet/EntityFramework#6886)
- Enables class libraries (fixes aspnet/EntityFramework#5320)
- Don't require EFCore.Tools (aspnet/EntityFramework#7066)
749711b
@bricelam
Member
bricelam commented Jan 4, 2017 edited

Bad news
The solution I had stopped working. You will have to use a separate startup project when working directly with .NET Standard projects. You will receive the following error.

Startup project 'ClassLibrary1' targets framework '.NETStandard'. This framework is not intended for execution. Specify a project that targets a concrete framework like '.NETCoreApp' or '.NETFramework' using the --startup-project option and try again.

Good news
They're adding a .NET Core (in addition to the .NET Standard) Class Library in Visual Studio 2017. The Entity Framework Core Tools will work as expected on these projects.

@bricelam
Member
bricelam commented Jan 5, 2017

Scratch that. It was an unrelated issue. .NET Standard class libraries will "work" (as much as they can)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment