使用不同的程序集添加迁移
Posted
技术标签:
【中文标题】使用不同的程序集添加迁移【英文标题】:Add migration with different assembly 【发布时间】:2016-12-06 22:30:47 【问题描述】:我正在使用 ASP.NET CORE 1.0.0 开发一个项目,并且我正在使用 EntityFrameworkCore。我有单独的程序集,我的项目结构如下所示:
ProjectSolution
-src
-1 Domain
-Project.Data
-2 Api
-Project.Api
在我的Project.Api
中是Startup
类
public void ConfigureServices(IServiceCollection services)
services.AddDbContext<ProjectDbContext>();
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ProjectDbContext>()
.AddDefaultTokenProviders();
DbContext
在我的Project.Data
项目中
public class ProjectDbContext : IdentityDbContext<IdentityUser>
public ProjectDbContext(DbContextOptions<ProjectDbContext> options) : base(options)
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
var builder = new ConfigurationBuilder();
builder.SetBasePath(Directory.GetCurrentDirectory());
builder.AddJsonFile("appsettings.json");
IConfiguration Configuration = builder.Build();
optionsBuilder.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection"));
base.OnConfiguring(optionsBuilder);
当我尝试进行初始迁移时,我收到此错误:
“您的目标项目“Project.Api”与您的迁移程序集“Project.Data”不匹配。请更改您的目标项目或更改您的迁移程序集。 使用 DbContextOptionsBuilder 更改您的迁移程序集。例如。 options.UseSqlServer(connection, b => b.MigrationsAssembly("Project.Api"))。默认情况下,迁移程序集是包含 DbContext 的程序集。 通过使用包管理器控制台的默认项目下拉列表,或从包含迁移项目的目录中执行“dotnet ef”,将您的目标项目更改为迁移项目。”
看到这个错误后,我尝试执行位于Project.Api
的这个命令:
dotnet ef --startup-project ../Project.Api --assembly "../../1 Data/Project.Data" 迁移添加 Initial
我得到了这个错误:
“选项“程序集”的意外值“../../1 Domain/Project.Data””
当我尝试使用“-assembly”参数执行命令时,我不知道为什么会出现此错误。
我无法从其他程序集创建初始迁移,我已经搜索了有关它的信息但没有得到任何结果。
有人遇到过类似的问题吗?
【问题讨论】:
您阅读文档了吗? docs.efproject.net/en/latest/miscellaneous/cli/… 是的,但我没有t get fix the error, i tryed diferent options of commands with --startup-project and --assebly but i didn
t 什么也得不到
不要使用 --assembly。这是一个应该从帮助消息中隐藏的内部实现细节,但由于github.com/aspnet/EntityFramework/issues/5188 无论如何都会显示出来
【参考方案1】:
所有 EF 命令都有this check:
if (targetAssembly != migrationsAssembly)
throw MigrationsAssemblyMismatchError;
targetAssembly = 您正在操作的目标项目。在命令行上,它是当前工作目录中的项目。在包管理器控制台中,它是在该窗口窗格右上角的下拉框中选择的任何项目。
migrationsAssembly = 包含迁移代码的程序集。这是可配置的。默认情况下,这将是包含 DbContext 的程序集,在您的情况下为 Project.Data.dll。 正如错误消息所示,您有两种选择来解决此问题
1 - 更改目标程序集。
cd Project.Data/
dotnet ef --startup-project ../Project.Api/ migrations add Initial
// code doesn't use .MigrationsAssembly...just rely on the default
options.UseSqlServer(connection)
2 - 更改迁移程序集。
cd Project.Api/
dotnet ef migrations add Initial
// change the default migrations assembly
options.UseSqlServer(connection, b => b.MigrationsAssembly("Project.Api"))
【讨论】:
我可以t execute a command from Project.Data because is a classlibrary and it doesn
t允许执行命令,我只能在Project.Api中执行命令
谢谢,非常有用;)
谢谢,在花了很多时间在其他解决方案上之后,这有所帮助。
出色的解释和示例,在浪费了几个小时在其他“解决方案”上后立即解决了我的问题。谢谢!!!
您是否有任何解释或链接来说明为什么要实施此检查?当上下文来自其他程序集时,禁止迁移的原因是什么?【参考方案2】:
我遇到了同样的问题,直到我注意到包管理器控制台顶部栏 =>“默认项目”应该是“Project.Data”而不是“Project.API”。
一旦您从下拉列表中定位“Project.Data”并运行迁移,您应该没问题。
【讨论】:
【参考方案3】:使用 EF Core 2,您可以轻松地将 Web 项目与 Data (DbContext) 项目分开。实际上,您只需要实现 IDesignTimeDbContextFactory 接口即可。根据Microsoft docs,IDesignTimeDbContextFactory 是:
用于创建派生 DbContext 实例的工厂。实现这个 为不支持的上下文类型启用设计时服务的接口 有一个公共的默认构造函数。在设计时,派生的 DbContext 可以创建实例以启用特定的设计时 迁移等经历。设计时服务将 自动发现此接口的实现 启动程序集或与派生上下文相同的程序集。
在底部代码 sn-p 中,您可以看到我在 Data 项目中定义的 DbContextFactory 实现:
public class DbContextFactory : IDesignTimeDbContextFactory<KuchidDbContext>
public KuchidDbContext CreateDbContext(string[] args)
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var dbContextBuilder = new DbContextOptionsBuilder<KuchidDbContext>();
var connectionString = configuration.GetConnectionString("Kuchid");
dbContextBuilder.UseSqlServer(connectionString);
return new KuchidDbContext(dbContextBuilder.Options);
现在,我可以通过将我的 Web 项目设置为 StartUp 项目并在包管理器控制台中选择我的 Data 项目来初始化 EF 迁移。
Add-Migration initial
您可以找到更多详细信息here。但是,这篇博文使用了一个过时的类而不是 IDesignTimeDbContextFactory。
【讨论】:
可以确认这项工作。我们需要一些更复杂的设置。如果 DbContext 本身位于 NuGet 包中,它甚至可以工作。您可以在 IDesignTimeDbContextFactory.AddJsonFile("appsettings.json")
。如果您的 .Data 项目中不存在 appsettings.json 文件怎么办?
这个有 3.0/1 版本吗?
微软在这里放了一些文档docs.microsoft.com/en-us/ef/core/cli/…【参考方案4】:
使用 CLI 命令添加迁移:
dotnet ef migrations add NewMigration --project YourAssemblyName
使用 PMC 命令添加迁移:
Add-Migration NewMigration -Project YourAssemblyName
Link About CLI Commands
Link About PMC Commands
【讨论】:
帮助链接:docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dotnet【参考方案5】:我跑了同样的问题,发现this
您是否尝试在类库上运行迁移?我也是。结果这还不支持,所以我们需要解决它。
编辑:我在this git repo找到了解决方案
【讨论】:
谢谢。我看到了这个解决方案,但它似乎有点强迫,但到目前为止,它是我看到它工作的唯一解决方案。我会点击链接获取新闻 非常感谢!! services.AddDbContext目前我认为 EF 只支持在尚未在类库上的项目上添加迁移。
对于想要将迁移添加到项目中特定文件夹的其他人来说,只是旁注:
EF CLI 还不支持这个。我试过--data-dir
,但没用。
唯一有效的方法是使用包管理器控制台:
-
选择您的默认项目
使用
-OutputDir
命令参数,例如,Add-Migration InitConfigurationStore -OutputDir PersistedStores/ConfigurationStore
命令会将管理输出到我项目中的“PersistedStores/ConfigurationStore”文件夹。
截至 2017 年 10 月 12 日的更新
public void ConfigureServices(IServiceCollection services)
...
string dbConnectionString = services.GetConnectionString("YOUR_PROJECT_CONNECTION");
string assemblyName = typeof(ProjectDbContext).Namespace;
services.AddDbContext<ProjectDbContext>(options =>
options.UseSqlServer(dbConnectionString,
optionsBuilder =>
optionsBuilder.MigrationsAssembly(assemblyName)
)
);
...
截至 2021 年 1 月 4 日的更新
我这次使用的是 EF Core 5.0。我希望optionBuilder.MigrationAssembly()
方法可以在您想在目标项目的文件夹下生成迁移但它没有。
我这次的结构是:
src
- presentation
- WebUI
- boundedContext
- domain
- application
- infrastructure
- data/
- appDbContext
- email-services
- sms-services
请参阅我将基础架构作为类库,它包含多个文件夹,因为我只想拥有一个项目来包含所有与基础架构相关的服务。但是我想用文件夹来组织它们。
string assemblyName = typeof(ProjectDbContext).Namespace
会给我正确的路径“src/infrastructure/data”,但添加迁移仍然失败,因为该文件夹不是程序集!
无法加载文件或程序集。系统找不到文件 指定。
因此,唯一真正起作用的就是再次指定输出文件夹...
使用 .NET Core CLI,您必须在目标项目下打开命令行,然后执行以下操作:
dotnet ef migrations add Init
-o Data\Migrations
-s RELATIVE_PATH_TO_STARTUP_PROJECT
【讨论】:
【参考方案7】:(ASP.NET Core 2+)
有同样的问题。 这是我所做的:
从将包含迁移的项目 (Project.B) 中引用包含 DbContext (Project.A) 的项目。
将现有迁移从 Project.A 移动到 Project.B (如果您没有迁移 - 先创建它们)
在 Project.A 中配置迁移程序集
options.UseSqlServer( 连接字符串, x => x.MigrationsAssembly("Project.B"));
假设您的项目位于同一个父文件夹中:
dotnet ef migrations add Init --p Project.B -c DbContext
迁移现在转到 Project.B
来源:Microsoft
【讨论】:
我错过了 -c DbContext。谢谢!【参考方案8】:解决方案中包含多个项目。
解决方案 |- MyApp(启动项目) |- MyApp.Migrations (ClassLibrary)
Add-Migration NewMigration -Project MyApp.Migrations
注意: MyApp.Migrations 还包括 DbContext。
【讨论】:
你能解释一下这个的背景,使它成为一个更好的答案。 这很有帮助,谢谢。我将 Migrations 文件夹和 DbContext 放在类库中,然后在我的 asp.net Web 应用程序项目中引用该类库。原因是我还在控制台应用程序中使用类库,该应用程序将作为 Web 作业部署到 Azure 中的同一应用服务。【参考方案9】:下面的命令对我有用。我正在使用 VS Code 并运行以下命令:
SocialApp.Models> dotnet ef migrations add InitialMigartion --startup-project ../SocialApp.API
礼貌:https://github.com/bricelam/Sample-SplitMigrations
【讨论】:
【参考方案10】:这适用于 EF Core 3.x。
基于来自Ehsan Mirsaeedi 的this 回答和来自Ales Potocnik Hahonina 的this 评论,我也设法使添加迁移工作。
我使用 Identity Server 4 作为 NuGet 包,包中有两个数据库上下文。 下面是实现 IDesignTimeDbContextFactory 接口的类的代码:
public class PersistedGrantDbContextFactory : IDesignTimeDbContextFactory<PersistedGrantDbContext>
public PersistedGrantDbContext CreateDbContext(string[] args)
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var dbContextBuilder = new DbContextOptionsBuilder<PersistedGrantDbContext>();
var connectionString = configuration.GetConnectionString("db");
dbContextBuilder.UseSqlServer(connectionString, b => b.MigrationsAssembly("DataSeeder"));
return new PersistedGrantDbContext(dbContextBuilder.Options, new OperationalStoreOptions() ConfigureDbContext = b => b.UseSqlServer(connectionString) );
与Ehsan Mirsaeedi 的答案相比,我修改了这些: 我添加了 MigrationsAssembly:
dbContextBuilder.UseSqlServer(connectionString, b => b.MigrationsAssembly("DataSeeder"));
“DataSeeder”是我的启动项目的名称,用于播种和迁移。
我添加了一个将 ConfigureDbContext 属性设置为连接字符串的选项对象:
return new PersistedGrantDbContext(dbContextBuilder.Options, new OperationalStoreOptions() ConfigureDbContext = b => b.UseSqlServer(connectionString) );
现在可以这样使用: 'Add-Migration -Context PersistedGrantDbContext
此时,创建迁移后,可以在迁移项目中为此创建服务,方法如下:
public async Task DoFullMigrationAsync()
using (var scope = _serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
var persistedGrantDbContextFactory = new PersistedGrantDbContextFactory();
PersistedGrantDbContext persistedGrantDbContext = persistedGrantDbContextFactory.CreateDbContext(null);
await persistedGrantDbContext.Database.MigrateAsync();
// Additional migrations
...
我希望我帮助了某人。
干杯,
汤姆
【讨论】:
【参考方案11】:您所要做的就是像这样修改您的 ConfigureServices:
public void ConfigureServices(IServiceCollection services)
services.AddDbContext<ProjectDbContext>(item => item.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly("Project.Api")));
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ProjectDbContext>()
.AddDefaultTokenProviders();
默认情况下,VS 将使用存储 DbContext 的项目的程序集。上面的改动,只是告诉VS使用你的API项目的程序集。
您仍然需要将您的 API 项目设置为默认启动项目,方法是在解决方案资源管理器中右键单击它并选择设置为启动项目
【讨论】:
【参考方案12】:目录结构
Root
APIProject
InfrastructureProject
通过进入根目录 添加迁移
dotnet ef migrations add Init --project InfrastructureProject -s APIProject
更新数据库
dotnet ef database update --project InfrastructureProject -s APIProject
【讨论】:
我这样做了,我得到“无法创建类型为 'DataContext' 的对象。对于设计时支持的不同模式......”我该如何解决这个问题?【参考方案13】:我的是一个单一的 .net 核心网络项目。
必须确保一件事来解决此错误。项目中必须存在以下类。
public class SqlServerContextFactory : IDesignTimeDbContextFactory<SqlServerContext>
public SqlServerContext CreateDbContext(string[] args)
var currentEnv = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var configuration = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings. currentEnv ?? "Production".json", optional: true)
.Build();
var connectionString = configuration.GetConnectionString("MsSqlServerDb");
var optionsBuilder = new DbContextOptionsBuilder<SqlServerContext>();
//var migrationAssembly = typeof(SqlServerContext).Assembly.FullName;
var migrationAssembly = this.GetType().Assembly.FullName;
if (connectionString == null)
throw new InvalidOperationException("Set the EF_CONNECTIONSTRING environment variable to a valid SQL Server connection string. E.g. SET EF_CONNECTIONSTRING=Server=localhost;Database=Elsa;User=sa;Password=Secret_password123!;");
optionsBuilder.UseSqlServer(
connectionString,
x => x.MigrationsAssembly(migrationAssembly)
);
return new SqlServerContext(optionsBuilder.Options);
请注意迁移程序集名称。
//var migrationAssembly = typeof(SqlServerContext).Assembly.FullName;
我已经注释掉了。这就是我的罪魁祸首。需要的是以下内容。
var migrationAssembly = this.GetType().Assembly.FullName;
有了它,以下两个命令运行良好。
Add-Migration -StartupProject MxWork.Elsa.WebSqLite -Context "SqlServerContext" InitialMigration
Add-Migration InitialMigration -o SqlServerMigrations -Context SqlServerContext
如果您想要此类项目的参考,请查看此git hub link
您应该在其中找到一个名为 Elsa.Guides.Dashboard.WebApp50.zip 的项目。下载看看那个网络应用程序。
【讨论】:
【参考方案14】:我遇到了类似的问题,尽管答案似乎很直接,但不知何故它们不起作用。 我的答案与@Ehsan Mirsaeedi 类似,只是在 DbContextFactory 类中进行了小改动。我没有在 API 的 Startup 类中添加迁移程序集名称,而是在作为 Data 项目(类库)的一部分的 DbContextFactory 类中提到。
public class DbContextFactory : IDesignTimeDbContextFactory<KuchidDbContext>
public KuchidDbContext CreateDbContext(string[] args)
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var dbContextBuilder = new DbContextOptionsBuilder<KuchidDbContext>();
var connectionString = configuration.GetConnectionString("connectionString");
var migrationAssemblyName= configuration.GetConnectionString("migrationAssemblyName");
dbContextBuilder.UseSqlServer(connectionString, o => o.MigrationAssembly(migrationAssemblyName));
return new KuchidDbContext(dbContextBuilder.Options);
您需要 'Microsoft.Extensions.Configuration' 和 'Microsoft.Extensions.Configuration.Json' 才能使 SetBasePath 和 AddJsonFile 扩展工作。
注意:我觉得这只是一种解决方法。它应该从启动类中获取 DbContextOptions ,但它不是。我想肯定有一些接线问题。
【讨论】:
【参考方案15】:dotnet ef update-database --startup-project Web --project 数据
Web
是我的创业项目
Data
是我的我的类库
【讨论】:
【参考方案16】:我已通过在 Startup.cs 中添加以下行来解决它。希望它也能帮助你。我用过 Postgres 你可以用 Sql Server 代替那个
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddIdentityServer(options =>
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
)
.AddSigningCredential(cert)
.AddCustomUserStore<IdentityServerConfigurationDbContext>()
// this adds the config data from DB (clients, resources)
.AddConfigurationStore(options =>
options.ConfigureDbContext = builder =>
builder.UseNpgsql(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
)
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
options.ConfigureDbContext = builder =>
builder.UseNpgsql(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 30;
);
【讨论】:
【参考方案17】:对于所有拥有多个创业项目的人。
请注意,您需要将目标项目设置为启动项目 - Project.Api
(形成问题示例)应该是启动项目。
希望对某人有所帮助:)
【讨论】:
依赖注入需要一个启动项目。以上是关于使用不同的程序集添加迁移的主要内容,如果未能解决你的问题,请参考以下文章
Code-First,当我进行启用迁移时,我得到“在程序集'DOC'中找不到上下文类型”
您必须添加对程序集 mscorlib 的引用,版本=4.0.0