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] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E5=B9=B6=E4=BF=AE=E5=A4=8DCi?= =?UTF-8?q?lckhouse=20CodeFirst=E4=B8=BB=E9=94=AE=E9=97=AE=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);