Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
using System.Data;
using ClickHouse.Client;
using Cnblogs.Architecture.Ddd.Infrastructure.Dapper;
using Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse;

namespace Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse;

/// <summary>
/// Clickhouse connection factory.
/// </summary>
public class ClickhouseDbConnectionFactory(IClickHouseDataSource dataSource) : IDbConnectionFactory
/// <typeparam name="TContext">The <see cref="ClickhouseDapperContext"/> this connection factory belongs to.</typeparam>
public class ClickhouseDbConnectionFactory<TContext>(IClickHouseDataSource dataSource) : IDbConnectionFactory
where TContext : ClickhouseDapperContext
{
/// <inheritdoc />
public IDbConnection CreateDbConnection()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using ClickHouse.Client;
using Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse;
using Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -21,8 +22,11 @@ public static void UseClickhouse<TContext>(
string connectionString)
where TContext : ClickhouseDapperContext
{
builder.UseDbConnectionFactory<ClickhouseDbConnectionFactory>();
builder.Services.AddClickHouseDataSource(connectionString);
var contextName = typeof(TContext).Name;
builder.UseDbConnectionFactory(sp
=> new ClickhouseDbConnectionFactory<TContext>(
sp.GetRequiredKeyedService<IClickHouseDataSource>(contextName)));
builder.Services.AddClickHouseDataSource(connectionString, serviceKey: contextName);
builder.Services.AddSingleton(new ClickhouseContextOptions<TContext>(connectionString));
builder.Services.Configure<ClickhouseContextCollection>(x => x.Add<TContext>());
builder.Services.AddHostedService<ClickhouseInitializeHostedService>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.1.1" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ public void UseDbConnectionFactory<TFactory>(TFactory factory)
c => c.AddDbConnectionFactory(_dapperContextTypeName, typeof(TFactory)));
}

/// <summary>
/// Add <typeparamref name="TFactory"/> by <paramref name="implementationFactory"/>.
/// </summary>
/// <param name="implementationFactory">The object initializer.</param>
/// <typeparam name="TFactory">The type of the factory.</typeparam>
public void UseDbConnectionFactory<TFactory>(Func<IServiceProvider, TFactory> implementationFactory)
where TFactory : class
{
Services.AddSingleton(implementationFactory);
Services.Configure<DbConnectionFactoryCollection>(
c => c.AddDbConnectionFactory(_dapperContextTypeName, typeof(TFactory)));
}

