Skip to content

Commit

Permalink
feat(DatabaseStorageBase): Add SchemaName parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
unchase committed Aug 31, 2021
1 parent 4ae9740 commit 757048a
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 31 deletions.
56 changes: 30 additions & 26 deletions src/MiniProfiler.Providers.SqlServer/SqlServerStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,29 @@ public SqlServerStorage(string connectionString) : base(connectionString) { /* b
/// <param name="profilersTable">The table name to use for MiniProfilers.</param>
/// <param name="timingsTable">The table name to use for MiniProfiler Timings.</param>
/// <param name="clientTimingsTable">The table name to use for MiniProfiler Client Timings.</param>
public SqlServerStorage(string connectionString, string profilersTable, string timingsTable, string clientTimingsTable)
: base(connectionString, profilersTable, timingsTable, clientTimingsTable) { }
/// <param name="schemaName">The database schema to use for MiniProfiler tables.</param>
public SqlServerStorage(string connectionString, string profilersTable = null, string timingsTable = null, string clientTimingsTable = null, string schemaName = null)
: base(connectionString, profilersTable, timingsTable, clientTimingsTable, schemaName) { }

private string _saveSql, _saveTimingsSql, _saveClientTimingsSql;

private string SaveSql => _saveSql ??= $@"
INSERT INTO {MiniProfilersTable}
INSERT INTO {SchemaName}.{MiniProfilersTable}
(Id, RootTimingId, Name, Started, DurationMilliseconds, [User], HasUserViewed, MachineName, CustomLinksJson, ClientTimingsRedirectCount)
SELECT @Id, @RootTimingId, @Name, @Started, @DurationMilliseconds, @User, @HasUserViewed, @MachineName, @CustomLinksJson, @ClientTimingsRedirectCount
WHERE NOT EXISTS (SELECT 1 FROM {MiniProfilersTable} WHERE Id = @Id)";
WHERE NOT EXISTS (SELECT 1 FROM {SchemaName}.{MiniProfilersTable} WHERE Id = @Id)";

private string SaveTimingsSql => _saveTimingsSql ??= $@"
INSERT INTO {MiniProfilerTimingsTable}
INSERT INTO {SchemaName}.{MiniProfilerTimingsTable}
(Id, MiniProfilerId, ParentTimingId, Name, DurationMilliseconds, StartMilliseconds, IsRoot, Depth, CustomTimingsJson)
SELECT @Id, @MiniProfilerId, @ParentTimingId, @Name, @DurationMilliseconds, @StartMilliseconds, @IsRoot, @Depth, @CustomTimingsJson
WHERE NOT EXISTS (SELECT 1 FROM {MiniProfilerTimingsTable} WHERE Id = @Id)";
WHERE NOT EXISTS (SELECT 1 FROM {SchemaName}.{MiniProfilerTimingsTable} WHERE Id = @Id)";

private string SaveClientTimingsSql => _saveClientTimingsSql ??= $@"
INSERT INTO {MiniProfilerClientTimingsTable}
INSERT INTO {SchemaName}.{MiniProfilerClientTimingsTable}
(Id, MiniProfilerId, Name, Start, Duration)
SELECT @Id, @MiniProfilerId, @Name, @Start, @Duration
WHERE NOT EXISTS (SELECT 1 FROM {MiniProfilerClientTimingsTable} WHERE Id = @Id)";
WHERE NOT EXISTS (SELECT 1 FROM {SchemaName}.{MiniProfilerClientTimingsTable} WHERE Id = @Id)";

/// <summary>
/// Stores to <c>dbo.MiniProfilers</c> under its <see cref="MiniProfiler.Id"/>;
Expand Down Expand Up @@ -181,9 +182,9 @@ public override async Task SaveAsync(MiniProfiler profiler)
private string _loadSql;

private string LoadSql => _loadSql ??= $@"
SELECT * FROM {MiniProfilersTable} WHERE Id = @id;
SELECT * FROM {MiniProfilerTimingsTable} WHERE MiniProfilerId = @id ORDER BY StartMilliseconds;
SELECT * FROM {MiniProfilerClientTimingsTable} WHERE MiniProfilerId = @id ORDER BY Start;";
SELECT * FROM {SchemaName}.{MiniProfilersTable} WHERE Id = @id;
SELECT * FROM {SchemaName}.{MiniProfilerTimingsTable} WHERE MiniProfilerId = @id ORDER BY StartMilliseconds;
SELECT * FROM {SchemaName}.{MiniProfilerClientTimingsTable} WHERE MiniProfilerId = @id ORDER BY Start;";

/// <summary>
/// Loads the <c>MiniProfiler</c> identified by 'id' from the database.
Expand Down Expand Up @@ -272,7 +273,7 @@ public override async Task<MiniProfiler> LoadAsync(Guid id)
private string _toggleViewedSql;

private string ToggleViewedSql => _toggleViewedSql ??= $@"
Update {MiniProfilersTable}
Update {SchemaName}.{MiniProfilersTable}
Set HasUserViewed = @hasUserVeiwed
Where Id = @id
And [User] = @user";
Expand All @@ -297,7 +298,7 @@ private async Task ToggleViewedAsync(string user, Guid id, bool hasUserVeiwed)

private string GetUnviewedIdsSql => _getUnviewedIdsSql ??= $@"
Select Id
From {MiniProfilersTable}
From {SchemaName}.{MiniProfilersTable}
Where [User] = @user
And HasUserViewed = 0
Order By Started";
Expand Down Expand Up @@ -367,7 +368,7 @@ private string BuildListQuery(DateTime? start = null, DateTime? finish = null, L
var sb = StringBuilderCache.Get();
sb.Append(@"
Select Top {=maxResults} Id
From ").Append(MiniProfilersTable).Append(@"
From ").Append(SchemaName).Append(".").Append(MiniProfilersTable).Append(@"
");
if (finish != null)
{
Expand Down Expand Up @@ -395,9 +396,12 @@ private string BuildListQuery(DateTime? start = null, DateTime? finish = null, L
protected override IEnumerable<string> GetTableCreationScripts()
{
yield return $@"
CREATE TABLE {MiniProfilersTable}
-- creating schema name if not exists
IF NOT EXISTS ( SELECT * FROM sys.schemas WHERE name = N'{SchemaName}') EXEC('CREATE SCHEMA [{SchemaName}]');
CREATE TABLE {SchemaName}.{MiniProfilersTable}
(
RowId integer not null identity constraint PK_{MiniProfilersTable} primary key clustered, -- Need a clustered primary key for SQL Azure
RowId integer not null identity constraint PK_{SchemaName}_{MiniProfilersTable} primary key clustered, -- Need a clustered primary key for SQL Azure
Id uniqueidentifier not null, -- don't cluster on a guid
RootTimingId uniqueidentifier null,
Name nvarchar(200) null,
Expand All @@ -410,14 +414,14 @@ CustomLinksJson nvarchar(max),
ClientTimingsRedirectCount int null
);
-- displaying results selects everything based on the main MiniProfilers.Id column
CREATE UNIQUE NONCLUSTERED INDEX IX_{MiniProfilersTable}_Id ON {MiniProfilersTable} (Id);
CREATE UNIQUE NONCLUSTERED INDEX IX_{SchemaName}_{MiniProfilersTable}_Id ON {SchemaName}.{MiniProfilersTable} (Id);
-- speeds up a query that is called on every .Stop()
CREATE NONCLUSTERED INDEX IX_{MiniProfilersTable}_User_HasUserViewed_Includes ON {MiniProfilersTable} ([User], HasUserViewed) INCLUDE (Id, [Started]);
CREATE NONCLUSTERED INDEX IX_{SchemaName}_{MiniProfilersTable}_User_HasUserViewed_Includes ON {SchemaName}.{MiniProfilersTable} ([User], HasUserViewed) INCLUDE (Id, [Started]);
CREATE TABLE {MiniProfilerTimingsTable}
CREATE TABLE {SchemaName}.{MiniProfilerTimingsTable}
(
RowId integer not null identity constraint PK_{MiniProfilerTimingsTable} primary key clustered,
RowId integer not null identity constraint PK_{SchemaName}_{MiniProfilerTimingsTable} primary key clustered,
Id uniqueidentifier not null,
MiniProfilerId uniqueidentifier not null,
ParentTimingId uniqueidentifier null,
Expand All @@ -429,21 +433,21 @@ StartMilliseconds decimal(15,3) not null,
CustomTimingsJson nvarchar(max) null
);
CREATE UNIQUE NONCLUSTERED INDEX IX_{MiniProfilerTimingsTable}_Id ON {MiniProfilerTimingsTable} (Id);
CREATE NONCLUSTERED INDEX IX_{MiniProfilerTimingsTable}_MiniProfilerId ON {MiniProfilerTimingsTable} (MiniProfilerId);
CREATE UNIQUE NONCLUSTERED INDEX IX_{SchemaName}_{MiniProfilerTimingsTable}_Id ON {SchemaName}.{MiniProfilerTimingsTable} (Id);
CREATE NONCLUSTERED INDEX IX_{SchemaName}_{MiniProfilerTimingsTable}_MiniProfilerId ON {SchemaName}.{MiniProfilerTimingsTable} (MiniProfilerId);
CREATE TABLE {MiniProfilerClientTimingsTable}
CREATE TABLE {SchemaName}.{MiniProfilerClientTimingsTable}
(
RowId integer not null identity constraint PK_{MiniProfilerClientTimingsTable} primary key clustered,
RowId integer not null identity constraint PK_{SchemaName}_{MiniProfilerClientTimingsTable} primary key clustered,
Id uniqueidentifier not null,
MiniProfilerId uniqueidentifier not null,
Name nvarchar(200) not null,
Start decimal(9, 3) not null,
Duration decimal(9, 3) not null
);
CREATE UNIQUE NONCLUSTERED INDEX IX_{MiniProfilerClientTimingsTable}_Id on {MiniProfilerClientTimingsTable} (Id);
CREATE NONCLUSTERED INDEX IX_{MiniProfilerClientTimingsTable}_MiniProfilerId on {MiniProfilerClientTimingsTable} (MiniProfilerId);
CREATE UNIQUE NONCLUSTERED INDEX IX_{SchemaName}_{MiniProfilerClientTimingsTable}_Id on {SchemaName}.{MiniProfilerClientTimingsTable} (Id);
CREATE NONCLUSTERED INDEX IX_{SchemaName}_{MiniProfilerClientTimingsTable}_MiniProfilerId on {SchemaName}.{MiniProfilerClientTimingsTable} (MiniProfilerId);
";
}
}
Expand Down
15 changes: 11 additions & 4 deletions src/MiniProfiler.Shared/Storage/DatabaseStorageBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ public abstract class DatabaseStorageBase : IAsyncStorage, IDatabaseStorageConne
/// </summary>
public readonly string MiniProfilerClientTimingsTable = "MiniProfilerClientTimings";

/// <summary>
/// The database schema to use for MiniProfiler tables.
/// </summary>
public readonly string SchemaName = "dbo";

/// <summary>
/// Gets or sets how we connect to the database used to save/load MiniProfiler results.
/// </summary>
Expand All @@ -49,12 +54,14 @@ protected DatabaseStorageBase(string connectionString)
/// <param name="profilersTable">The table name to use for MiniProfilers.</param>
/// <param name="timingsTable">The table name to use for MiniProfiler Timings.</param>
/// <param name="clientTimingsTable">The table name to use for MiniProfiler Client Timings.</param>
protected DatabaseStorageBase(string connectionString, string profilersTable, string timingsTable, string clientTimingsTable)
/// <param name="schemaName">The database schema to use for MiniProfiler tables.</param>
protected DatabaseStorageBase(string connectionString, string profilersTable = null, string timingsTable = null, string clientTimingsTable = null, string schemaName = null)
{
ConnectionString = connectionString;
MiniProfilersTable = profilersTable;
MiniProfilerTimingsTable = timingsTable;
MiniProfilerClientTimingsTable = clientTimingsTable;
MiniProfilersTable = profilersTable ?? MiniProfilersTable;
MiniProfilerTimingsTable = timingsTable ?? MiniProfilerTimingsTable;
MiniProfilerClientTimingsTable = clientTimingsTable ?? MiniProfilerClientTimingsTable;
SchemaName = schemaName ?? SchemaName;
}

/// <summary>
Expand Down
3 changes: 2 additions & 1 deletion tests/MiniProfiler.Tests/Storage/SqlServerStorageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public SqlServerStorageFixture()
TestConfig.Current.SQLServerConnectionString,
"MPTest" + TestId,
"MPTimingsTest" + TestId,
"MPClientTimingsTest" + TestId);
"MPClientTimingsTest" + TestId,
"MPSchemaNameTest" + TestId);
try
{
Storage.CreateSchema();
Expand Down

0 comments on commit 757048a

Please sign in to comment.