【问题标题】: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”参数执行命令时,我不知道为什么会出现此错误。

我无法从其他程序集创建初始迁移,我已经搜索了有关它的信息但没有得到任何结果。

有人遇到过类似的问题吗?

【问题讨论】:

标签: c# asp.net-core entity-framework-core entity-framework-migrations


【解决方案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 docsIDesignTimeDbContextFactory 是:

    用于创建派生 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

    【解决方案5】:

    我跑了同样的问题,发现this

    您是否尝试在类库上运行迁移?我也是。结果这还不支持,所以我们需要解决它。

    编辑:我在this git repo找到了解决方案

    【讨论】:

    • 谢谢。我看到了这个解决方案,但它似乎有点强迫,但到目前为止,它是我看到它工作的唯一解决方案。我会点击链接获取新闻
    • 非常感谢!! services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), x => x.MigrationsAssembly("ClasslibraryGoesHere")));
    【解决方案6】:

    目前我认为 EF 只支持在尚未在类库上的项目上添加迁移。

    对于想要将迁移添加到项目中特定文件夹的其他人来说,只是旁注

    EF CLI 还不支持这个。我试过--data-dir,但没用。

    唯一有效的方法是使用包管理器控制台:

    1. 选择您的默认项目
    2. 使用-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+)

      有同样的问题。 这是我所做的:

      1. 从将包含迁移的项目 (Project.B) 中引用包含 DbContext (Project.A) 的项目。

      2. 将现有迁移从 Project.A 移动到 Project.B (如果您没有迁移 - 先创建它们)

      3. 在 Project.A 中配置迁移程序集

      options.UseSqlServer( 连接字符串, x => x.MigrationsAssembly("Project.B"));

      假设您的项目位于同一个父文件夹中:

      1. 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 Mirsaeedithis 回答和来自Ales Potocnik Hahoninathis 评论,我也设法使添加迁移工作。

        我使用 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 数据

                1. Web是我的创业项目
                2. 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(形成问题示例)应该是启动项目。

                    希望对某人有所帮助:)

                    【讨论】:

                    • 依赖注入需要一个启动项目。
                    猜你喜欢
                    • 1970-01-01
                    • 2013-05-16
                    • 1970-01-01
                    • 1970-01-01
                    • 2020-06-21
                    • 1970-01-01
                    • 2021-05-15
                    • 2019-04-30
                    • 1970-01-01
                    相关资源
                    最近更新 更多