使用不同的程序集

时间:2016-08-01 18:29:21

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

我在ASP.NET CORE 1.0.0中做了一个项目,我正在使用EntityFrameworkCore。我有单独的程序集,我的项目结构如下所示:

ProjectSolution
   -src
      -1 Domain
         -Project.Data
      -2 Api
         -Project.Api

我的Project.ApiStartup

public void ConfigureServices(IServiceCollection services)
    {            
        services.AddDbContext<ProjectDbContext>();

        services.AddIdentity<IdentityUser, IdentityRole>()
                .AddEntityFrameworkStores<ProjectDbContext>()
                .AddDefaultTokenProviders();
    }

我的Project.Data项目中有DbContext

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);
    }
}

当我尝试进行初始迁移时,我收到此错误:

  

&#34;您的目标项目&#39; Project.Api&#39;与您的迁移程序集“Project.Data&#39;”不匹配。更改目标项目或更改迁移程序集。   使用DbContextOptionsBuilder更改迁移程序集。例如。 options.UseSqlServer(connection,b =&gt; b.MigrationsAssembly(&#34; Project.Api&#34;))。默认情况下,迁移程序集是包含DbContext的程序集。   使用程序包管理器控制台的默认项目下拉列表或执行&#34; dotnet ef&#34;将目标项目更改为迁移项目。来自包含迁移项目的目录。&#34;

在看到此错误后,我尝试执行Project.Api中的此命令:

  

dotnet ef --startup-project ../Project.Api --assembly&#34; ../../ 1 Data / Project.Data&#34;迁移添加初始

我收到了这个错误:

  

&#34;意外的值&#39; ../../ 1 Domain / Project.Data&#39;选项&#39;组装&#39;&#34;

我没有t know why I get this error, when I try to execute the command with the - assembly`参数。

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

有人有类似的问题吗?

16 个答案:

答案 0 :(得分:35)

所有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"))

答案 1 :(得分:16)

我遇到了同样的问题,直到我注意到在包管理器控制台顶部栏=&gt; &#34;默认项目&#34;应该是&#34; Project.Data&#34;而不是&#34; Project.API&#34;。

一旦你定位了&#34; Project.Data&#34;从下拉列表中运行迁移你应该没问题。

答案 2 :(得分:8)

使用EF Core 2,您可以轻松地将 Web 项目与 Data (DbContext)项目分开。实际上,您只需要实现 IDesignTimeDbContextFactory 接口。根据{{​​3}}, IDesignTimeDbContextFactory 是:

  

用于创建派生DbContext实例的工厂。实现这一点   接口,为没有的上下文类型启用设计时服务   有一个公共默认构造函数。在设计时,派生DbContext   可以创建实例以启用特定的设计时间   迁移等经验。设计时服务会   自动发现该接口的实现   启动程序集或与派生上下文相同的程序集。

在底部的代码片段中,您可以看到我在 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项目并在Package Manager控制台中选择我的 Data 项目来初始化EF迁移。

Add-Migration initial

您可以找到更多详情Microsoft docs。但是,此博客文章使用的是废弃的类,而不是 IDesignTimeDbContextFactory

答案 3 :(得分:5)

我遇到了同样的问题并找到this

我们是您尝试在类库上运行迁移?我也是如此。事实证明这还不支持,所以我们需要解决它。

编辑:我在this git repo

找到了解决方案

答案 4 :(得分:5)

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

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

EF CLI 尚不支持此功能。我试过了--data-dir,但它没有用。

唯一有效的方法是使用Package Manager控制台:

  1. 选择您的默认项目
  2. 使用-OutputDir命令参数,.e.g。,Add-Migration InitConfigurationStore -OutputDir PersistedStores/ConfigurationStore命令会将mgiry输出到我项目中的文件夹'PersistedStores / ConfigurationStore'。
  3. 截至10/12/2017的更新

    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)
            )
       );
    
       ...
    }
    

答案 5 :(得分:2)

以下命令对我有用。我正在使用VS Code,并运行以下命令:

SocialApp.Models> dotnet ef migrations add InitialMigartion --startup-project ../SocialApp.API

礼貌:https://github.com/bricelam/Sample-SplitMigrations

答案 6 :(得分:1)

(ASP.NET Core 2 +)

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

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

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

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

options.UseSqlServer( connectionString, x => x.MigrationsAssembly(“ Project.A”)))

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

  1. dotnet ef migrations add Init --project ../AskGoo.Data -c DbContext

现在迁移到Project.B

来源:Microsoft

答案 7 :(得分:1)

这是针对EF Core 3.x。

基于thisEhsan Mirsaeedi答案和thisAles Potocnik Hahonina评论,我也设法使Add-Migration起作用。

我将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) });

现在可以这样使用: '添加迁移-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
                ...
            }
        }

希望我能帮助一个人。

干杯

汤姆

答案 8 :(得分:1)

您要做的就是像这样修改您的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项目设置为默认启动项目,方法是在解决方案资源管理器中右键单击该项目,然后选择“设置为启动项目”

答案 9 :(得分:1)

我的是一个单一的 .net 核心网络项目。

必须确保 1 件事来解决此错误。项目中必须存在以下类。

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 的项目。下载该网络应用程序。

答案 10 :(得分:0)

我也面临着类似的问题,尽管答案似乎很直接,但以某种方式却无法解决。 我的答案类似于@Ehsan Mirsaeedi,但DbContextFactory类的更改很小。我没有在API的Startup类中添加迁移程序集名称,而是在DbContextFactory类中提到过,该类是Data项目(类库)的一部分。

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。我想肯定有一些接线问题。

答案 11 :(得分:0)

Add-Migration NewMigration -Project MyApp.Migrations

答案 12 :(得分:0)

使用CLI命令添加迁移:

dotnet ef migrations add NewMigration --project YourAssemplyName

使用PMC命令添加迁移:

Add-Migration NewMigration -Project YourAssemplyName

答案 13 :(得分:0)

我已通过在Startup.cs中添加以下行来解决此问题。希望它也能对您有所帮助。我用过Postgres,可以用Sql Server代替

- hosts: all
  vars:
    test: "Test Successfull"
    repo_dir: /media/disk1/sandbox/xyz
    path: /media/disk1/sandbox/xyz/api
  tasks:
   - debug:
         msg: "{{ test.split()[0] }} {{ test.split()[1] }}"

   - name: Running npm install in directory "{{ path }} and {{ repo_dir }}/lib as well"
     command: npm install
     args:
         chdir: "{{ item }}"
     loop:
         - "{{ path }}"
         - "{{ repo_dir }}/lib"
     become_user: yash
     become: yes

答案 14 :(得分:0)

dotnet ef update-database --startup-project Web --project 数据

  1. Web 是我的启动项目
  2. Data 是我的类库

答案 15 :(得分:-1)

针对所有拥有 多个启动项目 的人。

请注意,您需要将目标项目设置为启动项目-Project.Api(形成问题示例)应该是启动项目。

希望对某人有帮助:)