可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am doing a project in ASP.NET CORE 1.0.0 and I am using EntityFrameworkCore. I have separate assemblies and my project structure looks like this:
ProjectSolution
-src
-1 Domain
-Project.Data
-2 Api
-Project.Api
In my Project.Api
is the Startup
class
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ProjectDbContext>();
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ProjectDbContext>()
.AddDefaultTokenProviders();
}
The DbContext
is in my Project.Data project
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);
}
}
When I try to make the initial migration, I get this error:
"Your target project 'Project.Api' doesn't match your migrations assembly 'Project.Data'. Either change your target project or change your migrations assembly.
Change your migrations assembly by using DbContextOptionsBuilder. E.g. options.UseSqlServer(connection, b => b.MigrationsAssembly("Project.Api")). By default, the migrations assembly is the assembly containing the DbContext.
Change your target project to the migrations project by using the Package Manager Console's Default project drop-down list, or by executing "dotnet ef" from the directory containing the migrations project."
After I seeing this error, I tried to execute this command located in Project.Api
:
dotnet ef --startup-project ../Project.Api --assembly "../../1 Data/Project.Data" migrations add Initial
and I got this error:
"Unexpected value '../../1 Domain/Project.Data' for option 'assembly'"
I dont know why I get this error, when I try to execute the command with the
-assembly` parameter.
I can`t create a Initial Migration from other assembly and I've searched for information about it but didn't got any results.
Has someone had similar issues?
回答1:
All EF commands have this check:
if (targetAssembly != migrationsAssembly)
throw MigrationsAssemblyMismatchError;
targetAssembly = the target project you are operating on. On the command line, it is the project in the current working directory. In Package Manager Console, it is whatever project is selected in the drop down box on the top right of that window pane.
migrationsAssembly = assembly containing code for migrations. This is configurable. By default, this will be the assembly containing the DbContext, in your case, Project.Data.dll.
As the error message suggests, you have have a two options to resolve this
1 - Change target assembly.
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 - Change the migrations assembly.
cd Project.Api/
dotnet ef migrations add Initial
// change the default migrations assembly
options.UseSqlServer(connection, b => b.MigrationsAssembly("Project.Api"))
回答2:
I had the same problem until I noticed that on the package manager console top bar => "Default Projects" was supposed to be "Project.Data" and not "Project.API".
Once you target the "Project.Data" from the dropdown list and run the migration you should be fine.
回答3:
Currently I think EF only supports to add migrations on projects not yet on class libraries.
And just side note for anybody else who wants to add migrations to specific folder inside your project:
EF CLI not support this yet. I tried --data-dir
but it didn't work.
The only thing works is to use Package Manager Console:
- Pick your default project
- use
-OutputDir
command parameter, .e.g., Add-Migration InitConfigurationStore -OutputDir PersistedStores/ConfigurationStore
command will output the mgiration to the folder 'PersistedStores/ConfigurationStore' in my project.
Updates as of 10/12/2017
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)
)
);
...
}
回答4:
I ran on the same problem and found this
We’re you trying to run your migrations on a class library? So was I. Turns out this isn’t supported yet, so we’ll need to work around it.
EDIT: I found solution on this git repo
回答5:
Using EF Core 2, you can easily separate your Web project from your Data (DbContext) project. In fact, you just need to implement the IDesignTimeDbContextFactory interface. According to Microsoft docs, IDesignTimeDbContextFactory is:
A factory for creating derived DbContext instances. Implement this
interface to enable design-time services for context types that do not
have a public default constructor. At design-time, derived DbContext
instances can be created in order to enable specific design-time
experiences such as Migrations. Design-time services will
automatically discover implementations of this interface that are in
the startup assembly or the same assembly as the derived context.
In the bottom code snippet you can see my implementation of DbContextFactory which is defined inside my Data project:
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);
}
}
Now, I can initialize EF migration by setting my Web project as the StartUp project and selecting my Data project inside the Package Manager Console.
Add-Migration initial
You can find more details here. However, this blog post uses an obsoleted class instead of IDesignTimeDbContextFactory.
回答6:
For all of you who have multiple startup projects.
Notice that you need to set your target project as startup project - Project.Api
(form the question example) should be the startup project.
Hope that will help someone :)