使用不同的程序集添加迁移

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 didnt 什么也得不到 不要使用 --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 doesnt允许执行命令,我只能在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 实现中引用上下文并且它可以工作。唯一的缺点是您不能运行“迁移添加”命令,因为它会尝试将迁移添加到数据库上下文所在的位置。您只能以这种方式运行“ef database update”和“ef database drop”。 您使用过.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(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), x => x.MigrationsAssembly("ClasslibraryGoesHere")));【参考方案6】:

目前我认为 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(形成问题示例)应该是启动项目。

希望对某人有所帮助:)

【讨论】:

依赖注入需要一个启动项目。

以上是关于使用不同的程序集添加迁移的主要内容,如果未能解决你的问题,请参考以下文章

Swinject:迁移到程序集

Maven 程序集:添加同一工件的不同版本

Code-First,当我进行启用迁移时,我得到“在程序集'DOC'中找不到上下文类型”

您必须添加对程序集 mscorlib 的引用,版本=4.0.0

Java程序员学深度学习 DJL上手9 在CIFAR-10数据集使用风格迁移学习

Java程序员学深度学习 DJL上手9 在CIFAR-10数据集使用风格迁移学习