.NET 标准库是否支持 EF Core 添加迁移?

Is EF Core Add Migration Supported from .NET Standard Library?

我们一直在尝试 运行 .Net Standard 1.6 class 库中的 EF Core 迁移,但一直失败。但在 .Net Core 1.1 class 库中同样通过得很好。

Is EF Migration supported in .NET STANDARD?

DbContext 被放置在 netstandardx.y Class 库中时,文档将这种情况描述为 know issue/限制。

Workaround 1 - Use an app as the startup project

If you have an existing .NET Core App or .NET Framework App (including an ASP.NET Core Web Application), you can use it as the startup project. If not, you can create a new one just for use with the .NET Command Line Tools. Specify a startup project that is a "runnable app." Example: console

dotnet ef migrations list --startup-project ../MyConsoleApp/

Workaround 2 - Cross-target a runnable framework

Add an additional target framework to the class library project. This can a version of either .NET Core App or .NET Framework. To make the project a .NET Core App, add the "netcoreapp1.0" framework to project like in the sample below: XML

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>netcoreapp1.0;netstandard1.4</TargetFrameworks>
  </PropertyGroup>
</Project>

When targeting .NET Framework, ensure you project targets version 4.5.1 or newer. XML

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net46;netstandard1.4</TargetFrameworks>
  </PropertyGroup>
</Project>

我没有尝试过 .Net Standard 1.6,但它确实适用于 2.0。

Microsoft.EntityFrameworkCore.Tools.DotNet 需要添加到每个包含 DbContext 的 class 库中。右键单击该项目并 select Edit *.csproj。然后,添加以下内容:

  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0-preview2-final" />
  </ItemGroup>

您可以在此处查看更深入的教程:

对于看到以下错误的 EF Core 包管理器控制台工具用户:

Startup project 'MyNetStandardLibrary' targets framework '.NETStandard'. There is no runtime associated with this framework, and projects targeting it cannot be executed directly. To use the Entity Framework Core Package Manager Console Tools with this project, add an executable project targeting .NET Framework or .NET Core that references this project, and set it as the startup project; or, update this project to cross-target .NET Framework or .NET Core.

Your target project 'MyNetCoreApp' doesn't match your migrations assembly 'MyNetStandardLibrary'. Either change your target project or change your migrations assembly.


documentation 揭示了这些错误的原因:

The target project is where any files are added (or in some cases removed). The target project defaults to the Default project selected in Package Manager Console, but can also be specified using the -Project parameter.

The startup project is the one emulated by the tools when executing your project's code. It defaults to one Set as StartUp Project in Solution Explorer. It can also be specified using the -StartupProject parameter.

简而言之,您需要将 StartUp Project 设置为具有 .NET 运行时的项目(在本例中为 .NET Core),然后确保将 .NET Standard 项目设置为包管理器控制台 >默认项目。

示例 CLI 解决方案:

Add-Migration MyMigration -Project MyNetStandardLibrary -StartupProject MyNetCoreApp

非 CLI 解决方案:

  1. 右键单击项目中的 .NET Core 应用程序
  2. 单击设置为启动项目
  3. 打开程序包管理器控制台
  4. Select 包管理器控制台中默认项目下拉列表中的 .NET Standard 项目
  5. 运行 您的 CLI 命令(Add-Migration、dotnet ef migrations add 等)

@Tseng,谢谢!这里有明确的说明。

编辑项目文件:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>
  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.1" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.1.1" />
  </ItemGroup>
  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
  </ItemGroup>
</Project>

然后添加设计工厂:

 public class DesignTimeActivitiesDbContextFactory : IDesignTimeDbContextFactory<ActivitiesDbContext>
    {
        public ActivitiesDbContext CreateDbContext(string[] args)
        {
            DbContextOptionsBuilder<ActivitiesDbContext> builder = new DbContextOptionsBuilder<ActivitiesDbContext>();

            var context = new ActivitiesDbContext(
                builder
                .UseSqlServer("Data Source=(local);Initial Catalog=Activities;Integrated Security=False;User ID=user;Password=pw;Connect Timeout=30;Encrypt=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;")
                .Options);

            return context;
        }
    }

然后构建。

然后打开命令提示符,导航到您的项目文件夹,然后运行:

dotnet ef migrations add InitialCreate

现在应该有一个自动生成的迁移文件夹。喜欢它!

好的,但有一个复杂的地方,我想给出一个解释。

案例:Asp.Net核心,我有一个包含Db-Context的标准库。我要迁移 this context 但标准库不直接接受迁移,需要一个启动项目。

解决方案:启动项目可以间接创建迁移

Enable-Migrations MyMigration -Project DB-ContextProjectNameThatIsStandartLib -StartupProject CallerExecutableProjectName_LikeMVCWebProjectOrConsole

Add-Migration MyMigration -Project DB-ContextProjectNameThatIsStandartLib -StartupProject CallerExecutableProjectName_LikeMVCWebProjectOrConsole

我们将从 Package Manager Console DropDown 中选择 Caller Project,但它会在库项目中创建迁移文件。 之后不要从下拉列表中选择其他项目,运行 直接从调用者项目更新 不带任何参数

Update-Database

试一试奇怪但真实

更新: 我已经将我的项目 Asp.net EntityFrameworkCore 3.1.3 升级到 3.1.4 并且上面的那些没有正常工作并给出了错误:

The EntityFramework package is not installed on project

和这个错误

Unable to create an object of type 'DomainDbContext'. For the different patterns supported at design time

这是一个EntityFramework.Core应用程序!我还安装了 EntityFramework 到标准库。但它无法理解并重新启动V.S。 这次它需要安装 entityframework 到启动 MVC (Web) 项目。我不能那样做。我决定添加一个新的控制台应用程序来解决这个要求。并为此创建了以下应用程序

install-Package Microsoft.Extensions.Configuration
Install-Package Microsoft.Extensions.Configuration.Json
Install-Package Microsoft.Extensions.Configuration.CommandLine
Install-Package Microsoft.Extensions.Configuration.EnvironmentVariables
class Program
{
    public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<DomainDbContext>
    {
        public DomainDbContext CreateDbContext(string[] args)
        {
            IConfigurationRoot configuration = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables()
                //.SetBasePath(Directory.GetCurrentDirectory())
                //.AddJsonFile("appsettings.json")
                .Build();
            var builder = new DbContextOptionsBuilder<DomainDbContext>();
            var connectionString = configuration.GetConnectionString("DefaultConnection");
            builder.UseSqlServer(connectionString);
            return new DomainDbContext(builder.Options);
        }
    }

    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");
    }
}

这次成功了!再次使用上述命令 :) cheer