ABP VNext种子数据按顺序插入
ABP VNext种子数据按顺序插入
- 1.Domain层
- 1.1 新加Author和Book实体
- 1.2 CustomDataSeedDbMigrationService新加方法
- 1.3新加ISowSeed接口
- 1.4 作者和图书种子数据逻辑
- 1.5 新加CustomDataSeedDataSeederContributor
- 2.EntityFrameworkCore
- 2.1 CustomDataSeedDbContext
- 2.2 生成迁移脚本
- 2.3 应用到数据库
- 3.源码
1.Domain层
1.1 新加Author和Book实体
public class Author : FullAuditedAggregateRoot<Guid>{public string Name { get; private set; }public DateTime BirthDate { get; set; }public string ShortBio { get; set; }private Author(){/* This constructor is for deserialization / ORM purpose */}internal Author(Guid id,[NotNull] string name,DateTime birthDate,[CanBeNull] string shortBio = null): base(id){SetName(name);BirthDate = birthDate;ShortBio = shortBio;}internal Author ChangeName([NotNull] string name){SetName(name);return this;}private void SetName([NotNull] string name){Name = Check.NotNullOrWhiteSpace(name,nameof(name),maxLength: 100);}}
public class Book : AuditedAggregateRoot<Guid>, IMultiTenant{public string Name { get; set; }public BookType Type { get; set; }public DateTime PublishDate { get; set; }public float Price { get; set; }public Guid AuthorId { get; set; }public Guid? TenantId { get; set; }}
1.2 CustomDataSeedDbMigrationService新加方法
CustomDataSeedDbMigrationService中的MigrateAsync方法中添加自定义的种子数据插入方法:
private async Task CustomSeedDataAsync(bool isUseCustomRank = true){var dataSeedContext = new DataSeedContext().WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, "admin@ycims.com").WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, "ycqwe123").WithProperty("IsUseCustomRank", isUseCustomRank);await _dataSeeder.SeedAsync(dataSeedContext);}
MigrateAsync完整代码:
public async Task MigrateAsync(){var initialMigrationAdded = AddInitialMigrationIfNotExist();if (initialMigrationAdded){return;}Logger.LogInformation("Started database migrations...");await MigrateDatabaseSchemaAsync();await SeedDataAsync();//自定义顺序插入种子数据await CustomSeedDataAsync();Logger.LogInformation($"Successfully completed host database migrations.");var tenants = await _tenantRepository.GetListAsync(includeDetails: true);var migratedDatabaseSchemas = new HashSet<string>();foreach (var tenant in tenants){using (_currentTenant.Change(tenant.Id)){if (tenant.ConnectionStrings.Any()){var tenantConnectionStrings = tenant.ConnectionStrings.Select(x => x.Value).ToList();if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings)){await MigrateDatabaseSchemaAsync(tenant);migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings);}}await SeedDataAsync(tenant);}Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations.");}Logger.LogInformation("Successfully completed all database migrations.");Logger.LogInformation("You can safely end this process...");}
1.3新加ISowSeed接口
public interface ISowSeed{/// <summary>/// 种子执行顺序(从小到大执行)/// </summary>int Sort { get; set; }Task ExecAsync(DataSeedContext context);}
1.4 作者和图书种子数据逻辑
这里作者的数据顺序为1,图书为2
public class AuthorSowSeed : ISowSeed, ITransientDependency{private readonly IRepository<Author, Guid> _authorRepository;private readonly IGuidGenerator _guidGenerator;public AuthorSowSeed(IRepository<Author, Guid> authorRepository, IGuidGenerator guidGenerator){_authorRepository = authorRepository;_guidGenerator = guidGenerator;}public int Sort { get; set; } = 1;public async Task ExecAsync(DataSeedContext context){await this.MockData();}private async ValueTask MockData(){var author1 = await _authorRepository.FindAsync(s => s.Name == "George Orwell");if (author1 == null){await _authorRepository.InsertAsync(new Author(_guidGenerator.Create(), "George Orwell", new DateTime(1903, 06, 25), "Orwell produced literary criticism and poetry, fiction and polemical journalism; and is best known for the allegorical novella Animal Farm (1945) and the dystopian novel Nineteen Eighty-Four (1949)."), autoSave: true);}var author2 = await _authorRepository.FindAsync(s => s.Name == "Douglas Adams");if (author2 == null){var douglas = await _authorRepository.InsertAsync(new Author(_guidGenerator.Create(), "Douglas Adams", new DateTime(1952, 03, 11), "Douglas Adams was an English author, screenwriter, essayist, humorist, satirist and dramatist. Adams was an advocate for environmentalism and conservation, a lover of fast cars, technological innovation and the Apple Macintosh, and a self-proclaimed 'radical atheist'."), autoSave: true);}}}public class BookSowSeed : ISowSeed, ITransientDependency{private readonly IRepository<Book, Guid> _bookRepository;private readonly IRepository<Author, Guid> _authorRepository;public BookSowSeed(IRepository<Book, Guid> bookRepository, IRepository<Author, Guid> authorRepository){_bookRepository = bookRepository;_authorRepository = authorRepository;}public int Sort { get; set; } = 2;public async Task ExecAsync(DataSeedContext context){await this.MockData();}private async ValueTask MockData(){var book1 = await _bookRepository.FindAsync(s => s.Name == "1984");if (book1 == null){await _bookRepository.InsertAsync(new Book{AuthorId = (await _authorRepository.FindAsync(s => s.Name == "George Orwell")).Id, // SET THE AUTHORName = "1984",Type = BookType.Dystopia,PublishDate = new DateTime(1949, 6, 8),Price = 19.84f},autoSave: true);}var book2 = await _bookRepository.FindAsync(s => s.Name == "The Hitchhiker's Guide to the Galaxy");if (book2 == null){await _bookRepository.InsertAsync(new Book{AuthorId = (await _authorRepository.FindAsync(s => s.Name == "Douglas Adams")).Id, // SET THE AUTHORName = "The Hitchhiker's Guide to the Galaxy",Type = BookType.ScienceFiction,PublishDate = new DateTime(1995, 9, 27),Price = 42.0f},autoSave: true);}}}
1.5 新加CustomDataSeedDataSeederContributor
internal class CustomDataSeedDataSeederContributor : IDataSeedContributor, ITransientDependency{private readonly IEnumerable<ISowSeed> _dataSowSeeds;public CustomDataSeedDataSeederContributor(IEnumerable<ISowSeed> dataSowSeeds){this._dataSowSeeds = dataSowSeeds;}public async Task SeedAsync(DataSeedContext context){if (!context.Properties.ContainsKey("IsUseCustomRank")){return;}var items = _dataSowSeeds.OrderBy(p => p.Sort);foreach (var item in items){await item.ExecAsync(context);}}}
2.EntityFrameworkCore
2.1 CustomDataSeedDbContext
public DbSet<Book> Books { get; set; }public DbSet<Author> Authors { get; set; }builder.Entity<Book>(b =>{b.ToTable(CustomDataSeedConsts.DbTablePrefix + "Books",CustomDataSeedConsts.DbSchema);b.ConfigureByConvention(); //auto configure for the base class propsb.Property(x => x.Name).IsRequired().HasMaxLength(128);b.HasOne<Author>().WithMany().HasForeignKey(x => x.AuthorId).IsRequired();});builder.Entity<Author>(b =>{b.ToTable(CustomDataSeedConsts.DbTablePrefix + "Authors",CustomDataSeedConsts.DbSchema);b.ConfigureByConvention();b.Property(x => x.Name).IsRequired().HasMaxLength(100);b.HasIndex(x => x.Name);});
2.2 生成迁移脚本
dotnet ef migrations add AddBooks
2.3 应用到数据库
应用到数据库之后,启动CustomDataSeed.DbMigrator项目可以打断点查看种子数据生成顺序
dotnet ef database update
3.源码
源代码