EntityFramework 7(EF7)迁移。 DbContext和StartUp Project位于不同的程序集中

时间:2015-08-07 06:00:54

标签: asp.net-core-mvc entity-framework-core

我尝试在EF7中使用entityframework.commands进行迁移。但我的DbContext与启动项目处于不同的程序集(asp.net mvc是一个启动项目,而Core.Implementation有一个DbContex)。

dnx。 ef migration添加MyMigration -c MyContext

System.InvalidOperationException:没有名为' MyContext'的DbContext被发现了。

我尝试使用命名空间指向其他程序集,但它也没有工作。有可能吗?或者我只需要将我的上下文放在ef7命令所在的汇编中?

4 个答案:

答案 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.WebApp.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)

每期#639#2256#2293#2294#2357#2553&amp; #2748,我们在该领域还有一些工作要做。 : - )

答案 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`

希望得到这个帮助。