至少对于SQLite数据库,它似乎是an issue that have been fixed already。
我的解决方案包含3个项目:
我已将以下软件包安装到主WPF项目中:
Microsoft.EntityFrameworkCore.Tools
Microsoft.EntityFrameworkCore.Design
在我的主要WPF项目中引用了项目2和3。因此,基本上,EF足以解决DbContext。
但是,事实并非如此-在我的WPF项目上运行Add-Migration
会导致:
PM> Add-Migration "Initial"
No DbContext was found in assembly 'TestWPFProject'. Ensure that you're using the correct assembly and that the type is neither abstract nor generic.
在Package Manager控制台中默认切换到项目3
会导致:
PM> Add-Migration "Initial"
Unable to create an object of type 'ClientDbContext'. Add an implementation of 'IDesignTimeDbContextFactory<ClientDataStoreDbContext>' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.
如何在类库项目和WPF项目中正确使用EF Core迁移?
答案 0 :(得分:12)
我复制了您的解决方案,然后发现了……解决方案:)
让我们加深。
名称: ClassLibrary1 。
类型: .NET Standard 2.0类库。
依赖关系:无。
在我的测试解决方案中,它仅包含一个类,即一个名为 Person 的模型。
Person.cs
namespace ClassLibrary1
{
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
}
名称: EFClassLibrary 。
类型: .NET Standard 2.0类库。
依赖项:
在我的测试解决方案中,该项目仅包含一个类:数据库上下文。
ClientDbContext.cs
using ClassLibrary1;
using Microsoft.EntityFrameworkCore;
namespace EFClassLibrary
{
public class ClientDbContext : DbContext
{
const string connectionString = "Server=(localdb)\\mssqllocaldb;Database=ClientDb;Trusted_Connection=True;";
public ClientDbContext() : base() { }
public ClientDbContext(DbContextOptions<ClientDbContext> options) : base(options) { }
public DbSet<Person> People { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(connectionString);
}
}
}
在此类中,定义了一个用于连接数据库的连接字符串(假设它是LocalDb SQL Server)。如果要将连接字符串放在配置文件中,可以在解决方案中添加共享的配置文件,然后在App.config
文件中引用该文件(有关更多信息,请查看this page)
为了能够在此项目上添加迁移而不将其他项目设置为启动项目,必须设置目标框架。右键单击该项目,然后单击 Edit EFClassLibrary.csproj 条目。在<TargetFramework>netstandard2.0</TargetFramework>
行下方,您应添加另一行,以指定要定位的框架。要定位.NET Framework 4.7,您应该添加
<TargetFramework>net47</TargetFramework>
可以找到所有允许值的列表here。
将.NET Framework 4.7添加为目标后,我的 EFClassLibrary.csproj 类似于下面的代码。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>net47</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj" />
</ItemGroup>
</Project>
现在,您可以添加第一次迁移了。打开软件包管理器控制台,并将 EFClassLibrary 设置为默认项目。另外,将该项目设置为启动项目(右键单击该项目,然后单击设置为启动项目条目)。
类型
PM> Add-Migration Initial
然后
PM> Update-Database
名称: WpfApp1 。
类型:使用 .NET Framework 4.7 的 WPF应用程序。
依赖项:
在此项目中,我没有添加任何文件。刚刚编辑过MainWindow.xaml.cs
文件以检查一切是否正常。
MainWindow.xaml.cs
using ClassLibrary1;
using EFClassLibrary;
using System.Windows;
namespace WpfApp1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var db = new ClientDbContext();
db.People.Add(new Person()
{
Name = "Omar"
});
db.SaveChanges();
}
}
}
希望它会有所帮助:)
答案 1 :(得分:3)
在启动项目中,您必须创建一个工厂,该工厂将实现IDesignTimeDbContextFactory并为您创建DBContext。
public class DBContextFactory : IDesignTimeDbContextFactory<DBContext>
{
public DBContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<DBContext>();
// Row numbers for paging adds support for old SQL server 2005+. See more:
// https://docs.microsoft.com/en-us/ef/core/api/microsoft.entityframeworkcore.infrastructure.sqlserverdbcontextoptionsbuilder
optionsBuilder.UseSqlServer("Server=localhost;Database=DatabaseName;Trusted_Connection=True;MultipleActiveResultSets=true;Integrated Security=SSPI", x => x.UseRowNumberForPaging());
return new DBContext(optionsBuilder.Options);
}
}
答案 2 :(得分:3)
microsoft的建议是为迁移创建一个新的类库,然后将模型快照文件和迁移移动到新的类库中。
如果尚未添加任何内容,则将其添加到DbContext项目中,然后将其移动。
然后配置迁移程序集:
options.UseSqlServer(
connectionString,
x => x.MigrationsAssembly("MyApp.Migrations"));
然后从启动程序集添加对迁移程序集的引用:
注意:
如果这导致循环依赖,请更新类库的输出路径:
<PropertyGroup>
<OutputPath>..\MyStarupProject\bin\$(Configuration)\</OutputPath>
</PropertyGroup>
有关实体库项目的EntityFramework Core迁移的其他参考,请使用Ben Cull's指南。
答案 3 :(得分:3)
对我有用的只是在UI Side Startup.cs上做一些常规的事情
services.AddDbContext<ShentonEvaDbContext>(options =>
options.UseSqlServer(
_configuration.GetConnectionString("DevelopmentConnection")));
然后在您的DBContext配置上只需添加一个构造函数
public ShentonEvaDbContext(DbContextOptions<ShentonEvaDbContext> options) : base(options)
{
}
之后,在Package Manager控制台上运行以下命令
dotnet ef migrations add InitialMigration --project "NameOfDbContextProject" --startup-project "NameOfWebUIProject"
然后添加Everytihng并为数据库更新执行相同操作
答案 4 :(得分:0)
我使用类库项目作为数据层,使用asp.net核心项目作为启动项目。首先,我将我的E.F核心上下文注册到asp.net启动类中。
public void ConfigureServices(IServiceCollection services)
{
//DataLayer namespace is in class library project
services.AddDbContext<DataLayer.EFCoreContext>();
}
然后在我的上下文类(位于类库项目中)中,提供了设置文件中的连接字符串,并将其用于OnConfiguring方法中。
public class EFCoreContext: DbContext
{
private string ConnectionString { get; set; }
public EFCoreContext() : base()
{
var settingsPath= AppDomain.CurrentDomain.BaseDirectory;
settingsPath += @"\datalayersettings.json";
var datalayersettings =File.ReadAllText(settingsPath);
dynamic jSetting = JObject.Parse(datalayersettings);
this.ConnectionString =
(string)jSetting.ConnectionStrings.ConnectionString;
}
protected override void OnConfiguring(DbContextOptionsBuilder
optionsBuilder)
{
optionsBuilder.UseSqlServer(this.ConnectionString);
}
}
然后应用迁移和更新数据库我分别使用了以下命令
add-migration MyEFCoreMigration -Context DataLayer.EFCoreContext -Project DataLayer
Update-Database -Context DataLayer.EFCoreContext -Project DataLayer