我尝试在EF7中使用entityframework.commands进行迁移。但我的DbContext与启动项目处于不同的程序集(asp.net mvc是一个启动项目,而Core.Implementation有一个DbContex)。
dnx。 ef migration添加MyMigration -c MyContext
System.InvalidOperationException:没有名为' MyContext'的DbContext被发现了。
我尝试使用命名空间指向其他程序集,但它也没有工作。有可能吗?或者我只需要将我的上下文放在ef7命令所在的汇编中?
答案 0 :(得分:24)
修改强>
自1.0.0-rc1-final(可能更早)以来,这项工作是不必要的
App.DataAccess/Startup.cs
(如果您使用下面的解决方法,只需将其删除)App.Web
)-p
参数):cd App.Web
dnx ef migrations add NewMigration -p App.DataAccess
如果你有多个数据库上下文,你还必须指定使用哪一个(-c
参数)
cd App.Web
dnx ef migrations add NewMigration -p App.DataAccess -c YourDbContext
END OF EDIT
我找到了解决方法
假设您有2个项目:App.Web
和App.DataAccess
您可以向App.DataAccess
添加一个非常基本的Startup类:
>App.Web
-->Startup.cs // your main startup
>App.DataAccess
-->path/to/ApplicationDbContext.cs
-->different/path/to/YourModels.cs
-->Startup.cs // add a simple startup class
-->project.json
简单的Startup类(App.DataAccess\Startup.cs
):
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Data.Entity;
using Microsoft.Dnx.Runtime;
using Microsoft.Framework.Configuration;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Logging;
namespace App.DataAccess
{
public class Startup
{
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
var builder = new ConfigurationBuilder(appEnv.ApplicationBasePath)
.AddJsonFile("../App.Web/config.json"); // path to your original configuration in Web project
Configuration = builder.Build();
}
public IConfiguration Configuration { get; set; }
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
}
}
}
在App.DataAccess(App.DataAccess/project.json
)中修改project.json:
{
"version": "1.0.0-*",
"description": "App.DataAccess Class Library",
"authors": [ "Author" ],
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": "",
"frameworks": {
"dnx451": { }
},
"dependencies": {
"EntityFramework.Commands": "7.0.0-beta7",
"Microsoft.Framework.Configuration.Json": "1.0.0-beta7",
},
"commands": {
"ef": "EntityFramework.Commands" // this line is important, it will give you access to 'dnx ef' in command line
}
}
你所要做的就是转到App.DataAccess
并使用dnx ef
:
cd App.DataAccess
dnx ef migrations add NewMigration
dnx ef migrations remove
dnx ef database update
dnx ef ...
答案 1 :(得分:10)
答案 2 :(得分:2)
对于ASP.NET Core 1.0和EF Core 1.0
假设我们想将上下文移到Core1RtmEmptyTest.DataLayer
项目。
首先通过修改其project.json
文件来启用此子项目的EF工具:
{
// same as before
"tools": {
"Microsoft.EntityFrameworkCore.Tools": {
"version": "1.0.0-preview2-final",
"imports": [
"portable-net45+win8"
]
}
},
// same as before
}
然后从这个新项目的根目录(而不是从主项目的根目录)运行命令
D:\path\Core1RtmEmptyTest\src\Core1RtmEmptyTest.DataLayer>dotnet ef --startup-project ../Core1RtmEmptyTest/ migrations add InitialDatabase
这里我们也应该指定startup-project
。
最后更新数据库
D:\path\Core1RtmEmptyTest\src\Core1RtmEmptyTest.DataLayer>dotnet ef --startup-project ../Core1RtmEmptyTest/ database update
答案 3 :(得分:0)
我有一个解决方法,但我使用的是EFCore 1.0.0,因此您必须进行迁移。在代码片段下方,您需要使其工作:
我们的想法是拥有一个中央datacontext:MigrationsDataContext
来处理整个数据库迁移。因此,您可以将此迁移放在专用于迁移数据库的独立项目中。您只需要MigrationsDataContext
查看包含所需datacontexts的其他项目。这样,您可以实例化每个其他datacontext并调用OnModelCreating
方法手动传递当前DbContext的ModelBuilder
作为参数。
public class MigrationsDataContext : DbContext
{
private readonly Dictionary<Type, DbContextOptions> dbCtxOpts;
private readonly IEnumerable<Type> dbCtxTypes = new[] {
typeof(CoreDataContext),
typeof(DbContext1),
typeof(DbContext2),
};
public MigrationsDataContext(DbContextOptions<MigrationsDataContext> options,
IEnumerable<DbContextOptions> dbCtxOpts)
:base(options)
{
this.dbCtxOpts = dbCtxOpts
.GroupBy(o => o.ContextType)
.ToDictionary(g => g.Key, g => g.First());
}
public MigrationsDataContext()
{ }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
foreach (var db in dbCtxTypes.Select(t => new { Type = t, Instance = Activator.CreateInstance(t, dbCtxOpts[t]) }))
{
var configurator = db.Type.GetMethod(nameof(OnModelCreating), BindingFlags.NonPublic | BindingFlags.Instance);
configurator.Invoke(db.Instance, new[] { builder });
}
}
}
为了从构造函数接收所有DbContextOptions,您需要将DbContextOptions<T>
的整个包注册为DbContextOptions
这是通过在ConfigureServices
Startup.cs
中调用以下方法来实现的}:
public static IServiceCollection AddBundle<T>(this IServiceCollection services)
{
var baseType = typeof(T);
var bundle = services
.Where(d => baseType.GetTypeInfo().IsAssignableFrom(d.ServiceType))
.Select(d => d.ServiceType)
.ToList();
foreach (var ctxType in bundle)
services.AddScoped(baseType, s => s.GetService(ctxType));
return services;
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services
.AddEntityFrameworkSqlServer()
.AddDbContext<CoreDataContext>(ConfigEf)
.AddDbContext<DbContext1>(ConfigEf)
.AddDbContext<DbContext2>(ConfigEf)
.AddDbContext<MigrationsDataContext>(ConfigEf)
.AddBundle<DbContextOptions>()
.AddBundle<DbContext>();
...
这就是全部。现在,您以这种方式管理迁移:
移至您的迁移项目,与MyWebApp项目相邻,
`$> dotnet ef --startup-project ../MyWebApp migrations add Initial --context Migrations.MigrationsDataContext`
希望得到这个帮助。