我有一个 Web API 解决方案,其中包含多个项目。测试、服务、领域、数据和 API。 API项目是启动项目。我所有的 EFCore 参考资料都在数据项目中。
我正在尝试在数据项目上运行 Scaffold-DbContext,但是因为它不是启动项目,所以我收到以下错误:
Your startup project 'APIProj' doesn't reference Microsoft.EntityFrameworkCore.Design. This package is required for the Entity Framework Core Tools to work. Ensure your startup project is correct, install the package, and try again.
API 项目不应该了解有关 EF Core 的任何信息,因此我不想只是将该引用放在那里然后就到此为止。试图把事情做得比以前更好......我也不想让其他使用它的人不得不兼顾启动项目。这应该很简单。
无论启动项目是什么,如何正确地将 Scaffold-DbContext 命令指向特定项目。
使用EF工具需要一个可执行的项目, 因此,您要么需要像您自己建议的那样将该程序集添加到可执行项目中,要么可以添加一个虚拟可执行项目。
参见前;
为什么需要虚拟项目?如前所述,这些工具必须在设计时执行应用程序代码。为此,他们需要使用 .NET Core 运行时。当 EF Core 模型位于面向 .NET Core 或 .NET Framework 的项目中时,EF Core 工具会从该项目借用运行时。如果 EF Core 模型位于 .NET Standard 类库中,他们就无法执行此操作。 .NET 标准不是实际的 .NET 实现;它是 .NET 实现必须支持的一组 API 的规范。因此,.NET Standard 不足以让 EF Core 工具执行应用程序代码。您创建的用作启动项目的虚拟项目提供了一个具体的目标平台,工具可以在其中加载 .NET 标准类库。
https://learn.microsoft.com/en-us/ef/core/cli/dotnet#other-target-frameworks
在我们自己的项目结构中,我们的可执行项目中也包含设计参考。然而,现在我正在考虑这一点,我们的应用程序变得相当大,并且运行 EF 命令会强制重建可执行项目,因此这意味着它将完全重建我的大型应用程序,这需要很长时间。
因此我建议使用虚拟项目,就像 MSDN 也推荐的那样。
编辑;
我认为理论上你也可以使你的数据项目成为一个可执行项目,并引用它:
// ConsoleApp1
new MyConsoleApp2Class().Print();
// ConsoleApp2
namespace ConsoleApp2;
public class MyConsoleApp2Class
{
public void Print()
{
Console.WriteLine("Hello world.");
}
}
这取决于您的数据项目的框架,.net 标准项目无法成为可执行文件。
然后,您可以使用设计时数据库上下文工厂来帮助实例化工具的数据库上下文(使用正确的 sql 连接字符串等):
这样,您不需要数据项目包含整个应用程序,如 https://learn.microsoft.com/en-us/ef/core/cli/dbcontext-creation?tabs=dotnet-core 中所述-cli#from-application-services
使用应用程序的可执行项目的优点是您可以维护 1 个项目的应用程序设置,其他方法您必须将连接字符串保存在 2 个位置,或者在设计时工厂中有一些逻辑来获取正确的连接字符串连接字符串或类似的东西。
但是您的数据库连接字符串多久更改一次?在大多数情况下几乎不会。
这太愚蠢了,花了太长时间才找到答案,而不仅仅是“在 API 中包含数据库内容”,这太荒谬了。
我将
MyApp.Data.EF
从库更改为控制台应用程序(在解决方案资源管理器中右键单击项目并更改启动类型)。添加一个带有 public static void Main 空方法的 Program.cs 文件。
然后你就可以像这样使用PMC:
add-migration Initial -context MyAppContext -StartupProject MyApp.Data.EF
只需确保 PMC 的默认项目指向正确的项目即可。
-context
是类名,不是文件名或其他任何东西,-StartupProject
只是项目的名称,而不是.csproj。