Skip to content

Commit e5df65b

Browse files
VCST-1752: Fix performance degradation on SQL Server (#2834)
1 parent c3adf25 commit e5df65b

15 files changed

+121
-68
lines changed

Directory.Build.props

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
<PropertyGroup>
1919
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
20+
<WarningsNotAsErrors>NU5048</WarningsNotAsErrors>
2021
</PropertyGroup>
2122

2223
<PropertyGroup Condition="'$(MSBuildProjectName.Contains(Tests))' == false">

src/VirtoCommerce.Platform.Data.MySql/DbContextOptionsBuilderExtensions.cs

-15
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Microsoft.EntityFrameworkCore;
2+
using Microsoft.EntityFrameworkCore.Infrastructure;
3+
using Microsoft.Extensions.Configuration;
4+
5+
namespace VirtoCommerce.Platform.Data.MySql.Extensions;
6+
7+
public static class DbContextOptionsBuilderExtensions
8+
{
9+
/// <summary>
10+
/// Configures the context to use MySql.
11+
/// </summary>
12+
public static DbContextOptionsBuilder UseMySqlDatabase(
13+
this DbContextOptionsBuilder optionsBuilder,
14+
string? connectionString,
15+
Type migrationsAssemblyMarkerType,
16+
IConfiguration configuration,
17+
Action<MySqlDbContextOptionsBuilder, IConfiguration>? mySqlOptionsAction = null)
18+
{
19+
return optionsBuilder.UseMySql(connectionString,
20+
ServerVersion.AutoDetect(connectionString),
21+
mySqlDbContextOptionsBuilder =>
22+
{
23+
mySqlDbContextOptionsBuilder.MigrationsAssembly(migrationsAssemblyMarkerType.Assembly.GetName().Name);
24+
mySqlOptionsAction?.Invoke(mySqlDbContextOptionsBuilder, configuration);
25+
});
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace VirtoCommerce.Platform.Data.MySql;
2+
3+
public class MySqlDataAssemblyMarker
4+
{
5+
}

src/VirtoCommerce.Platform.Data.MySql/MySqlDbContextFactory.cs

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
61
using Microsoft.EntityFrameworkCore;
72
using Microsoft.EntityFrameworkCore.Design;
83
using VirtoCommerce.Platform.Data.Repositories;
@@ -23,7 +18,7 @@ PlatformDbContext IDesignTimeDbContextFactory<PlatformDbContext>.CreateDbContext
2318
connectionString,
2419
ResolveServerVersion(serverVersion, connectionString),
2520
db => db
26-
.MigrationsAssembly(typeof(MySqlDbContextFactory).Assembly.GetName().Name));
21+
.MigrationsAssembly(typeof(MySqlDataAssemblyMarker).Assembly.GetName().Name));
2722

2823
return new PlatformDbContext(builder.Options);
2924
}
@@ -38,7 +33,7 @@ SecurityDbContext IDesignTimeDbContextFactory<SecurityDbContext>.CreateDbContext
3833
connectionString,
3934
ResolveServerVersion(serverVersion, connectionString),
4035
db => db
41-
.MigrationsAssembly(typeof(MySqlDbContextFactory).Assembly.GetName().Name));
36+
.MigrationsAssembly(typeof(MySqlDataAssemblyMarker).Assembly.GetName().Name));
4237

4338
builder.UseOpenIddict();
4439

src/VirtoCommerce.Platform.Data.PostgreSql/DbContextOptionsBuilderExtensions.cs

