Ответ 1
По вопросам # 639, # 2256, # 2293, # 2294, # 2357, # 2553 и # 2748, у нас есть немного работы, которые нужно сделать в этой области.: -)
Я пытаюсь использовать миграции в EF7 с помощью entityframework.commands. Но мой DbContext находится в другой сборке с проектом запуска (asp.net mvc - это начальный проект, а Core.Implementation имеет DbContex).
dnx. ef migration добавить MyMigration -c MyContext
System.InvalidOperationException: не найден DbContext с именем MyContext.
Я попытался использовать пространство имен, чтобы указать на другую сборку, но это тоже не сработало. Это вообще возможно? Или мне просто нужно поставить свой контекст в сборку, где команда ef7?
По вопросам # 639, # 2256, # 2293, # 2294, # 2357, # 2553 и # 2748, у нас есть немного работы, которые нужно сделать в этой области.: -)
ИЗМЕНИТЬ
Поскольку 1.0.0-rc1-final (возможно, раньше), этот workaroud не нужен
App.DataAccess/Startup.cs
(просто удалите его, если вы использовали обходной путь ниже)App.Web
)-p
paramater), содержащий миграции: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
КОНЕЦ РЕДАКТИРОВАНИЯ
Я нашел обходное решение для этого
Предположим, что у вас есть 2 проекта: App.Web
и App.DataAccess
Вы можете добавить очень простой класс Startup к вашему App.DataAccess
:
>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
Простой класс запуска (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)
{
}
}
}
Чем изменен ваш project.json в App.DataAccess(App.DataAccess/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 ...
Для ASP.NET Core 1.0 и EF Core 1.0
Предположим, что мы хотим переместить наш контекст в проект Core1RtmEmptyTest.DataLayer
.
Сначала включите инструменты EF для этого субпроекта, изменив его файл project.json
:
{
// 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
У меня есть обходной путь, но я использую EFCore 1.0.0, поэтому вы должны выполнить миграцию. Ниже кодовых папок вам необходимо заставить его работать:
Идея состоит в том, чтобы иметь центральный datacontext: MigrationsDataContext
для обработки целых миграций базы данных. Таким образом, вы можете разместить эту миграцию в отдельном проекте, предназначенном только для миграции базы данных. Вы должны сделать MigrationsDataContext
для просмотра других проектов, содержащих требуемые типы данных. Таким образом, вы можете создать экземпляр 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`
Надеюсь на эту помощь.