如何防止在 Entity Framework Core 6 中创建迁移并将其应用于指定的 dbContext?

发布于 2025-01-09 10:31:50 字数 6024 浏览 0 评论 0原文

我在读取写入端使用两个数据库上下文,指向相同的数据库架构。

ReadDbContextWriteDbContext 分别定义了自己的模型。

由于这两种上下文配置中的关系、表名以及最后的数据库都是相同的,因此只有其中之一可以构建数据库。

有没有办法禁用为指定数据库上下文应用创建的迁移的能力?更进一步,是否有可能禁止迁移创建?

我尝试将 Database.SetInitializer(null) 添加到 DbContext 构造函数,但这似乎在 EF Core 6 中不起作用。

为了更好地理解,您可以查看下面的代码。

ReadDbContext

internal sealed class ReadDbContext : DbContext
{
    public DbSet<UserReadModel> Users => Set<UserReadModel>();
    public DbSet<RoleReadModel> Roles => Set<RoleReadModel>();
    public DbSet<PermissionReadModel> Permissions => Set<PermissionReadModel>();

    public ReadDbContext(DbContextOptions<ReadDbContext> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("user-manager");

        var configuration = new ReadConfiguration();

        modelBuilder.ApplyConfiguration<UserReadModel>(configuration);
        modelBuilder.ApplyConfiguration<RoleReadModel>(configuration);
        modelBuilder.ApplyConfiguration<PermissionReadModel>(configuration);
    }
}

WriteDbContext

internal sealed class WriteDbContext : DbContext
{
    public DbSet<User> Users => Set<User>();
    public DbSet<Role> Roles => Set<Role>();
    public DbSet<Permission> Permissions => Set<Permission>();

    public WriteDbContext(DbContextOptions<WriteDbContext> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("user-manager");

        var configuration = new WriteConfiguration();

        modelBuilder.ApplyConfiguration<User>(configuration);
        modelBuilder.ApplyConfiguration<Role>(configuration);
        modelBuilder.ApplyConfiguration<Permission>(configuration);
    }
}

ReadConfiguration

internal sealed class ReadConfiguration : IEntityTypeConfiguration<UserReadModel>, IEntityTypeConfiguration<RoleReadModel>,
    IEntityTypeConfiguration<PermissionReadModel>
{
    private readonly ValueConverter<UserNameReadModel, string> _userNameConverter = new(un => un.ToString(), un =>  new UserNameReadModel(un));
    
    public void Configure(EntityTypeBuilder<UserReadModel> builder)
    {
        builder.ToTable("Users");
        builder.HasKey(u => u.Id);

        builder
            .HasMany(u => u.Roles)
            .WithMany(r => r.Users)
            .UsingEntity("UsersRoles");

        builder
            .Property(u => u.Name)
            .HasConversion(_userNameConverter!);
    }

    public void Configure(EntityTypeBuilder<RoleReadModel> builder)
    {
        builder.ToTable("Roles");
        builder.HasKey(r => r.Id);

        builder
            .HasMany(r => r.Permissions)
            .WithMany(p => p.Roles)
            .UsingEntity("RolesPermissions");
    }

    public void Configure(EntityTypeBuilder<PermissionReadModel> builder)
    {
        builder.ToTable("Permissions");
        builder.HasKey(p => p.Id);
    }
}

WriteConfiguration

internal sealed class WriteConfiguration : IEntityTypeConfiguration<User>, IEntityTypeConfiguration<Role>,
    IEntityTypeConfiguration<Permission>
{
    private readonly ValueConverter<UserId, Guid> _userIdConverter = new(u => u.Value, u => u);
    private readonly ValueConverter<RoleId, Guid> _roleIdConverter = new(r => r.Value, r => r);
    private readonly ValueConverter<UserName, string> _userNameConverter = new(un => un.ToString(), un => UserName.Create(un));
    private readonly ValueConverter<RoleName, string> _roleNameConverter = new(rn => rn.ToString(), rn => RoleName.Create(rn));
    private readonly ValueConverter<Email, string> _emailConverter = new(e => e.ToString(), e => Email.Create(e));
    private readonly ValueConverter<Password, string> _passwordConverter = new(p => p.ToString(), p => Password.Create(p));

    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder.ToTable("Users");
        builder.HasKey(u => u.Id);
        builder
            .Property(r => r.Id)
            .HasConversion(_userIdConverter);
        
        builder
            .Property(typeof(UserName), "_name")
            .HasConversion(_userNameConverter)
            .HasColumnName("Name");
        
        builder
            .Property(typeof(Email), "_email")
            .HasConversion(_emailConverter)
            .HasColumnName(nameof(Email));
        
        builder
            .Property(typeof(Password), "_password")
            .HasConversion(_passwordConverter)
            .HasColumnName(nameof(Password));
        
        builder
            .HasMany(typeof(Role), "_roles")
            .WithMany("_users")
            .UsingEntity("UsersRoles");
    }

    public void Configure(EntityTypeBuilder<Role> builder)
    {
        builder.ToTable("Roles");
        builder.HasKey(r => r.Id);
        builder
            .Property(r => r.Id)
            .HasConversion(_roleIdConverter);
        
        builder
            .Property(typeof(RoleName), "_name")
            .HasConversion(_roleNameConverter)
            .HasColumnName("Name");

        builder.HasMany(typeof(Permission), "_permissions");
    }

    public void Configure(EntityTypeBuilder<Permission> builder)
    {
        builder.ToTable("Permissions");
        builder.Property<Guid>("Id");
        builder.Property<string>("Name");
    }
}

I'm using two db contexts for read and write side, poinitng to the same db schema.