-14
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Microsoft.EntityFrameworkCore;
2+
using Microsoft.Extensions.Configuration;
3+
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
4+
5+
namespace VirtoCommerce.Platform.Data.PostgreSql.Extensions;
6+
7+
public static class DbContextOptionsBuilderExtensions
8+
{
9+
/// <summary>
10+
/// Configures the context to use PostgreSql.
11+
/// </summary>
12+
public static DbContextOptionsBuilder UsePostgreSqlDatabase(
13+
this DbContextOptionsBuilder optionsBuilder,
14+
string? connectionString,
15+
Type migrationsAssemblyMarkerType,
16+
IConfiguration configuration,
17+
Action<NpgsqlDbContextOptionsBuilder, IConfiguration>? npgsqlOptionsAction = null)
18+
{
19+
return optionsBuilder.UseNpgsql(connectionString,
20+
npgsqlDbContextOptionsBuilder =>
21+
{
22+
npgsqlDbContextOptionsBuilder.MigrationsAssembly(migrationsAssemblyMarkerType.Assembly.GetName().Name);
23+
npgsqlOptionsAction?.Invoke(npgsqlDbContextOptionsBuilder, configuration);
24+
});
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace VirtoCommerce.Platform.Data.PostgreSql;
2+
3+
public class PostgreSqlDataAssemblyMarker
4+
{
5+
}

src/VirtoCommerce.Platform.Data.PostgreSql/PostgreSqlDbContextFactory.cs

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
61
using Microsoft.EntityFrameworkCore;
72
using Microsoft.EntityFrameworkCore.Design;
83
using VirtoCommerce.Platform.Data.Repositories;
@@ -20,7 +15,7 @@ PlatformDbContext IDesignTimeDbContextFactory<PlatformDbContext>.CreateDbContext
2015

2116
builder.UseNpgsql(
2217
connectionString,
23-
db => db.MigrationsAssembly(typeof(PostgreSqlDbContextFactory).Assembly.GetName().Name));
18+
db => db.MigrationsAssembly(typeof(PostgreSqlDataAssemblyMarker).Assembly.GetName().Name));
2419

2520
return new PlatformDbContext(builder.Options);
2621
}
@@ -32,7 +27,7 @@ SecurityDbContext IDesignTimeDbContextFactory<SecurityDbContext>.CreateDbContext
3227

3328
builder.UseNpgsql(
3429
connectionString,
35-
db => db.MigrationsAssembly(typeof(PostgreSqlDbContextFactory).Assembly.GetName().Name));
30+
db => db.MigrationsAssembly(typeof(PostgreSqlDataAssemblyMarker).Assembly.GetName().Name));
3631

3732
builder.UseOpenIddict();
3833

src/VirtoCommerce.Platform.Data.SqlServer/DbContextOptionsBuilderExtensions.cs

-16
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using Microsoft.EntityFrameworkCore;
2+
using Microsoft.EntityFrameworkCore.Infrastructure;
3+
using Microsoft.Extensions.Configuration;
4+
5+
namespace VirtoCommerce.Platform.Data.SqlServer.Extensions;
6+
7+
public static class DbContextOptionsBuilderExtensions
8+
{
9+
/// <summary>
10+
/// Configures the context to use SqlServer.
11+
/// </summary>
12+
public static DbContextOptionsBuilder UseSqlServerDatabase(
13+
this DbContextOptionsBuilder optionsBuilder,
14+
string? connectionString,
15+
Type migrationsAssemblyMarkerType,
16+
IConfiguration configuration,
17+
Action<SqlServerDbContextOptionsBuilder, IConfiguration>? sqlServerOptionsAction = null)
18+
{
19+
return optionsBuilder.UseSqlServer(connectionString,
20+
sqlServerOptionsBuilder =>
21+
{
22+
var compatibilityLevel = configuration.GetValue<int?>("SqlServer:CompatibilityLevel", null);
23+
if (compatibilityLevel != null)
24+
{
25+
sqlServerOptionsBuilder.UseCompatibilityLevel(compatibilityLevel.Value);
26+
}
27+
28+
sqlServerOptionsBuilder.MigrationsAssembly(migrationsAssemblyMarkerType.Assembly.GetName().Name);
29+
sqlServerOptionsAction?.Invoke(sqlServerOptionsBuilder, configuration);
30+
});
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace VirtoCommerce.Platform.Data.SqlServer;
2+
3+
public class SqlServerDataAssemblyMarker
4+
{
5+
}

src/VirtoCommerce.Platform.Data.SqlServer/SqlServerDbContextFactory.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ PlatformDbContext IDesignTimeDbContextFactory<PlatformDbContext>.CreateDbContext
1515

1616
builder.UseSqlServer(
1717
connectionString,
18-
db => db.MigrationsAssembly(typeof(SqlServerDbContextFactory).Assembly.GetName().Name));
18+
db => db.MigrationsAssembly(typeof(SqlServerDataAssemblyMarker).Assembly.GetName().Name));
1919

2020
return new PlatformDbContext(builder.Options);
2121
}
@@ -27,7 +27,7 @@ SecurityDbContext IDesignTimeDbContextFactory<SecurityDbContext>.CreateDbContext
2727

