From 54e1ed6fdb87e999d29ced1d9809bf9443eda85b Mon Sep 17 00:00:00 2001
From: Daily <963922242@qq.com>
Date: Thu, 30 May 2024 10:47:10 +0800
Subject: [PATCH 1/4] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E5=B9=B6=E4=BF=AE?=
=?UTF-8?q?=E5=A4=8DCilckhouse=20CodeFirst=E4=B8=BB=E9=94=AE=E9=97=AE?=
=?UTF-8?q?=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
FreeSql.DbContext/FreeSql.DbContext.xml | 9 +
.../ClickHouse/ClickhouseIssueTest.cs | 136 ++++++++
FreeSql/FreeSql.xml | 299 ++++++++++++++++++
.../ClickHouseCodeFirst.cs | 34 +-
4 files changed, 459 insertions(+), 19 deletions(-)
create mode 100644 FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs
diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml
index 6c9bef48..197e6480 100644
--- a/FreeSql.DbContext/FreeSql.DbContext.xml
+++ b/FreeSql.DbContext/FreeSql.DbContext.xml
@@ -826,5 +826,14 @@
+
+
+ 批量注入 Repository,可以参考代码自行调整
+
+
+
+
+
+
diff --git a/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs b/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs
new file mode 100644
index 00000000..dac6315a
--- /dev/null
+++ b/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs
@@ -0,0 +1,136 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using FreeSql.DataAnnotations;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace FreeSql.Tests.ClickHouse
+{
+ public class ClickhouseIssueTest
+ {
+ private readonly ITestOutputHelper _output;
+
+ private static IFreeSql _fsql;
+
+ public ClickhouseIssueTest(ITestOutputHelper output)
+ {
+ _output = output;
+
+ _fsql = new FreeSqlBuilder().UseConnectionString(DataType.ClickHouse,
+ "Host=192.168.1.123;Port=8123;Database=test_issue;Compress=True;Min Pool Size=1")
+ .UseMonitorCommand(cmd => _output.WriteLine($"线程:{cmd.CommandText}\r\n"))
+ .UseNoneCommandParameter(true)
+ .UseAdoConnectionPool(true)
+ .Build();
+ }
+
+ #region https: //github.com/dotnetcore/FreeSql/issues/1813
+
+ [Fact]
+ public void TestIssue1813()
+ {
+ //var personsUpdate = new List
+ //{
+ // new Person
+ // {
+ // Id = 1,
+ // Name = $"test2{DateTime.Now.Millisecond}",
+ // Age = 20,
+ // CreateTime = DateTime.Now
+ // },
+ // new Person
+ // {
+ // Id = 2,
+ // Name = "test3"+ 286,
+ // Age = 22,
+ // CreateTime = DateTime.Now
+ // }
+ //};
+
+ //_fsql.Update().SetSource()
+ }
+
+ [Fact]
+ public void TestIssue1813CodeFirst()
+ {
+ _fsql.CodeFirst.SyncStructure();
+ var insertSingle = _fsql.Insert(new Person
+ {
+ Name = $"test{DateTime.Now.Millisecond}",
+ Age = 18,
+ CreateTime = DateTime.Now
+ }).ExecuteAffrows();
+
+ _output.WriteLine(insertSingle.ToString());
+
+ var persons = new List
+ {
+ new Person
+ {
+ Name = $"test2{DateTime.Now.Millisecond}",
+ Age = 20,
+ CreateTime = DateTime.Now
+ },
+ new Person
+ {
+ Name = "test3" + 286,
+ Age = 22,
+ CreateTime = DateTime.Now
+ }
+ };
+
+ var insertMany = _fsql.Insert(persons).ExecuteAffrows();
+ }
+ [Fact]
+ public void TestIssue1813CodeFirst2()
+ {
+ _fsql.CodeFirst.SyncStructure();
+ var insertSingle = _fsql.Insert(new Person
+ {
+ Id = Guid.NewGuid().ToString(),
+ Name = $"test{DateTime.Now.Millisecond}",
+ Age = 18,
+ CreateTime = DateTime.Now
+ }).ExecuteAffrows();
+
+ _output.WriteLine(insertSingle.ToString());
+
+ var persons = new List
+ {
+ new Person
+ {
+ Id = Guid.NewGuid().ToString(),
+ Name = $"test2{DateTime.Now.Millisecond}",
+ Age = 20,
+ CreateTime = DateTime.Now
+ },
+ new Person
+ {
+ Id = Guid.NewGuid().ToString(),
+ Name = "test3" + 286,
+ Age = 22,
+ CreateTime = DateTime.Now
+ }
+ };
+
+ var insertMany = _fsql.Insert(persons).ExecuteAffrows();
+ }
+
+
+
+ public class Person
+ {
+ [Column(IsPrimary = true, IsIdentity = true)]
+ public string Id { get; set; }
+ public string Name { get; set; }
+ public int Age { get; set; }
+ public DateTime CreateTime { get; set; }
+ public DateTime? UpdateTime { get; set; }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml
index 4bdcab9f..5f6a3f2a 100644
--- a/FreeSql/FreeSql.xml
+++ b/FreeSql/FreeSql.xml
@@ -1104,6 +1104,93 @@
+
+
+ 动态创建实体类型
+
+
+
+
+ 配置Class
+
+ 类名
+ 类标记的特性[Table(Name = "xxx")] [Index(xxxx)]
+
+
+
+
+ 获取类型构建器,可作为要构建的Type来引用
+
+
+
+
+ 配置属性
+
+ 属性名称
+ 属性类型
+ 属性标记的特性-支持多个
+
+
+
+
+ 配置属性
+
+ 属性名称
+ 属性类型
+ 该属性是否重写父类属性
+ 属性标记的特性-支持多个
+
+
+
+
+ 配置属性
+
+ 属性名称
+ 属性类型
+ 该属性是否重写父类属性
+ 属性默认值
+ 属性标记的特性-支持多个
+
+
+
+
+ 配置父类
+
+ 父类类型
+
+
+
+
+ Override属性
+
+
+
+
+
+ Emit动态创建出Class - Type
+
+
+
+
+
+ Emit动态创建出Class - Type,不附带获取TableInfo
+
+
+
+
+
+ 首字母小写
+
+
+
+
+
+
+ 首字母大写
+
+
+
+
获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 ""
@@ -3283,6 +3370,13 @@
+
+
+ 执行SQL语句,返回更新后的记录
+ 注意:此方法只有 Postgresql/SqlServer 有效果
+
+
+
指定事务对象
@@ -3627,6 +3721,177 @@
+
+
+ 测试数据库是否连接正确,本方法执行如下命令:
+ MySql/SqlServer/PostgreSQL/达梦/人大金仓/神通: SELECT 1
+ Oracle: SELECT 1 FROM dual
+
+ 命令超时设置(秒)
+
+ true: 成功, false: 失败
+
+
+
+ 查询,若使用读写分离,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】
+
+
+
+
+
+
+
+
+
+ 查询,ExecuteReaderAsync(dr => {}, "select * from user where age > @age", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
+ 查询
+
+
+
+
+
+
+
+
+ 查询,ExecuteArrayAsync("select * from user where age > @age", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
+ 查询
+
+
+
+
+
+
+
+
+ 查询,ExecuteDataSetAsync("select * from user where age > @age; select 2", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
+ 查询
+
+
+
+
+
+
+
+
+ 查询,ExecuteDataTableAsync("select * from user where age > @age", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
+ 在【主库】执行
+
+
+
+
+
+
+
+
+ 在【主库】执行,ExecuteNonQueryAsync("delete from user where age > @age", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
+ 在【主库】执行
+
+
+
+
+
+
+
+
+ 在【主库】执行,ExecuteScalarAsync("select 1 from user where age > @age", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
+ 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new SqlParameter { ParameterName = "age", Value = 25 })
+
+
+
+
+
+
+
+
+
+
+ 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
+
+ 执行SQL返回对象集合,Query<User>("select * from user where age > @age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 })
+
+
+
+
+
+
+
+
+
+
+
+ 执行SQL返回对象集合,Query<User, Address>("select * from user where age > @age; select * from address", new { age = 25 })
+ 提示:parms 参数还可以传 Dictionary<string, object>
+
+
+
+
+
+
+
+
可自定义解析表达式
@@ -4626,6 +4891,12 @@
超时
+
+
+ 获取资源
+
+
+
使用完毕后,归还资源
@@ -4701,6 +4972,12 @@
资源对象
+
+
+ 从对象池获取对象成功的时候触发,通过该方法统计或初始化对象
+
+ 资源对象
+
归还对象给对象池的时候触发
@@ -5631,6 +5908,28 @@
请使用 fsql.InsertDict(dict) 方法插入字典数据
+
+
+ 动态构建Class Type
+
+
+
+
+
+ 根据字典,创建 table 对应的实体对象
+
+
+
+
+
+
+
+ 根据实体对象,创建 table 对应的字典
+
+
+
+
+
C#: that >= between && that <= and
diff --git a/Providers/FreeSql.Provider.ClickHouse/ClickHouseCodeFirst.cs b/Providers/FreeSql.Provider.ClickHouse/ClickHouseCodeFirst.cs
index bd4e4854..15704eef 100644
--- a/Providers/FreeSql.Provider.ClickHouse/ClickHouseCodeFirst.cs
+++ b/Providers/FreeSql.Provider.ClickHouse/ClickHouseCodeFirst.cs
@@ -254,25 +254,25 @@ namespace FreeSql.ClickHouse
sb.Append("TYPE set(8192) GRANULARITY 5,");
}
- sb.Remove(sb.Length - 1, 1);
+ //sb.Remove(sb.Length - 1, 1);
+
+ if (tb.Primarys.Any())
+ {
+ var primaryKeys = string.Join(",", tb.Primarys.Select(p => _commonUtils.QuoteSqlName(p.Attribute.Name)));
+ sb.Append(" \r\n PRIMARY KEY ");
+ sb.Append($"( {primaryKeys} ) ");
+ }
+
sb.Append("\r\n) ");
sb.Append("\r\nENGINE = MergeTree()");
if (tb.Primarys.Any())
{
- sb.Append(" \r\nORDER BY ( ");
- var ls = new StringBuilder();
- foreach (var tbcol in tb.Primarys)
- ls.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
- sb.Append(ls);
- sb.Remove(sb.Length - 2, 2);
- sb.Append(" )");
- sb.Append(" \r\nPRIMARY KEY ");
- sb.Append($"({ls}) ");
- sb.Remove(sb.Length - 2, 2).Append(",");
+ var primaryKeys = string.Join(",", tb.Primarys.Select(p => _commonUtils.QuoteSqlName(p.Attribute.Name)));
+ sb.Append(" \r\nORDER BY ");
+ sb.Append($"( {primaryKeys} ) ");
}
- sb.Remove(sb.Length - 1, 1);
//if (string.IsNullOrEmpty(tb.Comment) == false)
// sb.Append(" Comment=").Append(_commonUtils.FormatSql("{0}", tb.Comment));
sb.Append(" SETTINGS index_granularity = 8192;\r\n");
@@ -477,16 +477,12 @@ where a.database in ({0}) and a.table in ({1})", tboldname ?? tbname);
if (tb.Primarys.Any())
{
+ var primaryKeys = string.Join(",", tb.Primarys.Select(p => _commonUtils.QuoteSqlName(p.Attribute.Name)));
sb.Append(" \r\nORDER BY ( ");
- var ls = new StringBuilder();
- foreach (var tbcol in tb.Primarys)
- ls.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
- sb.Append(ls);
- sb.Remove(sb.Length - 2, 2);
+ sb.Append(primaryKeys);
sb.Append(" )");
sb.Append(" \r\nPRIMARY KEY ");
- sb.Append($"({ls}) ");
- sb.Remove(sb.Length - 2, 2).Append(",");
+ sb.Append($"({primaryKeys}) ");
}
sb.Remove(sb.Length - 1, 1);
From 9aef33e3df2951039ff2d3db3a9c9e397ae2c969 Mon Sep 17 00:00:00 2001
From: Daily <963922242@qq.com>
Date: Thu, 30 May 2024 11:27:49 +0800
Subject: [PATCH 2/4] =?UTF-8?q?=E8=A7=A3=E5=86=B3ClickHouse=20=E6=89=B9?=
=?UTF-8?q?=E9=87=8F=E6=9B=B4=E6=96=B0DateTime=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ClickHouse/ClickhouseIssueTest.cs | 48 +++++++++++--------
.../ClickHouseUtils.cs | 2 +-
.../Curd/ClickHouseUpdate.cs | 11 +++++
3 files changed, 41 insertions(+), 20 deletions(-)
diff --git a/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs b/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs
index dac6315a..71bf127f 100644
--- a/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs
@@ -22,7 +22,7 @@ namespace FreeSql.Tests.ClickHouse
_fsql = new FreeSqlBuilder().UseConnectionString(DataType.ClickHouse,
"Host=192.168.1.123;Port=8123;Database=test_issue;Compress=True;Min Pool Size=1")
.UseMonitorCommand(cmd => _output.WriteLine($"线程:{cmd.CommandText}\r\n"))
- .UseNoneCommandParameter(true)
+ .UseNoneCommandParameter(false)
.UseAdoConnectionPool(true)
.Build();
}
@@ -32,25 +32,35 @@ namespace FreeSql.Tests.ClickHouse
[Fact]
public void TestIssue1813()
{
- //var personsUpdate = new List
- //{
- // new Person
- // {
- // Id = 1,
- // Name = $"test2{DateTime.Now.Millisecond}",
- // Age = 20,
- // CreateTime = DateTime.Now
- // },
- // new Person
- // {
- // Id = 2,
- // Name = "test3"+ 286,
- // Age = 22,
- // CreateTime = DateTime.Now
- // }
- //};
+ //普通修改
+ _fsql.Update()
+ .Set(p => p.Name == "update_name")
+ .Set(p => p.UpdateTime == DateTime.Now)
+ .Where(p => p.Id == "25e8d92e-29f2-43ff-b861-9ade0eec4041")
+ .ExecuteAffrows();
+
+ //批量修改
+ var updatePerson = new List();
+ updatePerson.Add(new Person
+ {
+ Id = "9cd7af52-85cc-4d26-898a-4020cadb0491",
+ Name = "update_name1",
+ UpdateTime = DateTime.Now
+ });
+
+ updatePerson.Add(new Person
+ {
+ Id = "bd9f9ed6-bd03-4675-abb4-12b7fdac7678",
+ Name = "update_name2",
+ UpdateTime = DateTime.Now
+ });
+
+ _fsql.Update().SetSource(updatePerson).UpdateColumns(person => new
+ {
+ person.Name,
+ person.UpdateTime,
+ }).ExecuteAffrows();
- //_fsql.Update().SetSource()
}
[Fact]
diff --git a/Providers/FreeSql.Provider.ClickHouse/ClickHouseUtils.cs b/Providers/FreeSql.Provider.ClickHouse/ClickHouseUtils.cs
index a4b93bb2..0061b284 100644
--- a/Providers/FreeSql.Provider.ClickHouse/ClickHouseUtils.cs
+++ b/Providers/FreeSql.Provider.ClickHouse/ClickHouseUtils.cs
@@ -158,7 +158,7 @@ namespace FreeSql.ClickHouse
var ts = (TimeSpan)value;
value = $"{Math.Floor(ts.TotalHours)}:{ts.Minutes}:{ts.Seconds}";
}
- else if (value is Array)
+ else if (value is Array)
{
var valueArr = value as Array;
var eleType = type.GetElementType();
diff --git a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs
index 3714bc27..740f63be 100644
--- a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs
+++ b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs
@@ -7,6 +7,7 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using DateTime = System.DateTime;
namespace FreeSql.ClickHouse.Curd
{
@@ -167,6 +168,16 @@ namespace FreeSql.ClickHouse.Curd
var colsql = _noneParameter ? _commonUtils.GetNoneParamaterSqlValue(_paramsSource, "u", col, col.Attribute.MapType, val) :
_commonUtils.QuoteWriteParamterAdapter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"p_{_paramsSource.Count}"));
+
+ //判断是否是DateTime类型,如果是DateTime类型,需要转换成ClickHouse支持的时间格式
+ if (col.Attribute.MapType == typeof(DateTime) || col.Attribute.MapType == typeof(DateTime?) )
+ {
+ //获取当前实时区
+ var timeZone = TimeZoneInfo.Local;
+
+ colsql = $"toDateTime({colsql},'Asia/Shanghai')";
+ }
+
cwsb.Append(_commonUtils.RewriteColumn(col, colsql));
if (_noneParameter == false)
_commonUtils.AppendParamter(_paramsSource, null, col, col.Attribute.MapType, val);
From 989cf290f645bb3552ff578ed0ba18e7d32cb7d0 Mon Sep 17 00:00:00 2001
From: Daily <963922242@qq.com>
Date: Thu, 30 May 2024 11:39:48 +0800
Subject: [PATCH 3/4] =?UTF-8?q?=E6=B5=8B=E8=AF=95ClickHouse=20=E6=89=B9?=
=?UTF-8?q?=E9=87=8F=E6=9B=B4=E6=96=B0DateTime=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ClickHouse/ClickhouseIssueTest.cs | 24 +++++++++++--------
.../Curd/ClickHouseUpdate.cs | 2 --
2 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs b/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs
index 71bf127f..cf84442a 100644
--- a/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs
@@ -22,7 +22,7 @@ namespace FreeSql.Tests.ClickHouse
_fsql = new FreeSqlBuilder().UseConnectionString(DataType.ClickHouse,
"Host=192.168.1.123;Port=8123;Database=test_issue;Compress=True;Min Pool Size=1")
.UseMonitorCommand(cmd => _output.WriteLine($"线程:{cmd.CommandText}\r\n"))
- .UseNoneCommandParameter(false)
+ .UseNoneCommandParameter(true)
.UseAdoConnectionPool(true)
.Build();
}
@@ -45,22 +45,25 @@ namespace FreeSql.Tests.ClickHouse
{
Id = "9cd7af52-85cc-4d26-898a-4020cadb0491",
Name = "update_name1",
- UpdateTime = DateTime.Now
+ UpdateTime = DateTime.Now,
+ CreateTime = DateTime.Parse("2024-05-30 10:01:02")
});
updatePerson.Add(new Person
{
Id = "bd9f9ed6-bd03-4675-abb4-12b7fdac7678",
Name = "update_name2",
- UpdateTime = DateTime.Now
+ UpdateTime = DateTime.Now,
+ CreateTime = DateTime.Parse("2024-05-30 10:01:02")
});
- _fsql.Update().SetSource(updatePerson).UpdateColumns(person => new
- {
- person.Name,
- person.UpdateTime,
- }).ExecuteAffrows();
-
+ var sql = _fsql.Update().SetSource(updatePerson)
+ .UpdateColumns(person => new
+ {
+ person.Name,
+ person.UpdateTime,
+ person.CreateTime
+ }).ToSql();
}
[Fact]
@@ -94,6 +97,7 @@ namespace FreeSql.Tests.ClickHouse
var insertMany = _fsql.Insert(persons).ExecuteAffrows();
}
+
[Fact]
public void TestIssue1813CodeFirst2()
{
@@ -130,11 +134,11 @@ namespace FreeSql.Tests.ClickHouse
}
-
public class Person
{
[Column(IsPrimary = true, IsIdentity = true)]
public string Id { get; set; }
+
public string Name { get; set; }
public int Age { get; set; }
public DateTime CreateTime { get; set; }
diff --git a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs
index 740f63be..9f90cdab 100644
--- a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs
+++ b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs
@@ -173,8 +173,6 @@ namespace FreeSql.ClickHouse.Curd
if (col.Attribute.MapType == typeof(DateTime) || col.Attribute.MapType == typeof(DateTime?) )
{
//获取当前实时区
- var timeZone = TimeZoneInfo.Local;
-
colsql = $"toDateTime({colsql},'Asia/Shanghai')";
}
From a53cbdd3db9a6490b28c8d0e1caf7711d28b86e8 Mon Sep 17 00:00:00 2001
From: Daily <963922242@qq.com>
Date: Thu, 30 May 2024 14:30:08 +0800
Subject: [PATCH 4/4] =?UTF-8?q?ClickHouse=E8=A1=A8=E5=88=86=E5=8C=BA?=
=?UTF-8?q?=E6=94=AF=E6=8C=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ClickHouse/ClickhouseIssueTest.cs | 32 +++++++++++++++
.../ClickHousePartitionAttribute.cs | 17 ++++++++
.../ClickHouseCodeFirst.cs | 40 +++++++++++++++----
3 files changed, 81 insertions(+), 8 deletions(-)
create mode 100644 Providers/FreeSql.Provider.ClickHouse/Attributes/ClickHousePartitionAttribute.cs
diff --git a/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs b/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs
index cf84442a..a518aeff 100644
--- a/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickhouseIssueTest.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FreeSql.DataAnnotations;
+using FreeSql.Provider.ClickHouse.Attributes;
using Xunit;
using Xunit.Abstractions;
@@ -141,10 +142,41 @@ namespace FreeSql.Tests.ClickHouse
public string Name { get; set; }
public int Age { get; set; }
+
public DateTime CreateTime { get; set; }
+
public DateTime? UpdateTime { get; set; }
}
#endregion
+
+ #region https: //github.com/dotnetcore/FreeSql/issues/1814
+
+ public class Test1814Table
+ {
+ [Column(IsPrimary = true, IsIdentity = true)]
+ public int Id { get; set; }
+
+ public string Name { get; set; }
+
+ [ClickHousePartition]
+ [Column(Name = "create_time")]
+ public DateTime CreateTime { get; set; }
+ }
+
+ [Fact]
+ public void TestIssue1814()
+ {
+ _fsql.CodeFirst.SyncStructure();
+
+ var insert = _fsql.Insert(new Test1814Table
+ {
+ Name = "test",
+ CreateTime = DateTime.Now
+ }).ExecuteAffrows();
+
+ var query = _fsql.Select().ToList();
+ }
+ #endregion
}
}
\ No newline at end of file
diff --git a/Providers/FreeSql.Provider.ClickHouse/Attributes/ClickHousePartitionAttribute.cs b/Providers/FreeSql.Provider.ClickHouse/Attributes/ClickHousePartitionAttribute.cs
new file mode 100644
index 00000000..c19c31dd
--- /dev/null
+++ b/Providers/FreeSql.Provider.ClickHouse/Attributes/ClickHousePartitionAttribute.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace FreeSql.Provider.ClickHouse.Attributes
+{
+ [AttributeUsage(AttributeTargets.Property)]
+ public class ClickHousePartitionAttribute : Attribute
+ {
+ public ClickHousePartitionAttribute(string format = "toYYYYMM({0})")
+ {
+ Format = format;
+ }
+
+ public string Format { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Providers/FreeSql.Provider.ClickHouse/ClickHouseCodeFirst.cs b/Providers/FreeSql.Provider.ClickHouse/ClickHouseCodeFirst.cs
index 15704eef..110172ee 100644
--- a/Providers/FreeSql.Provider.ClickHouse/ClickHouseCodeFirst.cs
+++ b/Providers/FreeSql.Provider.ClickHouse/ClickHouseCodeFirst.cs
@@ -8,8 +8,10 @@ using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Data.Common;
+using System.Reflection;
using FreeSql.Internal.ObjectPool;
using ClickHouse.Client.ADO;
+using FreeSql.Provider.ClickHouse.Attributes;
namespace FreeSql.ClickHouse
{
@@ -95,10 +97,11 @@ namespace FreeSql.ClickHouse
{
var arrayDbType = $"Array({value.dbtype})";
var defaultArray = new ArrayList(0);
- return new DbInfoResult(Convert.ToInt32(DbType.Object), arrayDbType, arrayDbType, false,defaultArray);
+ return new DbInfoResult(Convert.ToInt32(DbType.Object), arrayDbType, arrayDbType, false,
+ defaultArray);
}
-
}
+
return null;
}
@@ -132,7 +135,7 @@ namespace FreeSql.ClickHouse
if (interfaces.Any(t => t.Name == "IEnumerable"))
flag = true;
- if (type.Name == "Array")
+ if (type.Name == "Array")
{
flag = true;
resultType = typeof(string);
@@ -173,7 +176,8 @@ namespace FreeSql.ClickHouse
if (tb == null)
throw new Exception(CoreStrings.S_Type_IsNot_Migrable(obj.tableSchema.Type.FullName));
if (tb.Columns.Any() == false)
- throw new Exception(CoreStrings.S_Type_IsNot_Migrable_0Attributes(obj.tableSchema.Type.FullName));
+ throw new Exception(
+ CoreStrings.S_Type_IsNot_Migrable_0Attributes(obj.tableSchema.Type.FullName));
var tbname = _commonUtils.SplitTableName(tb.DbName);
if (tbname?.Length == 1)
tbname = new[] { database, tbname[0] };
@@ -258,7 +262,8 @@ namespace FreeSql.ClickHouse
if (tb.Primarys.Any())
{
- var primaryKeys = string.Join(",", tb.Primarys.Select(p => _commonUtils.QuoteSqlName(p.Attribute.Name)));
+ var primaryKeys = string.Join(",",
+ tb.Primarys.Select(p => _commonUtils.QuoteSqlName(p.Attribute.Name)));
sb.Append(" \r\n PRIMARY KEY ");
sb.Append($"( {primaryKeys} ) ");
}
@@ -268,14 +273,32 @@ namespace FreeSql.ClickHouse
if (tb.Primarys.Any())
{
- var primaryKeys = string.Join(",", tb.Primarys.Select(p => _commonUtils.QuoteSqlName(p.Attribute.Name)));
+ var primaryKeys = string.Join(",",
+ tb.Primarys.Select(p => _commonUtils.QuoteSqlName(p.Attribute.Name)));
sb.Append(" \r\nORDER BY ");
sb.Append($"( {primaryKeys} ) ");
}
+ //查找属性是否标记了分区特性
+ var partitionColumnInfos = tb.Properties.Where(
+ c => c.Value.GetCustomAttribute() != null).ToList();
+
+ if (partitionColumnInfos != null && partitionColumnInfos.Any())
+ {
+ var partitionProperty = partitionColumnInfos.First();
+
+ var partitionColumnInfo = tb.Columns.FirstOrDefault(pair =>
+ pair.Value.CsName == partitionProperty.Value.Name);
+ var partitionName = _commonUtils.QuoteSqlName(partitionColumnInfo.Value.Attribute.Name);
+ var partitionAttribute = partitionProperty.Value
+ .GetCustomAttribute();
+ sb.Append($" \r\nPARTITION BY {string.Format(partitionAttribute.Format, partitionName)}");
+ }
+
+
//if (string.IsNullOrEmpty(tb.Comment) == false)
// sb.Append(" Comment=").Append(_commonUtils.FormatSql("{0}", tb.Comment));
- sb.Append(" SETTINGS index_granularity = 8192;\r\n");
+ sb.Append(" \r\nSETTINGS index_granularity = 8192;\r\n");
continue;
}
@@ -477,7 +500,8 @@ where a.database in ({0}) and a.table in ({1})", tboldname ?? tbname);
if (tb.Primarys.Any())
{
- var primaryKeys = string.Join(",", tb.Primarys.Select(p => _commonUtils.QuoteSqlName(p.Attribute.Name)));
+ var primaryKeys = string.Join(",",
+ tb.Primarys.Select(p => _commonUtils.QuoteSqlName(p.Attribute.Name)));
sb.Append(" \r\nORDER BY ( ");
sb.Append(primaryKeys);
sb.Append(" )");