feat(configmanager): add dedicated SQL Server port control
Add SqlServerPort property to connection string editor for explicit port configuration, replacing the need to embed port in server name (e.g., localhost,1434). The port control generates the comma-separated format in the connection string but does not parse it back when loading existing connection strings.
This commit is contained in:
@@ -107,6 +107,7 @@ public class ConnectionStringEntryTests
|
||||
entry.Name.ShouldBe(string.Empty);
|
||||
entry.Provider.ShouldBe(ConnectionProvider.Generic);
|
||||
entry.Server.ShouldBeNull();
|
||||
entry.SqlServerPort.ShouldBeNull();
|
||||
entry.Database.ShouldBeNull();
|
||||
entry.UserId.ShouldBeNull();
|
||||
entry.Password.ShouldBeNull();
|
||||
@@ -119,4 +120,70 @@ public class ConnectionStringEntryTests
|
||||
entry.ServiceName.ShouldBeNull();
|
||||
entry.RawConnectionString.ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerateConnectionString_SqlServer_WithPort_IncludesPortInServer()
|
||||
{
|
||||
// Arrange
|
||||
var entry = new ConnectionStringEntry
|
||||
{
|
||||
Provider = ConnectionProvider.SqlServer,
|
||||
Server = "localhost",
|
||||
SqlServerPort = 1434,
|
||||
Database = "TestDb",
|
||||
UserId = "sa",
|
||||
Password = "secret123"
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = entry.GenerateConnectionString();
|
||||
|
||||
// Assert
|
||||
result.ShouldContain("Server=localhost,1434");
|
||||
result.ShouldContain("Database=TestDb");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerateConnectionString_SqlServer_WithoutPort_NoPortInServer()
|
||||
{
|
||||
// Arrange
|
||||
var entry = new ConnectionStringEntry
|
||||
{
|
||||
Provider = ConnectionProvider.SqlServer,
|
||||
Server = "localhost",
|
||||
SqlServerPort = null,
|
||||
Database = "TestDb",
|
||||
UserId = "sa",
|
||||
Password = "secret123"
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = entry.GenerateConnectionString();
|
||||
|
||||
// Assert
|
||||
result.ShouldContain("Server=localhost;");
|
||||
result.ShouldNotContain("Server=localhost,");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerateConnectionString_SqlServer_WithZeroPort_NoPortInServer()
|
||||
{
|
||||
// Arrange
|
||||
var entry = new ConnectionStringEntry
|
||||
{
|
||||
Provider = ConnectionProvider.SqlServer,
|
||||
Server = "localhost",
|
||||
SqlServerPort = 0,
|
||||
Database = "TestDb",
|
||||
UserId = "sa",
|
||||
Password = "secret123"
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = entry.GenerateConnectionString();
|
||||
|
||||
// Assert
|
||||
result.ShouldContain("Server=localhost;");
|
||||
result.ShouldNotContain("Server=localhost,");
|
||||
}
|
||||
}
|
||||
|
||||
+81
-1
@@ -34,7 +34,8 @@ public class ConnectionStringsSectionConverterTests
|
||||
|
||||
var lotFinder = section.Entries.First(e => e.Name == "LotFinder");
|
||||
lotFinder.Provider.ShouldBe(ConnectionProvider.SqlServer);
|
||||
lotFinder.Server.ShouldBe("localhost,1434");
|
||||
lotFinder.Server.ShouldBe("localhost,1434"); // Port embedded in server, not parsed separately
|
||||
lotFinder.SqlServerPort.ShouldBeNull();
|
||||
lotFinder.Database.ShouldBe("ScopingTool");
|
||||
lotFinder.UserId.ShouldBe("sa");
|
||||
|
||||
@@ -195,4 +196,83 @@ public class ConnectionStringsSectionConverterTests
|
||||
secondary.Port.ShouldBe(1521);
|
||||
secondary.ServiceName.ShouldBe("ORCL");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Deserialize_SqlServerWithEmbeddedPort_KeepsPortInServer()
|
||||
{
|
||||
// Arrange - connection string with port embedded in server name (legacy format)
|
||||
var json = """
|
||||
{
|
||||
"TestDb": "Server=localhost,1434;Database=TestDB;User Id=testuser;Password=testpass"
|
||||
}
|
||||
""";
|
||||
|
||||
// Act
|
||||
var section = JsonSerializer.Deserialize<ConnectionStringsSection>(json, JsonOptions);
|
||||
|
||||
// Assert - port is NOT parsed out, stays embedded in server name
|
||||
section.ShouldNotBeNull();
|
||||
section.Entries.Count.ShouldBe(1);
|
||||
|
||||
var entry = section.Entries[0];
|
||||
entry.Name.ShouldBe("TestDb");
|
||||
entry.Provider.ShouldBe(ConnectionProvider.SqlServer);
|
||||
entry.Server.ShouldBe("localhost,1434"); // Port stays in server name
|
||||
entry.SqlServerPort.ShouldBeNull(); // Port control not populated from parsing
|
||||
entry.Database.ShouldBe("TestDB");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Deserialize_SqlServerWithoutPort_ServerHasNoPort()
|
||||
{
|
||||
// Arrange
|
||||
var json = """
|
||||
{
|
||||
"TestDb": "Server=myserver;Database=TestDB;User Id=testuser;Password=testpass"
|
||||
}
|
||||
""";
|
||||
|
||||
// Act
|
||||
var section = JsonSerializer.Deserialize<ConnectionStringsSection>(json, JsonOptions);
|
||||
|
||||
// Assert
|
||||
section.ShouldNotBeNull();
|
||||
section.Entries.Count.ShouldBe(1);
|
||||
|
||||
var entry = section.Entries[0];
|
||||
entry.Server.ShouldBe("myserver");
|
||||
entry.SqlServerPort.ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTrip_SqlServerWithPort_EmbedsPortInServer()
|
||||
{
|
||||
// Arrange - entry with separate port control
|
||||
var original = new ConnectionStringsSection
|
||||
{
|
||||
Entries = new List<ConnectionStringEntry>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Name = "WithPort",
|
||||
Provider = ConnectionProvider.SqlServer,
|
||||
Server = "localhost",
|
||||
SqlServerPort = 1434,
|
||||
Database = "DB1",
|
||||
UserId = "user1",
|
||||
Password = "pass1"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Act
|
||||
var json = JsonSerializer.Serialize(original, JsonOptions);
|
||||
var deserialized = JsonSerializer.Deserialize<ConnectionStringsSection>(json, JsonOptions);
|
||||
|
||||
// Assert - after round trip, port is embedded in server name (not parsed back out)
|
||||
deserialized.ShouldNotBeNull();
|
||||
var entry = deserialized.Entries.First();
|
||||
entry.Server.ShouldBe("localhost,1434"); // Port embedded in server after round trip
|
||||
entry.SqlServerPort.ShouldBeNull(); // Port control not populated from parsing
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user