Repository navigation
Expand file tree
/
Copy pathMigrateDatabaseInitializer.cs
More file actions
156 lines (129 loc) · 3.87 KB
/
Copy pathMigrateDatabaseInitializer.cs
File metadata and controls
156 lines (129 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Migrations;
using System.Linq;
using SmartStore.Core.Data;
using SmartStore.Data.Caching;
using SmartStore.Data.Migrations;
using SmartStore.Utilities;
namespace SmartStore.Data.Setup
{
/// <summary>
/// An implementation of <see cref="IDatabaseInitializer{TContext}" /> that will use Code First Migrations
/// to update the database to the latest version.
/// </summary>
public class MigrateDatabaseInitializer<TContext, TConfig> : IDatabaseInitializer<TContext>
where TContext : DbContext, new()
where TConfig : DbMigrationsConfiguration<TContext>, new()
{
#region Ctor
public MigrateDatabaseInitializer()
{
}
public MigrateDatabaseInitializer(string connectionString)
{
this.ConnectionString = connectionString;
}
#endregion
#region Properties
public IEnumerable<IDataSeeder<TContext>> DataSeeders
{
get;
set;
}
public IEnumerable<string> TablesToCheck
{
get;
set;
}
public string ConnectionString
{
get;
private set;
}
#endregion
#region Interface members
/// <summary>
/// Initializes the database.
/// </summary>
/// <param name="context">The context.</param>
public virtual void InitializeDatabase(TContext context)
{
if (!context.Database.Exists())
{
throw Error.InvalidOperation("Database migration failed because the target database does not exist. Ensure the database was initialized and seeded with the 'InstallDatabaseInitializer'.");
}
var config = CreateConfiguration();
var migrator = new DbSeedingMigrator<TContext>(config);
using (new DbContextScope(context as IDbContext, hooksEnabled: false))
{
// run all pending migrations
var appliedCount = migrator.RunPendingMigrations(context);
if (appliedCount > 0)
{
Seed(context);
}
else
{
// DB is up-to-date and no migration ran.
EfMappingViewCacheFactory.SetContext(context);
if (config is MigrationsConfiguration coreConfig && context is SmartObjectContext ctx)
{
// Call the main Seed method anyway (on every startup),
// we could have locale resources or settings to add/update.
coreConfig.SeedDatabase(ctx);
}
}
// not needed anymore
this.DataSeeders = null;
}
}
#endregion
#region Methods
/// <summary>
/// Seeds the specified context.
/// </summary>
/// <param name="context">The context.</param>
protected virtual void Seed(TContext context)
{
if (this.DataSeeders == null)
return;
this.DataSeeders.Each((x) => x.Seed(context));
}
protected virtual TConfig CreateConfiguration()
{
var config = new TConfig();
if (this.ConnectionString.HasValue())
{
var dbContextInfo = new DbContextInfo(typeof(TContext));
config.TargetDatabase = new DbConnectionInfo(this.ConnectionString, dbContextInfo.ConnectionProviderName);
}
if (config.CommandTimeout == null && DataSettings.Current.IsSqlServer)
{
var commandTimeout = CommonHelper.GetAppSetting<int?>("sm:EfMigrationsCommandTimeout");
if (commandTimeout.HasValue)
{
config.CommandTimeout = commandTimeout.Value;
}
}
return config;
}
/// <summary>
/// Checks tables existence
/// </summary>
/// <returns>
/// Returns <c>true</c> if the tables to check exist in the database or the check list is empty.
/// </returns>
protected bool CheckTables(TContext context)
{
if (this.TablesToCheck == null || !this.TablesToCheck.Any())
return true;
var existingTableNames = new List<string>(context.Database.SqlQuery<string>("SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_type = 'BASE TABLE'"));
var result = existingTableNames.Intersect(this.TablesToCheck, StringComparer.InvariantCultureIgnoreCase).Count() == 0;
return !result;
}
#endregion
}
}