Skip to content

Commit 8298e8e

Browse files
(#2) Add a provider
1 parent cb0e8cb commit 8298e8e

12 files changed

+226
-8
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-- Run this in to your database. You can change the schema to suit if you need to.
2+
3+
CREATE SCHEMA Stravaig;
4+
GO
5+
CREATE TABLE Stravaig.AppConfiguation
6+
(
7+
ConfigKey NVARCHAR(1024) PRIMARY KEY CLUSTERED,
8+
ConfigValue NVARCHAR(MAX)
9+
);
10+
GO
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Stravaig.Configuration.SqlServer.Tests;
5+
6+
public class FakeDataLoader : IDataLoader
7+
{
8+
public KeyValuePair<string, string>[] FakeData { get; set; } = Array.Empty<KeyValuePair<string, string>>();
9+
public IEnumerable<KeyValuePair<string, string>> RetrieveData(SqlServerConfigurationSource source)
10+
{
11+
return FakeData;
12+
}
13+
}

src/Stravaig.Configuration.SqlServer.Tests/Stravaig.Configuration.SqlServer.Tests.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,16 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10+
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
1011
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0"/>
1112
<PackageReference Include="NUnit" Version="3.13.2"/>
1213
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1"/>
1314
<PackageReference Include="coverlet.collector" Version="3.1.1"/>
1415
<PackageReference Include="Shouldly" Version="4.0.3"/>
1516
</ItemGroup>
1617

18+
<ItemGroup>
19+
<ProjectReference Include="..\Stravaig.Configuration.SqlServer\Stravaig.Configuration.SqlServer.csproj" />
20+
</ItemGroup>
21+
1722
</Project>
Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,51 @@
1+
using System.Collections.Generic;
2+
using Microsoft.Extensions.Configuration;
3+
using Microsoft.Extensions.Hosting;
14
using NUnit.Framework;
5+
using Shouldly;
26

37
namespace Stravaig.Configuration.SqlServer.Tests;
48

5-
public class Tests
9+
public class SqlServerConfigurationProviderTests
610
{
11+
private const string DummyConnectionString = "Server=localhost;Database=testing";
12+
713
[SetUp]
814
public void Setup()
915
{
16+
1017
}
1118

1219
[Test]
13-
public void Test1()
20+
public void ValuesAreRetrievable()
1421
{
15-
Assert.Pass();
22+
var provider = SetupProvider();
23+
provider.Load();
24+
25+
provider.TryGet("A", out var value);
26+
value.ShouldBe("111");
27+
28+
provider.TryGet("B:A", out value);
29+
value.ShouldBe("222");
30+
31+
provider.TryGet("B:B", out value);
32+
value.ShouldBe("333");
33+
}
34+
35+
private static SqlServerConfigurationProvider SetupProvider()
36+
{
37+
var fakeDataLoader = new FakeDataLoader()
38+
{
39+
FakeData = new[]
40+
{
41+
new KeyValuePair<string, string>("A", "111"),
42+
new KeyValuePair<string, string>("B:A", "222"),
43+
new KeyValuePair<string, string>("B:B", "333"),
44+
}
45+
};
46+
47+
var provider =
48+
new SqlServerConfigurationProvider(new SqlServerConfigurationSource(DummyConnectionString), fakeDataLoader);
49+
return provider;
1650
}
1751
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
using System.Runtime.CompilerServices;
2+
3+
[assembly: InternalsVisibleTo("Stravaig.Configuration.SqlServer.Tests")]

src/Stravaig.Configuration.SqlServer/Class1.cs

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System.Collections.Generic;
2+
using System.Data.SqlClient;
3+
4+
namespace Stravaig.Configuration.SqlServer;
5+
6+
public interface IDataLoader
7+
{
8+
IEnumerable<KeyValuePair<string, string>> RetrieveData(SqlServerConfigurationSource source);
9+
}
10+
public class DataLoader : IDataLoader
11+
{
12+
private const string RetrieveSqlTemplate = "SELECT [ConfigKey], [ConfigValue] FROM [{0}].[{1}]";
13+
private const int keyColumnPosition = 0;
14+
private const int valueColumnPosition = 1;
15+
16+
public IEnumerable<KeyValuePair<string, string>> RetrieveData(SqlServerConfigurationSource source)
17+
{
18+
var sql = RetrieveSql(source.SchemaName, source.TableName);
19+
using SqlConnection connection = new SqlConnection(source.ConnectionString);
20+
connection.Open();
21+
var cmd = new SqlCommand(sql, connection);
22+
using var reader = cmd.ExecuteReader();
23+
while (reader.HasRows)
24+
{
25+
var key = reader.GetString(keyColumnPosition);
26+
var value = reader.GetString(valueColumnPosition);
27+
yield return new KeyValuePair<string, string>(key, value);
28+
}
29+
}
30+
31+
private string RetrieveSql(string schemaName, string tableName) =>
32+
string.Format(RetrieveSqlTemplate, schemaName, tableName);
33+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
using Microsoft.Extensions.Configuration;
3+
4+
namespace Stravaig.Configuration.SqlServer;
5+
6+
public static class SqlServerConfigurationBuilderExtensions
7+
{
8+
public static IConfigurationBuilder AddSqlServer(this IConfigurationBuilder builder, Action<SqlServerConfigurationOptions>? optionsBuilder = null)
9+
{
10+
var options = new SqlServerConfigurationOptions();
11+
optionsBuilder?.Invoke(options);
12+
13+
if (!string.IsNullOrWhiteSpace(options.ConfigurationSection))
14+
SetOptionsFromConfiguration(builder.Build(), options);
15+
16+
return builder.Add(new SqlServerConfigurationSource(
17+
options.ConnectionString ?? throw new InvalidOperationException("Cannot build a SQL Server Configuration Provider with a null connection string."),
18+
options.SchemaName,
19+
options.TableName));
20+
}
21+
22+
private static void SetOptionsFromConfiguration(IConfigurationRoot configRoot, SqlServerConfigurationOptions options)
23+
{
24+
var section = configRoot.GetSection(options.ConfigurationSection);
25+
section.Bind(options);
26+
}
27+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace Stravaig.Configuration.SqlServer;
2+
3+
public class SqlServerConfigurationOptions
4+
{
5+
public string? ConnectionString { get; set; }
6+
public string? ConfigurationSection { get; set; }
7+
public string SchemaName { get; set; } = "Stravaig";
8+
public string TableName { get; set; } = "AppConfiguration";
9+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Microsoft.Extensions.Configuration;
4+
5+
namespace Stravaig.Configuration.SqlServer;
6+
7+
public class SqlServerConfigurationProvider : ConfigurationProvider
8+
{
9+
private readonly SqlServerConfigurationSource _source;
10+
private readonly IDataLoader _dataLoader;
11+
12+
public SqlServerConfigurationProvider(SqlServerConfigurationSource source)
13+
: this (source, new DataLoader())
14+
{
15+
}
16+
17+
internal SqlServerConfigurationProvider(SqlServerConfigurationSource source, IDataLoader dataLoader)
18+
{
19+
_source = source;
20+
_dataLoader = dataLoader;
21+
}
22+
23+
public override void Load()
24+
{
25+
var data = _dataLoader.RetrieveData(_source);
26+
Data = new Dictionary<string, string>(data, StringComparer.OrdinalIgnoreCase);
27+
}
28+
}

0 commit comments

Comments
 (0)