abp

Форк
0
203 строки · 6.2 Кб
1
using System.Diagnostics;
2
using System.Runtime.InteropServices;
3
using Microsoft.Extensions.Logging.Abstractions;
4
using Volo.Abp.Data;
5
using Volo.Abp.DependencyInjection;
6
using Volo.Abp.Identity;
7
using Volo.Abp.MultiTenancy;
8
using Volo.Abp.TenantManagement;
9

10
namespace MyCompanyName.MyProjectName.Data;
11

12
public class MyProjectNameDbMigrationService : ITransientDependency
13
{
14
    public ILogger<MyProjectNameDbMigrationService> Logger { get; set; }
15

16
    private readonly IDataSeeder _dataSeeder;
17
    private readonly MyProjectNameEFCoreDbSchemaMigrator _dbSchemaMigrator;
18
    private readonly ITenantRepository _tenantRepository;
19
    private readonly ICurrentTenant _currentTenant;
20

21
    public MyProjectNameDbMigrationService(
22
        IDataSeeder dataSeeder,
23
        MyProjectNameEFCoreDbSchemaMigrator dbSchemaMigrator,
24
        ITenantRepository tenantRepository,
25
        ICurrentTenant currentTenant)
26
    {
27
        _dataSeeder = dataSeeder;
28
        _dbSchemaMigrator = dbSchemaMigrator;
29
        _tenantRepository = tenantRepository;
30
        _currentTenant = currentTenant;
31

32
        Logger = NullLogger<MyProjectNameDbMigrationService>.Instance;
33
    }
34

35
    public async Task MigrateAsync()
36
    {
37
        var initialMigrationAdded = AddInitialMigrationIfNotExist();
38

39
        if (initialMigrationAdded)
40
        {
41
            return;
42
        }
43

44
        Logger.LogInformation("Started database migrations...");
45

46
        await MigrateDatabaseSchemaAsync();
47
        await SeedDataAsync();
48

49
        Logger.LogInformation($"Successfully completed host database migrations.");
50

51
        var tenants = await _tenantRepository.GetListAsync(includeDetails: true);
52

53
        var migratedDatabaseSchemas = new HashSet<string>();
54
        foreach (var tenant in tenants)
55
        {
56
            using (_currentTenant.Change(tenant.Id))
57
            {
58
                if (tenant.ConnectionStrings.Any())
59
                {
60
                    var tenantConnectionStrings = tenant.ConnectionStrings
61
                        .Select(x => x.Value)
62
                        .ToList();
63

64
                    if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings))
65
                    {
66
                        await MigrateDatabaseSchemaAsync(tenant);
67

68
                        migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings);
69
                    }
70
                }
71

72
                await SeedDataAsync(tenant);
73
            }
74

75
            Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations.");
76
        }
77

78
        Logger.LogInformation("Successfully completed all database migrations.");
79
        Logger.LogInformation("You can safely end this process...");
80
    }
81

82
    private async Task MigrateDatabaseSchemaAsync(Tenant? tenant = null)
83
    {
84
        Logger.LogInformation($"Migrating schema for {(tenant == null ? "host" : tenant.Name + " tenant")} database...");
85
        await _dbSchemaMigrator.MigrateAsync();
86
    }
87

88
    private async Task SeedDataAsync(Tenant? tenant = null)
89
    {
90
        Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed...");
91

92
        await _dataSeeder.SeedAsync(new DataSeedContext(tenant?.Id)
93
            .WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, IdentityDataSeedContributor.AdminEmailDefaultValue)
94
            .WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, IdentityDataSeedContributor.AdminPasswordDefaultValue)
95
        );
96
    }
97

98
    private bool AddInitialMigrationIfNotExist()
99
    {
100
        try
101
        {
102
            if (!DbMigrationsProjectExists())
103
            {
104
                return false;
105
            }
106
        }
107
        catch (Exception)
108
        {
109
            return false;
110
        }
111

112
        try
113
        {
114
            if (!MigrationsFolderExists())
115
            {
116
                AddInitialMigration();
117
                return true;
118
            }
119
            else
120
            {
121
                return false;
122
            }
123
        }
124
        catch (Exception e)
125
        {
126
            Logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message);
127
            return false;
128
        }
129
    }
130

131
    private bool DbMigrationsProjectExists()
132
    {
133
        return Directory.Exists(GetEntityFrameworkCoreProjectFolderPath());
134
    }
135

136
    private bool MigrationsFolderExists()
137
    {
138
        var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath();
139

140
        return Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "Migrations"));
141
    }
142

143
    private void AddInitialMigration()
144
    {
145
        Logger.LogInformation("Creating initial migration...");
146

147
        string argumentPrefix;
148
        string fileName;
149

150
        if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
151
        {
152
            argumentPrefix = "-c";
153
            fileName = "/bin/bash";
154
        }
155
        else
156
        {
157
            argumentPrefix = "/C";
158
            fileName = "cmd.exe";
159
        }
160

161
        var procStartInfo = new ProcessStartInfo(fileName,
162
            $"{argumentPrefix} \"abp create-migration-and-run-migrator \"{GetEntityFrameworkCoreProjectFolderPath()}\" --nolayers\""
163
        );
164

165
        try
166
        {
167
            Process.Start(procStartInfo);
168
        }
169
        catch (Exception)
170
        {
171
            throw new Exception("Couldn't run ABP CLI...");
172
        }
173
    }
174

175
    private string GetEntityFrameworkCoreProjectFolderPath()
176
    {
177
        var slnDirectoryPath = GetSolutionDirectoryPath();
178

179
        if (slnDirectoryPath == null)
180
        {
181
            throw new Exception("Solution folder not found!");
182
        }
183

184
        return Path.Combine(slnDirectoryPath, "MyCompanyName.MyProjectName.Host");
185
    }
186

187
    private string? GetSolutionDirectoryPath()
188
    {
189
        var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());
190

191
        while (currentDirectory != null && Directory.GetParent(currentDirectory.FullName) != null)
192
        {
193
            currentDirectory = Directory.GetParent(currentDirectory.FullName);
194

195
            if (currentDirectory != null && Directory.GetFiles(currentDirectory.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null)
196
            {
197
                return currentDirectory.FullName;
198
            }
199
        }
200

201
        return null;
202
    }
203
}
204

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.