2828
builder.UseSqlServer(
2929
connectionString,
30-
db => db.MigrationsAssembly(typeof(SqlServerDbContextFactory).Assembly.GetName().Name));
30+
db => db.MigrationsAssembly(typeof(SqlServerDataAssemblyMarker).Assembly.GetName().Name));
3131

3232
builder.UseOpenIddict();
3333

src/VirtoCommerce.Platform.Web/Startup.cs

+9-7
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,14 @@
4646
using VirtoCommerce.Platform.Core.Settings;
4747
using VirtoCommerce.Platform.Data.Extensions;
4848
using VirtoCommerce.Platform.Data.MySql;
49+
using VirtoCommerce.Platform.Data.MySql.Extensions;
4950
using VirtoCommerce.Platform.Data.MySql.HealthCheck;
5051
using VirtoCommerce.Platform.Data.PostgreSql;
52+
using VirtoCommerce.Platform.Data.PostgreSql.Extensions;
5153
using VirtoCommerce.Platform.Data.PostgreSql.HealthCheck;
5254
using VirtoCommerce.Platform.Data.Repositories;
5355
using VirtoCommerce.Platform.Data.SqlServer;
56+
using VirtoCommerce.Platform.Data.SqlServer.Extensions;
5457
using VirtoCommerce.Platform.Data.SqlServer.HealthCheck;
5558
using VirtoCommerce.Platform.DistributedLock;
5659
using VirtoCommerce.Platform.Hangfire.Extensions;
@@ -133,19 +136,18 @@ public void ConfigureServices(IServiceCollection services)
133136

134137
services.AddDbContext<PlatformDbContext>((provider, options) =>
135138
{
136-
var databaseProvider = Configuration.GetValue("DatabaseProvider", "SqlServer");
137139
var connectionString = Configuration.GetConnectionString("VirtoCommerce");
138140

139141
switch (databaseProvider)
140142
{
141143
case "MySql":
142-
options.UseMySqlDatabase(connectionString);
144+
options.UseMySqlDatabase(connectionString, typeof(MySqlDataAssemblyMarker), Configuration);
143145
break;
144146
case "PostgreSql":
145-
options.UsePostgreSqlDatabase(connectionString);
147+
options.UsePostgreSqlDatabase(connectionString, typeof(PostgreSqlDataAssemblyMarker), Configuration);
146148
break;
147149
default:
148-
options.UseSqlServerDatabase(connectionString);
150+
options.UseSqlServerDatabase(connectionString, typeof(SqlServerDataAssemblyMarker), Configuration);
149151
break;
150152
}
151153
});
@@ -203,13 +205,13 @@ public void ConfigureServices(IServiceCollection services)
203205
switch (databaseProvider)
204206
{
205207
case "MySql":
206-
options.UseMySqlDatabase(connectionString);
208+
options.UseMySqlDatabase(connectionString, typeof(MySqlDataAssemblyMarker), Configuration);
207209
break;
208210
case "PostgreSql":
209-
options.UsePostgreSqlDatabase(connectionString);
211+
options.UsePostgreSqlDatabase(connectionString, typeof(PostgreSqlDataAssemblyMarker), Configuration);
210212
break;
211213
default:
212-
options.UseSqlServerDatabase(connectionString);
214+
options.UseSqlServerDatabase(connectionString, typeof(SqlServerDataAssemblyMarker), Configuration);
213215
break;
214216
}
215217

src/VirtoCommerce.Platform.Web/appsettings.json

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
"VirtoCommerce": "Data Source=(local);Initial Catalog=VirtoCommerce3.net8;Persist Security Info=True;User ID=virto;Password=virto;Connect Timeout=30;TrustServerCertificate=True;"
66
//"RedisConnectionString": "127.0.0.1:6379,ssl=False"
77
},
8+
"SqlServer": {
9+
// Set compatibility level to 120 (SQL Server 2014) to prevent the use of OPENJSON, which has poor performance.
10+
// https://github.com/dotnet/efcore/issues/32394
11+
// "CompatibilityLevel": 120
12+
},
813
"Serilog": {
914
"Using": [
1015
"Serilog.Sinks.Console",

0 commit comments

Comments
 (0)