Skip to content

Commit f03e34f

Browse files
committed
Modify DatabaseObject to support state
This makes DatabaseUser simpler to work with. It can store a reference to the database the user should be created in, and the class can handle switching to/from that database.
1 parent 7d6f87f commit f03e34f

3 files changed

Lines changed: 40 additions & 16 deletions

File tree

src/Microsoft.Data.SqlClient/tests/Common/Fixtures/DatabaseObjects/DatabaseObject.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,28 @@ namespace Microsoft.Data.SqlClient.Tests.Common.Fixtures.DatabaseObjects;
1212
/// Base class for a transient database object (such as a table, type or
1313
/// stored procedure.)
1414
/// </summary>
15-
public abstract class DatabaseObject : IDisposable
15+
/// <typeparam name="TState">
16+
/// The type of the internal state accessible to derived types at the point of object creation
17+
/// via the <see cref="State"/> property.
18+
/// </typeparam>
19+
public abstract class DatabaseObject<TState> : IDisposable
1620
{
1721
private readonly bool _shouldDrop;
1822

1923
protected SqlConnection Connection { get; }
2024

25+
protected TState State { get; }
26+
2127
public string Name { get; }
2228

2329
public string UnescapedName => Name.Substring(1, Name.Length - 2).Replace("]]", "]");
2430

25-
protected DatabaseObject(SqlConnection connection, string name, string definition, bool shouldCreate, bool shouldDrop)
31+
protected DatabaseObject(SqlConnection connection, string name, string definition, TState state, bool shouldCreate, bool shouldDrop)
2632
{
2733
_shouldDrop = shouldDrop;
2834

2935
Connection = connection;
36+
State = state;
3037
Name = name;
3138

3239
if (shouldCreate)
@@ -263,3 +270,15 @@ public void Dispose()
263270
GC.SuppressFinalize(this);
264271
}
265272
}
273+
274+
/// <summary>
275+
/// Base class for a transient database object (such as a table, type or
276+
/// stored procedure.)
277+
/// </summary>
278+
public abstract class DatabaseObject : DatabaseObject<object?>
279+
{
280+
protected DatabaseObject(SqlConnection connection, string name, string definition, bool shouldCreate, bool shouldDrop)
281+
: base(connection, name, definition, state: null, shouldCreate, shouldDrop)
282+
{
283+
}
284+
}

src/Microsoft.Data.SqlClient/tests/Common/Fixtures/DatabaseObjects/DatabaseUser.cs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,48 +10,54 @@ namespace Microsoft.Data.SqlClient.Tests.Common.Fixtures.DatabaseObjects;
1010
/// <remarks>
1111
/// This class assumes that the associated server login already exists.
1212
/// </remarks>
13-
public sealed class DatabaseUser : DatabaseObject
13+
public sealed class DatabaseUser : DatabaseObject<string>
1414
{
15-
private readonly string _databaseName;
15+
public string DatabaseName => State;
1616

1717
/// <summary>
1818
/// Initializes a new instance of the DatabaseUser class using the specified SQL connection
1919
/// and associated server login.
2020
/// </summary>
2121
/// <param name="connection">The SQL connection used to interact with the database.</param>
22+
/// <param name="database">The name of the database where the user will be created.</param>
2223
/// <param name="login">The server login which the database user will be associated with.</param>
23-
public DatabaseUser(SqlConnection connection, ServerLogin login)
24-
: base(connection, login.Name, $"FOR LOGIN {login.Name}", shouldCreate: true, shouldDrop: true)
24+
public DatabaseUser(SqlConnection connection, string database, ServerLogin login)
25+
: base(connection, login.Name, $"FOR LOGIN {login.Name}", database, shouldCreate: true, shouldDrop: true)
2526
{
26-
_databaseName = Connection.Database;
2727
}
2828

2929
protected override void CreateObject(string definition)
3030
{
3131
using SqlCommand createCommand = new($"CREATE USER {Name} {definition}", Connection);
3232

33-
createCommand.ExecuteNonQuery();
33+
ExecuteCommandInDatabase(createCommand);
3434
}
3535

3636
protected override void DropObject()
3737
{
38-
string? originalDatabase = _databaseName == Connection.Database ? null : _databaseName;
3938
using SqlCommand dropCommand = new($"IF USER_ID('{UnescapedName}') IS NOT NULL DROP USER {Name}", Connection);
4039

40+
ExecuteCommandInDatabase(dropCommand);
41+
}
42+
43+
private void ExecuteCommandInDatabase(SqlCommand command)
44+
{
45+
string? originalDatabase = DatabaseName == command.Connection.Database ? null : command.Connection.Database;
46+
4147
try
4248
{
4349
if (originalDatabase is not null)
4450
{
45-
Connection.ChangeDatabase(_databaseName);
51+
command.Connection.ChangeDatabase(DatabaseName);
4652
}
4753

48-
dropCommand.ExecuteNonQuery();
54+
command.ExecuteNonQuery();
4955
}
5056
finally
5157
{
5258
if (originalDatabase is not null)
5359
{
54-
Connection.ChangeDatabase(originalDatabase);
60+
command.Connection.ChangeDatabase(originalDatabase);
5561
}
5662
}
5763
}

src/Microsoft.Data.SqlClient/tests/Common/Fixtures/DatabaseObjects/ServerLogin.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ namespace Microsoft.Data.SqlClient.Tests.Common.Fixtures.DatabaseObjects;
77
/// <summary>
88
/// A transient server login, created at the start of its scope and dropped when disposed.
99
/// </summary>
10-
public sealed class ServerLogin : DatabaseObject
10+
public sealed class ServerLogin : DatabaseObject<string>
1111
{
12-
public string Password { get; }
12+
public string Password => State;
1313

1414
/// <summary>
1515
/// Initializes a new instance of the ServerLogin class using the specified SQL connection, login name prefix, and default database.
@@ -24,9 +24,8 @@ public ServerLogin(SqlConnection connection, string namePrefix, string? defaultD
2424
}
2525

2626
private ServerLogin(SqlConnection connection, string namePrefix, string password, string? defaultDatabase)
27-
: base(connection, namePrefix, GenerateDefinition(password, defaultDatabase), shouldCreate: true, shouldDrop: true)
27+
: base(connection, namePrefix, GenerateDefinition(password, defaultDatabase), password, shouldCreate: true, shouldDrop: true)
2828
{
29-
Password = password;
3029
}
3130

3231
private static string GenerateDefinition(string password, string? defaultDatabase) =>

0 commit comments

Comments
 (0)