/// <summary>
/// Add <typeparamref name="TFactory"/> as <see cref="IDbConnectionFactory"/> and get instance from DI when used.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ public static class ServiceCollectionInjector
public static DapperConfigurationBuilder<TContext> AddDapperContext<TContext>(this IServiceCollection services)
where TContext : DapperContext
{
var alreadyAdded = services.Any(s => s.ServiceType == typeof(TContext));
if (alreadyAdded)
{
throw new InvalidOperationException($"Dapper context with name {typeof(TContext).Name} already added");
}

services.AddScoped<TContext>();
return new DapperConfigurationBuilder<TContext>(services);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="StackExchange.Redis" Version="2.8.58" />
<PackageReference Include="StackExchange.Redis" Version="2.9.11" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="MongoDB.Driver" Version="3.4.2" />
<PackageReference Include="MongoDB.Driver" Version="3.4.3" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Cnblogs.Serilog.Extensions" Version="1.1.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.3">
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Serilog.Sinks.InMemory" Version="0.16.0" />
<PackageReference Include="Serilog.Sinks.InMemory" Version="2.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<ItemGroup>
<PackageReference Include="xunit" Version="2.9.3"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1"/>
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.3">
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand All @@ -15,6 +15,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse\Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse.csproj" />
<ProjectReference Include="..\..\src\Cnblogs.Architecture.Ddd.Cqrs.EntityFramework\Cnblogs.Architecture.Ddd.Cqrs.EntityFramework.csproj"/>
<ProjectReference Include="..\..\src\Cnblogs.Architecture.Ddd.Cqrs.MongoDb\Cnblogs.Architecture.Ddd.Cqrs.MongoDb.csproj"/>
<ProjectReference Include="..\Cnblogs.Architecture.TestIntegrationEvents\Cnblogs.Architecture.TestIntegrationEvents.csproj"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using ClickHouse.Client;
using Cnblogs.Architecture.Ddd.Cqrs.Dapper;
using Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse;
using Microsoft.Extensions.DependencyInjection;

namespace Cnblogs.Architecture.UnitTests.Cqrs.Dapper;

public class ClickhouseDependencyInjectorTests
{
[Fact]
public void UseClickhouse_InjectSingle_Injected()
{
// Arrange
var services = new ServiceCollection();

// Act
services.AddDapperContext<TestClickhouseDapperContext>().UseClickhouse("HOST=clickhouse");
var serviceProvider = services.BuildServiceProvider();
var dbContext = serviceProvider.GetRequiredService<TestClickhouseDapperContext>();
var clickhouseDataSource =
serviceProvider.GetRequiredKeyedService<IClickHouseDataSource>(nameof(TestClickhouseDapperContext));

// Assert
Assert.NotNull(dbContext);
Assert.NotNull(clickhouseDataSource);
}

[Fact]
public void UseClickhouse_InjectMultiple_Injected()
{
// Arrange
var services = new ServiceCollection();

// Act
services.AddDapperContext<TestClickhouseDapperContext>().UseClickhouse("HOST=clickhouse");
services.AddDapperContext<TestAlterClickhouseDapperContext>().UseClickhouse("HOST=alterclickhouse");
var serviceProvider = services.BuildServiceProvider();
var dbContext = serviceProvider.GetRequiredService<TestClickhouseDapperContext>();
var alterContext = serviceProvider.GetRequiredService<TestAlterClickhouseDapperContext>();
var dbFactory = dbContext.Factory;
var alterFactory = alterContext.Factory;

// Assert
Assert.True(dbFactory is ClickhouseDbConnectionFactory<TestClickhouseDapperContext>);
Assert.True(alterFactory is ClickhouseDbConnectionFactory<TestAlterClickhouseDapperContext>);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using Cnblogs.Architecture.Ddd.Infrastructure.Dapper;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

namespace Cnblogs.Architecture.UnitTests.Cqrs.Dapper;

public class DapperConfigurationBuilderTests
{
[Fact]
public void UseDbConnectionFactory_Instance_AddInstance()
{
// Arrange
var services = new ServiceCollection();
var factory = new TestDbConnectionFactory();

// Act
services.AddDapperContext<TestDapperContext>().UseDbConnectionFactory(factory);
var serviceProvider = services.BuildServiceProvider();
var fetchedFactory = serviceProvider.GetService<TestDbConnectionFactory>();
var collection = serviceProvider.GetRequiredService<IOptions<DbConnectionFactoryCollection>>().Value;

// Assert
Assert.Equal(factory, fetchedFactory);
Assert.Equal(typeof(TestDbConnectionFactory), collection.GetFactory(nameof(TestDapperContext)));
}

[Fact]
public void UseDbConnectionFactory_Type_AddType()
{
// Arrange
var services = new ServiceCollection();

// Act
services.AddDapperContext<TestDapperContext>().UseDbConnectionFactory<TestDbConnectionFactory>();
var serviceProvider = services.BuildServiceProvider();
var fetchedFactory = serviceProvider.GetService<TestDbConnectionFactory>();
var collection = serviceProvider.GetRequiredService<IOptions<DbConnectionFactoryCollection>>().Value;

// Assert
Assert.NotNull(fetchedFactory);
Assert.Equal(typeof(TestDbConnectionFactory), collection.GetFactory(nameof(TestDapperContext)));
}

[Fact]
public void UseDbConnectionFactory_Func_AddFunc()
{
// Arrange
var services = new ServiceCollection();
var factory = new TestDbConnectionFactory();
services.AddKeyedSingleton("test", factory);

// Act
services.AddDapperContext<TestDapperContext>()
.UseDbConnectionFactory(sp => sp.GetRequiredKeyedService<TestDbConnectionFactory>("test"));
var serviceProvider = services.BuildServiceProvider();
var fetchedFactory = serviceProvider.GetRequiredService<TestDbConnectionFactory>();
var collection = serviceProvider.GetRequiredService<IOptions<DbConnectionFactoryCollection>>().Value;

// Assert
Assert.Equal(factory, fetchedFactory);
Assert.Equal(typeof(TestDbConnectionFactory), collection.GetFactory(nameof(TestDapperContext)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Microsoft.Extensions.DependencyInjection;

namespace Cnblogs.Architecture.UnitTests.Cqrs.Dapper;

public class DapperServiceCollectionInjectorTests
{
[Fact]
public void AddDapperContext_AddContext_Success()
{
// Arrange
var services = new ServiceCollection();

// Act
services.AddDapperContext<TestDapperContext>();

// Assert
Assert.Contains(services, s => s.ServiceType == typeof(TestDapperContext));
}

[Fact]
public void AddDapperContext_AddSameContextMultipleTimes_ThrowsException()
{
// Arrange
var services = new ServiceCollection();

// Act
services.AddDapperContext<TestDapperContext>();

// Assert
Assert.Throws<InvalidOperationException>(() => services.AddDapperContext<TestDapperContext>());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Cnblogs.Architecture.Ddd.Infrastructure.Dapper;
using Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse;
using Microsoft.Extensions.Options;

namespace Cnblogs.Architecture.UnitTests.Cqrs.Dapper;

public class TestAlterClickhouseDapperContext(
IOptions<DbConnectionFactoryCollection> dbConnectionFactoryCollection,
ClickhouseContextOptions<TestAlterClickhouseDapperContext> options,
IServiceProvider serviceProvider)
: ClickhouseDapperContext(dbConnectionFactoryCollection, options, serviceProvider)
{
/// <inheritdoc />
protected override void ConfigureModels(ClickhouseModelCollectionBuilder builder)
{
// ignore
}

public IDbConnectionFactory Factory => DbConnectionFactory;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Cnblogs.Architecture.Ddd.Infrastructure.Dapper;
using Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse;
using Microsoft.Extensions.Options;

namespace Cnblogs.Architecture.UnitTests.Cqrs.Dapper;

public class TestClickhouseDapperContext(
IOptions<DbConnectionFactoryCollection> dbConnectionFactoryCollection,
ClickhouseContextOptions<TestClickhouseDapperContext> options,
IServiceProvider serviceProvider)
: ClickhouseDapperContext(dbConnectionFactoryCollection, options, serviceProvider)
{
public bool ConfigureModelsCalled { get; set; }

public IDbConnectionFactory Factory => DbConnectionFactory;

/// <inheritdoc />
protected override void ConfigureModels(ClickhouseModelCollectionBuilder builder)
{
ConfigureModelsCalled = true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Cnblogs.Architecture.Ddd.Infrastructure.Dapper;
using Microsoft.Extensions.Options;

namespace Cnblogs.Architecture.UnitTests.Cqrs.Dapper;

public class TestDapperContext : DapperContext
{
/// <inheritdoc />
public TestDapperContext(
IOptions<DbConnectionFactoryCollection> dbConnectionFactoryCollection,
IServiceProvider sp)
: base(dbConnectionFactoryCollection, sp)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Data;
using Cnblogs.Architecture.Ddd.Infrastructure.Dapper;
using NSubstitute;

namespace Cnblogs.Architecture.UnitTests.Cqrs.Dapper;

public class TestDbConnectionFactory : IDbConnectionFactory
{
/// <inheritdoc />
public IDbConnection CreateDbConnection()
{
return Substitute.For<IDbConnection>();
}
}