diff --git a/Cnblogs.Architecture.sln b/Cnblogs.Architecture.sln
index 560d570..3e04f06 100644
--- a/Cnblogs.Architecture.sln
+++ b/Cnblogs.Architecture.sln
@@ -62,6 +62,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cnblogs.Architecture.Ddd.In
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cnblogs.Architecture.TestShared", "test\Cnblogs.Architecture.TestShared\Cnblogs.Architecture.TestShared.csproj", "{3B22F0CC-9A61-4D95-8ED9-F41B7FCBFC6F}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse", "src\Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse\Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse.csproj", "{73665E32-3D10-4F71-B893-4C65F36332D0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse", "src\Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse\Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse.csproj", "{4BD98FBF-FB98-4172-B352-BB7BF8761FCB}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -94,6 +98,8 @@ Global
{E7ABC399-AF71-46A6-A4D4-A38972BC7D50} = {D3A6DF01-017E-4088-936C-B3791F41DF53}
{A6A8FDC5-20E7-4776-9CB6-A2E43DCCBE7B} = {D3A6DF01-017E-4088-936C-B3791F41DF53}
{3B22F0CC-9A61-4D95-8ED9-F41B7FCBFC6F} = {772497F8-2CB1-4EA6-AEB8-482C3ECD0A9D}
+ {73665E32-3D10-4F71-B893-4C65F36332D0} = {D3A6DF01-017E-4088-936C-B3791F41DF53}
+ {4BD98FBF-FB98-4172-B352-BB7BF8761FCB} = {D3A6DF01-017E-4088-936C-B3791F41DF53}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{54D9D850-1CFC-485E-97FE-87F41C220523}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -200,5 +206,13 @@ Global
{3B22F0CC-9A61-4D95-8ED9-F41B7FCBFC6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B22F0CC-9A61-4D95-8ED9-F41B7FCBFC6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B22F0CC-9A61-4D95-8ED9-F41B7FCBFC6F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {73665E32-3D10-4F71-B893-4C65F36332D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {73665E32-3D10-4F71-B893-4C65F36332D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {73665E32-3D10-4F71-B893-4C65F36332D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {73665E32-3D10-4F71-B893-4C65F36332D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4BD98FBF-FB98-4172-B352-BB7BF8761FCB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4BD98FBF-FB98-4172-B352-BB7BF8761FCB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4BD98FBF-FB98-4172-B352-BB7BF8761FCB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4BD98FBF-FB98-4172-B352-BB7BF8761FCB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/ClickhouseContextCollection.cs b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/ClickhouseContextCollection.cs
new file mode 100644
index 0000000..d93603d
--- /dev/null
+++ b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/ClickhouseContextCollection.cs
@@ -0,0 +1,14 @@
+namespace Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse;
+
+///
+/// The collection for clickhouse contexts.
+///
+public class ClickhouseContextCollection
+{
+ internal List ContextTypes { get; } = new();
+
+ internal void Add()
+ {
+ ContextTypes.Add(typeof(TContext));
+ }
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/ClickhouseDbConnectionFactory.cs b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/ClickhouseDbConnectionFactory.cs
new file mode 100644
index 0000000..6021841
--- /dev/null
+++ b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/ClickhouseDbConnectionFactory.cs
@@ -0,0 +1,28 @@
+using System.Data;
+using ClickHouse.Client.ADO;
+using Cnblogs.Architecture.Ddd.Infrastructure.Dapper;
+
+namespace Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse;
+
+///
+/// Clickhouse connection factory.
+///
+public class ClickhouseDbConnectionFactory : IDbConnectionFactory
+{
+ private readonly string _connectionString;
+
+ ///
+ /// Create a clickhouse connection factory.
+ ///
+ /// The connection string.
+ public ClickhouseDbConnectionFactory(string connectionString)
+ {
+ _connectionString = connectionString;
+ }
+
+ ///
+ public IDbConnection CreateDbConnection()
+ {
+ return new ClickHouseConnection(_connectionString);
+ }
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/ClickhouseInitializeHostedService.cs b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/ClickhouseInitializeHostedService.cs
new file mode 100644
index 0000000..94420e4
--- /dev/null
+++ b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/ClickhouseInitializeHostedService.cs
@@ -0,0 +1,47 @@
+using Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Options;
+
+namespace Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse;
+
+///
+/// Hosed service to initialize clickhouse contexts.
+///
+public class ClickhouseInitializeHostedService : IHostedService
+{
+ private readonly ClickhouseContextCollection _collection;
+ private readonly IServiceProvider _serviceProvider;
+
+ ///
+ /// Create a .
+ ///
+ /// The contexts been registered.
+ /// The provider for contexts.
+ public ClickhouseInitializeHostedService(
+ IOptions collections,
+ IServiceProvider serviceProvider)
+ {
+ _serviceProvider = serviceProvider;
+ _collection = collections.Value;
+ }
+
+ ///
+ public Task StartAsync(CancellationToken cancellationToken)
+ {
+ using var scope = _serviceProvider.CreateScope();
+ foreach (var collectionContextType in _collection.ContextTypes)
+ {
+ var context = scope.ServiceProvider.GetRequiredService(collectionContextType) as ClickhouseDapperContext;
+ context?.Init();
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ return Task.CompletedTask;
+ }
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse.csproj b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse.csproj
new file mode 100644
index 0000000..d482735
--- /dev/null
+++ b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse.csproj
@@ -0,0 +1,14 @@
+
+
+
+
+ Provides clickhouse dapper integration.
+
+
+
+
+
+
+
+
+
diff --git a/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/DapperConfigurationBuilderExtension.cs b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/DapperConfigurationBuilderExtension.cs
new file mode 100644
index 0000000..590eace
--- /dev/null
+++ b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse/DapperConfigurationBuilderExtension.cs
@@ -0,0 +1,29 @@
+using Cnblogs.Architecture.Ddd.Cqrs.Dapper.Clickhouse;
+using Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse;
+using Microsoft.Extensions.DependencyInjection;
+
+// ReSharper disable once CheckNamespace
+namespace Cnblogs.Architecture.Ddd.Cqrs.Dapper;
+
+///
+/// Extension methods for inject clickhouse to dapper context.
+///
+public static class DapperConfigurationBuilderExtension
+{
+ ///
+ /// Use clickhouse as the underlying database.
+ ///
+ /// .
+ /// The connection string for clickhouse.
+ /// The context type been used.
+ public static void UseClickhouse(
+ this DapperConfigurationBuilder builder,
+ string connectionString)
+ where TContext : ClickhouseDapperContext
+ {
+ builder.UseDbConnectionFactory(new ClickhouseDbConnectionFactory(connectionString));
+ builder.Services.AddSingleton(new ClickhouseContextOptions(connectionString));
+ builder.Services.Configure(x => x.Add());
+ builder.Services.AddHostedService();
+ }
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.SqlServer/DapperConfigurationBuilderExtension.cs b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.SqlServer/DapperConfigurationBuilderExtension.cs
index 0e46e57..496efc5 100644
--- a/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.SqlServer/DapperConfigurationBuilderExtension.cs
+++ b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper.SqlServer/DapperConfigurationBuilderExtension.cs
@@ -1,19 +1,23 @@
-using Cnblogs.Architecture.Ddd.Infrastructure.Dapper;
+using Cnblogs.Architecture.Ddd.Cqrs.Dapper.SqlServer;
+using Cnblogs.Architecture.Ddd.Infrastructure.Dapper;
-namespace Cnblogs.Architecture.Ddd.Cqrs.Dapper.SqlServer;
+// ReSharper disable once CheckNamespace
+namespace Cnblogs.Architecture.Ddd.Cqrs.Dapper;
///
-/// 用于配置 Dapper Configuration 的扩展方法。
+/// Extension methods to configure dapper context.
///
public static class DapperConfigurationBuilderExtension
{
///
- /// 使用 SqlServer 配置
+ /// Configure to use sql server as underlying database.
///
- ///
- /// 连接字符串。
- public static void UseSqlServer(this DapperConfigurationBuilder builder, string connectionString)
+ ///
+ /// The connection string for sql server.
+ /// The type of context been configured.
+ public static void UseSqlServer(this DapperConfigurationBuilder builder, string connectionString)
+ where TContext : DapperContext
{
builder.UseDbConnectionFactory(new SqlServerDbConnectionFactory(connectionString));
}
-}
\ No newline at end of file
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper/DapperConfigurationBuilder.cs b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper/DapperConfigurationBuilder.cs
index c04f9cb..95cb79a 100644
--- a/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper/DapperConfigurationBuilder.cs
+++ b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper/DapperConfigurationBuilder.cs
@@ -7,20 +7,20 @@ namespace Cnblogs.Architecture.Ddd.Cqrs.Dapper;
///
/// Dapper 配置类。
///
-public class DapperConfigurationBuilder
+/// The context type been configured.
+public class DapperConfigurationBuilder
+ where TContext : DapperContext
{
- private readonly IServiceCollection _services;
private readonly string _dapperContextTypeName;
///
/// 创建一个 DapperConfigurationBuilder。
///
- /// 正在配置的 DapperContext 名称。
///
- public DapperConfigurationBuilder(string dapperContextTypeName, IServiceCollection services)
+ public DapperConfigurationBuilder(IServiceCollection services)
{
- _dapperContextTypeName = dapperContextTypeName;
- _services = services;
+ _dapperContextTypeName = typeof(TContext).Name;
+ Services = services;
}
///
@@ -31,7 +31,12 @@ public DapperConfigurationBuilder(string dapperContextTypeName, IServiceCollecti
public void UseDbConnectionFactory(TFactory factory)
where TFactory : IDbConnectionFactory
{
- _services.Configure(
+ Services.Configure(
c => c.AddDbConnectionFactory(_dapperContextTypeName, factory));
}
-}
\ No newline at end of file
+
+ ///
+ /// The underlying .
+ ///
+ public IServiceCollection Services { get; }
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper/ServiceCollectionInjector.cs b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper/ServiceCollectionInjector.cs
index 95970e6..f5a3080 100644
--- a/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper/ServiceCollectionInjector.cs
+++ b/src/Cnblogs.Architecture.Ddd.Cqrs.Dapper/ServiceCollectionInjector.cs
@@ -15,10 +15,10 @@ public static class ServiceCollectionInjector
/// 。
/// 的实现类型。
///
- public static DapperConfigurationBuilder AddDapperContext(this IServiceCollection services)
+ public static DapperConfigurationBuilder AddDapperContext(this IServiceCollection services)
where TContext : DapperContext
{
services.AddScoped();
- return new DapperConfigurationBuilder(typeof(TContext).Name, services);
+ return new DapperConfigurationBuilder(services);
}
-}
\ No newline at end of file
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseContextOptions.cs b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseContextOptions.cs
new file mode 100644
index 0000000..7aa7869
--- /dev/null
+++ b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseContextOptions.cs
@@ -0,0 +1,43 @@
+namespace Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse;
+
+///
+/// The options for clickhouse context.
+///
+/// The type of been configured.
+public class ClickhouseContextOptions : ClickhouseContextOptions
+ where TContext : ClickhouseDapperContext
+{
+ ///
+ /// Create a with given connection string.
+ ///
+ /// The connection string for clickhouse.
+ public ClickhouseContextOptions(string connectionString)
+ : base(connectionString)
+ {
+ }
+}
+
+///
+/// The options for .
+///
+public class ClickhouseContextOptions
+{
+ private readonly Dictionary _entityConfigurations = new();
+
+ internal ClickhouseContextOptions(string connectionString)
+ {
+ ConnectionString = connectionString;
+ }
+
+ internal string ConnectionString { get; }
+
+ internal void Add(Type type, ClickhouseEntityConfiguration configuration)
+ {
+ _entityConfigurations.Add(type, configuration);
+ }
+
+ internal ClickhouseEntityConfiguration? GetConfiguration()
+ {
+ return _entityConfigurations.GetValueOrDefault(typeof(T));
+ }
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseDapperContext.cs b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseDapperContext.cs
new file mode 100644
index 0000000..bd12207
--- /dev/null
+++ b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseDapperContext.cs
@@ -0,0 +1,66 @@
+using ClickHouse.Client.Copy;
+using Microsoft.Extensions.Options;
+
+namespace Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse;
+
+///
+/// DapperContext that specialized for clickhouse.
+///
+public abstract class ClickhouseDapperContext : DapperContext
+{
+ private readonly ClickhouseContextOptions _options;
+
+ ///
+ /// Create a .
+ ///
+ /// The underlying collection.
+ /// The options used for this context.
+ protected ClickhouseDapperContext(
+ IOptions dbConnectionFactoryCollection,
+ ClickhouseContextOptions options)
+ : base(dbConnectionFactoryCollection)
+ {
+ _options = options;
+ }
+
+ ///
+ /// Init context, register models, etc.
+ ///
+ public void Init()
+ {
+ var builder = new ClickhouseModelCollectionBuilder();
+ ConfigureModels(builder);
+ builder.Build(_options);
+ }
+
+ ///
+ /// Configure models that related to this context.
+ ///
+ /// .
+ protected abstract void ConfigureModels(ClickhouseModelCollectionBuilder builder);
+
+ ///
+ /// Bulk write entities to clickhouse.
+ ///
+ /// The entity to be written.
+ /// The type of entity.
+ /// Throw when is not registered.
+ public async Task BulkWriteAsync(IEnumerable entities)
+ where T : class
+ {
+ var configuration = _options.GetConfiguration();
+ if (configuration is null)
+ {
+ throw new InvalidOperationException(
+ $"The model type {typeof(T).Name} is not registered, make sure you have called builder.Entity() at ConfigureModels()");
+ }
+
+ using var bulkCopyInterface = new ClickHouseBulkCopy(_options.ConnectionString)
+ {
+ DestinationTableName = configuration.TableName
+ };
+
+ var objs = entities.Select(x => configuration.ToObjectArray(x));
+ await bulkCopyInterface.WriteToServerAsync(objs, configuration.ColumnNames);
+ }
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseEntityConfiguration.cs b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseEntityConfiguration.cs
new file mode 100644
index 0000000..2cb45aa
--- /dev/null
+++ b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseEntityConfiguration.cs
@@ -0,0 +1,11 @@
+using System.Reflection;
+
+namespace Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse;
+
+internal record ClickhouseEntityConfiguration(string TableName, PropertyInfo[] Properties, string[] ColumnNames)
+{
+ internal object?[] ToObjectArray(object entity)
+ {
+ return Properties.Select(x => x.GetValue(entity)).ToArray();
+ }
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseModelBuilder.cs b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseModelBuilder.cs
new file mode 100644
index 0000000..3850e69
--- /dev/null
+++ b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseModelBuilder.cs
@@ -0,0 +1,64 @@
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse;
+
+///
+/// Configure mapping between clickhouse and C# class.
+///
+/// The type of model been configured.
+public class ClickhouseModelBuilder : IClickhouseModelBuilder
+{
+ private readonly Dictionary> _propertyBuilders;
+ private string _tableName;
+
+ internal ClickhouseModelBuilder()
+ {
+ _tableName = typeof(T).Name;
+ _propertyBuilders = typeof(T).GetProperties().Where(x => x.GetGetMethod() != null)
+ .Select(x => new ClickhouseModelPropertyBuilder(this, x)).ToDictionary(x => x.PropertyInfo.Name, x => x);
+ }
+
+ ///
+ /// Map model type to specific table.
+ ///
+ /// The full name of table, includes database name. e.x. <database>.<table>
+ /// .
+ public ClickhouseModelBuilder ToTable(string tableName)
+ {
+ _tableName = tableName;
+ return this;
+ }
+
+ ///
+ /// Start configure property.
+ ///
+ /// The property been configured.
+ /// The type of property.
+ /// .
+ /// When no suitable property was fount by .
+ public ClickhouseModelPropertyBuilder Property(Expression> propertyGetter)
+ {
+ if ((propertyGetter.Body as MemberExpression)?.Member is not PropertyInfo propertyInfo)
+ {
+ throw new InvalidOperationException("No suitable property can be found from given expression");
+ }
+
+ var builder = _propertyBuilders.GetValueOrDefault(propertyInfo.Name);
+ if (builder is null)
+ {
+ throw new InvalidOperationException($"No suitable property was found by name: {propertyInfo.Name}");
+ }
+
+ return builder;
+ }
+
+ ClickhouseEntityConfiguration IClickhouseModelBuilder.Build()
+ {
+ var builders = _propertyBuilders.Values.Where(x => x.IsIgnored == false).ToArray();
+ return new ClickhouseEntityConfiguration(
+ _tableName,
+ builders.Select(x => x.PropertyInfo).ToArray(),
+ builders.Select(x => x.ColumnName).ToArray());
+ }
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseModelCollectionBuilder.cs b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseModelCollectionBuilder.cs
new file mode 100644
index 0000000..f755002
--- /dev/null
+++ b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseModelCollectionBuilder.cs
@@ -0,0 +1,30 @@
+namespace Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse;
+
+///
+/// Configure models for clickhouse.
+///
+public class ClickhouseModelCollectionBuilder
+{
+ private readonly Dictionary _builders = new();
+
+ ///
+ /// Register an entity to context.
+ ///
+ /// The type of entity.
+ /// .
+ public ClickhouseModelBuilder Entity()
+ where T : class
+ {
+ var builder = new ClickhouseModelBuilder();
+ _builders.Add(typeof(T), builder);
+ return builder;
+ }
+
+ internal void Build(ClickhouseContextOptions options)
+ {
+ foreach (var (key, value) in _builders)
+ {
+ options.Add(key, value.Build());
+ }
+ }
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseModelPropertyBuilder.cs b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseModelPropertyBuilder.cs
new file mode 100644
index 0000000..066d26c
--- /dev/null
+++ b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/ClickhouseModelPropertyBuilder.cs
@@ -0,0 +1,48 @@
+using System.Reflection;
+
+namespace Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse;
+
+///
+/// Configuration builder for clickhouse model property;
+///
+/// The entity type that property belongs.
+public class ClickhouseModelPropertyBuilder
+{
+ ///
+ /// Create a ClickhouseModelPropertyBuilder from entity builder.
+ ///
+ /// The parent entity builder.
+ /// The property been configured.
+ public ClickhouseModelPropertyBuilder(ClickhouseModelBuilder entityBuilder, PropertyInfo propertyInfo)
+ {
+ PropertyInfo = propertyInfo;
+ ColumnName = propertyInfo.Name;
+ }
+
+ ///
+ /// Configure column name for this property.
+ ///
+ /// New column name.
+ ///
+ public ClickhouseModelPropertyBuilder HasColumnName(string name)
+ {
+ ColumnName = name;
+ return this;
+ }
+
+ ///
+ /// Ignore this property from mapping.
+ ///
+ ///
+ public ClickhouseModelPropertyBuilder Ignore()
+ {
+ IsIgnored = true;
+ return this;
+ }
+
+ internal string ColumnName { get; private set; }
+
+ internal PropertyInfo PropertyInfo { get; }
+
+ internal bool IsIgnored { get; private set; }
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse.csproj b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse.csproj
new file mode 100644
index 0000000..dd522db
--- /dev/null
+++ b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse.csproj
@@ -0,0 +1,19 @@
+
+
+
+
+ Provides implementation for persistance layer of DDD with Dapper and Clickhouse.
+ Commonly used types:
+ Cnblogs.Architecture.Ddd.Infrasturcture.Dapper.Clickhouse.ClickhouseDapperContext
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/IClickhouseModelBuilder.cs b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/IClickhouseModelBuilder.cs
new file mode 100644
index 0000000..1e9a36d
--- /dev/null
+++ b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse/IClickhouseModelBuilder.cs
@@ -0,0 +1,6 @@
+namespace Cnblogs.Architecture.Ddd.Infrastructure.Dapper.Clickhouse;
+
+internal interface IClickhouseModelBuilder
+{
+ ClickhouseEntityConfiguration Build();
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper/DapperContext.cs b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper/DapperContext.cs
index f00ab04..77acd16 100644
--- a/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper/DapperContext.cs
+++ b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper/DapperContext.cs
@@ -28,4 +28,4 @@ protected DapperContext(IOptions dbConnectionFact
///
///
public IDbConnection CreateDbConnection() => DbConnectionFactory.CreateDbConnection();
-}
\ No newline at end of file
+}
diff --git a/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper/DbConnectionFactoryCollection.cs b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper/DbConnectionFactoryCollection.cs
index d99f62c..3b25a93 100644
--- a/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper/DbConnectionFactoryCollection.cs
+++ b/src/Cnblogs.Architecture.Ddd.Infrastructure.Dapper/DbConnectionFactoryCollection.cs
@@ -12,12 +12,13 @@ public class DbConnectionFactoryCollection
///
/// 名称。
/// 工厂示例。
+ /// Throw when already been registered with other factory.
public void AddDbConnectionFactory(string name, IDbConnectionFactory factory)
{
- if (_factories.ContainsKey(name))
+ if (_factories.TryGetValue(name, out var value))
{
- _factories[name] = factory;
- return;
+ throw new InvalidOperationException(
+ $"The dapper context already configured with db connection factory: {value.GetType().Name}");
}
_factories.Add(name, factory);
@@ -32,4 +33,4 @@ public IDbConnectionFactory GetFactory(string name)
{
return _factories[name];
}
-}
\ No newline at end of file
+}