在添加迁移期间忽略引用的程序集中的实体

时间:2016-06-27 11:09:15

标签: c# .net entity-framework entity-framework-6

我有一个项目,我的域在一堆独立的程序集和DbContexts之间分开,所有这些都使用相同的底层Sql Server数据库。这些程序集不会相互引用,只有一个例外 - 其中一个包含可能称为共享实体的内容,这些内容对所有其他域都是通用的,有时也称为导航属性。简化示例:

// Shared.dll
namespace Shared
{
   // Shared POCO
   class Hero
   {
       public string Name { get; set; }
       public string Description { get; set; }
   }

   class MyDbContext : DbContext
   {
       public virtual DbSet<Hero> Heroes { get; set; }
   } 

   internal sealed class MyDbContextConfiguration : DbMigrationsConfiguration<MyDbContext>
   {
       public MyDbContextConfiguration ()
       {
           AutomaticMigrationsEnabled = false;
           MigrationsDirectory = @"Migrations\MyDbContext";
           ContextKey = "Shared";
       }
   }
}

// Game.dll <- references Shared.dll
namespace Game
{
   // Individual POCO
   class Mission
   {
       public string Name { get; set; }
       public virtual ICollection<Hero> Protagonists { get; set; }
   }

   class MyDbContext : DbContext
   {
       public virtual DbSet<Mission> Missions { get; set; }
   } 

   internal sealed class MyDbContextConfiguration : DbMigrationsConfiguration<MyDbContext>
   {
       public MyDbContextConfiguration ()
       {
           AutomaticMigrationsEnabled = false;
           MigrationsDirectory = @"Migrations\MyDbContext";
           ContextKey = "Game";
       }
   }
}

问题是,当我通过Hero导航属性在 Game.dll 程序集模型中引用ICollection<Hero> Protagonists POCO时,调用:

add-migration Test -ProjectName:Game -ConfigurationTypeName MyDbContextConfiguration -StartUpProjectName Main

最终会创建DbMigration,其中包含来自引用的 Shared.dll 组合的Hero实体的更改。

    public partial class Test : DbMigration
    {
        public override void Up()
        {
            AddColumn("shared.Heroes", "Name", c => c.String());
            AddColumn("shared.Heroes", "Description", c => c.String());
            ...

如何限制add-migration仅监视位于已定义DbContext的程序集中的实体的更改?换句话说,当针对 Games.dll 运行add-migration时,我想忽略对 Shared.dll 中的实体所做的任何更改。

还可以通过命名空间或数据库对象架构来限制。我只是不希望任何位于引用程序集中的实体的更改都包含在我的迁移中,因为所有迁移都是按程序集维护的。

1 个答案:

答案 0 :(得分:3)

我有一个技巧,你可以轻松使用它(在你的MyDbContext中使用modelBuilder.Ignore),如果你熟悉Bounded Contexts,那么这对你来说应该不是什么新东西:

你的DbContext:

 public class MyDbContext : DbContext
 {
   private readonly bool _isMigrationMode;

   public MyDbContext()
   {
     // This used by migration default and you can give the connection string in the command line.
     _isMigrationMode = true;
   }

   // isMigrationMode: I have give it here as an optional parameter, in case, if you want to create the migration from the code.
   public MyDbContext(string connectionString, bool isMigrationMode = false)
         : base("name=" + connectionString)
   {
     _isMigrationMode = isMigrationMode;
   }
   protected override void OnModelCreating(DbModelBuilder modelBuilder)
   {
     if (_isMigrationMode)
     {
       modelBuilder.Ignore<Hero>();
     }

     base.OnModelCreating(modelBuilder);
   }

   public DbSet<Mission> Missions { get; set; }
 }

现在您可以从命令行添加迁移,如:

add-migration FirstDb -ConfigurationTypeName配置-CONNECTIONSTRINGNAME YourConnectionString

这是您在示例中使用的类似实体的输出

 public partial class FirstDb : DbMigration
 {
     public override void Up()
     {
         CreateTable(
             "dbo.Missions",
             c => new
                 {
                     MissionId = c.Long(nullable: false, identity: true),
                     Amount = c.Int(nullable: false),
                     Amount2 = c.Int(nullable: false),
                     HeroId = c.Long(nullable: false),
                 })
             .PrimaryKey(t => t.MissionId);

     }

     public override void Down()
     {
         DropTable("dbo.Missions");
     }
 }