ReadDbContext and WriteDbContext have their own read and write models defined respectively.

Since the relations, table names and finally the database are the same in both of these contexts configuration, only the one of them can scaffold the database.

Is there any way to disable the ability of applying created migrations for specified db conext? Going further, is there a possibility to even disallow the migrations creating?

I tried to add Database.SetInitializer<TContext>(null) to DbContext constructor, but that doesn't seem to work in EF Core 6.

For better understanding you can checkout the code below.

ReadDbContext

internal sealed class ReadDbContext : DbContext
{
    public DbSet<UserReadModel> Users => Set<UserReadModel>();
    public DbSet<RoleReadModel> Roles => Set<RoleReadModel>();
    public DbSet<PermissionReadModel> Permissions => Set<PermissionReadModel>();

    public ReadDbContext(DbContextOptions<ReadDbContext> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("user-manager");

        var configuration = new ReadConfiguration();

        modelBuilder.ApplyConfiguration<UserReadModel>(configuration);
        modelBuilder.ApplyConfiguration<RoleReadModel>(configuration);
        modelBuilder.ApplyConfiguration<PermissionReadModel>(configuration);
    }
}

WriteDbContext

internal sealed class WriteDbContext : DbContext
{
    public DbSet<User> Users => Set<User>();
    public DbSet<Role> Roles => Set<Role>();
    public DbSet<Permission> Permissions => Set<Permission>();

    public WriteDbContext(DbContextOptions<WriteDbContext> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("user-manager");

        var configuration = new WriteConfiguration();

        modelBuilder.ApplyConfiguration<User>(configuration);
        modelBuilder.ApplyConfiguration<Role>(configuration);
        modelBuilder.ApplyConfiguration<Permission>(configuration);
    }
}

ReadConfiguration

internal sealed class ReadConfiguration : IEntityTypeConfiguration<UserReadModel>, IEntityTypeConfiguration<RoleReadModel>,
    IEntityTypeConfiguration<PermissionReadModel>
{
    private readonly ValueConverter<UserNameReadModel, string> _userNameConverter = new(un => un.ToString(), un =>  new UserNameReadModel(un));
    
    public void Configure(EntityTypeBuilder<UserReadModel> builder)
    {
        builder.ToTable("Users");
        builder.HasKey(u => u.Id);

        builder
            .HasMany(u => u.Roles)
            .WithMany(r => r.Users)
            .UsingEntity("UsersRoles");

        builder
            .Property(u => u.Name)
            .HasConversion(_userNameConverter!);
    }

    public void Configure(EntityTypeBuilder<RoleReadModel> builder)
    {
        builder.ToTable("Roles");
        builder.HasKey(r => r.Id);

        builder
            .HasMany(r => r.Permissions)
            .WithMany(p => p.Roles)
            .UsingEntity("RolesPermissions");
    }

    public void Configure(EntityTypeBuilder<PermissionReadModel> builder)
    {
        builder.ToTable("Permissions");
        builder.HasKey(p => p.Id);
    }
}

WriteConfiguration

internal sealed class WriteConfiguration : IEntityTypeConfiguration<User>, IEntityTypeConfiguration<Role>,
    IEntityTypeConfiguration<Permission>
{
    private readonly ValueConverter<UserId, Guid> _userIdConverter = new(u => u.Value, u => u);
    private readonly ValueConverter<RoleId, Guid> _roleIdConverter = new(r => r.Value, r => r);
    private readonly ValueConverter<UserName, string> _userNameConverter = new(un => un.ToString(), un => UserName.Create(un));
    private readonly ValueConverter<RoleName, string> _roleNameConverter = new(rn => rn.ToString(), rn => RoleName.Create(rn));
    private readonly ValueConverter<Email, string> _emailConverter = new(e => e.ToString(), e => Email.Create(e));
    private readonly ValueConverter<Password, string> _passwordConverter = new(p => p.ToString(), p => Password.Create(p));

    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder.ToTable("Users");
        builder.HasKey(u => u.Id);
        builder
            .Property(r => r.Id)
            .HasConversion(_userIdConverter);
        
        builder
            .Property(typeof(UserName), "_name")
            .HasConversion(_userNameConverter)
            .HasColumnName("Name");
        
        builder
            .Property(typeof(Email), "_email")
            .HasConversion(_emailConverter)
            .HasColumnName(nameof(Email));
        
        builder
            .Property(typeof(Password), "_password")
            .HasConversion(_passwordConverter)
            .HasColumnName(nameof(Password));
        
        builder
            .HasMany(typeof(Role), "_roles")
            .WithMany("_users")
            .UsingEntity("UsersRoles");
    }

    public void Configure(EntityTypeBuilder<Role> builder)
    {
        builder.ToTable("Roles");
        builder.HasKey(r => r.Id);
        builder
            .Property(r => r.Id)
            .HasConversion(_roleIdConverter);
        
        builder
            .Property(typeof(RoleName), "_name")
            .HasConversion(_roleNameConverter)
            .HasColumnName("Name");

        builder.HasMany(typeof(Permission), "_permissions");
    }

    public void Configure(EntityTypeBuilder<Permission> builder)
    {
        builder.ToTable("Permissions");
        builder.Property<Guid>("Id");
        builder.Property<string>("Name");
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜光 2025-01-16 10:31:50

您可以从迁移中排除:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Entity<ApplicationUser>().ToTable("ApplicationUsers", t => t.ExcludeFromMigrations());
}

You can exclude from migrations:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Entity<ApplicationUser>().ToTable("ApplicationUsers", t => t.ExcludeFromMigrations());
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文