diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml
index da7ace6b..bdd16ff9 100644
--- a/FreeSql.DbContext/FreeSql.DbContext.xml
+++ b/FreeSql.DbContext/FreeSql.DbContext.xml
@@ -538,5 +538,14 @@
+
+
+ 批量注入 Repository,可以参考代码自行调整
+
+
+
+
+
+
diff --git a/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickHouseTest1.cs b/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickHouseTest1.cs
index b8f068cc..28f1ca01 100644
--- a/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickHouseTest1.cs
+++ b/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickHouseTest1.cs
@@ -36,18 +36,14 @@ namespace FreeSql.Tests.MySql
public int? Points { get; set; }
}
[FreeSql.DataAnnotations.Table(Name = "ClickHouseTest")]
- public class TestClickHouse : IEnumerable
+ public class TestClickHouse
{
[FreeSql.DataAnnotations.Column(IsPrimary = true, IsIdentity = true)]
[Now]
public long Id { get; set; }
public string Name { get; set; }
- public IEnumerator GetEnumerator()
- {
- yield return Id;
- yield return Name;
- }
+ public Decimal Money { get; set; }
}
class NowAttribute: Attribute { }
@@ -231,6 +227,41 @@ namespace FreeSql.Tests.MySql
Debug.WriteLine("更新用时:" + stopwatch.ElapsedMilliseconds.ToString());
}
+ [Fact]
+ public async void TestInsertUpdateData()
+ {
+ //g.clickHouse.CodeFirst.SyncStructure();
+ Stopwatch stopwatch = new Stopwatch();
+ var fsql = g.clickHouse;
+ var repository=fsql.GetRepository();
+ await repository.DeleteAsync(o=>o.Id>0);
+ List tables = new List();
+ for (int i = 1; i < 3; i++)
+ {
+ tables.Add(new CollectDataEntity
+ {
+ Id = new Random().Next(),
+ CollectTime = DateTime.Now,
+ DataFlag = "1",
+ EquipmentCode = "11",
+ UnitStr = "111",
+ PropertyCode = "1111",
+ NumericValue=1111.1119999912500M
+ });
+ }
+
+ var insert = repository.Orm.Insert(tables);
+ insert.ExecuteAffrows();
+ var list = repository.Orm.Select().ToList();
+ //var list = repository.Insert(tables);
+ //var list = repository.Select.ToList();
+ //list.ForEach(o=>o.EquipmentCode = "666");
+ //stopwatch.Start();
+ //await repository.UpdateAsync(list);
+ //stopwatch.Stop();
+ Debug.WriteLine("更新用时:" + stopwatch.ElapsedMilliseconds.ToString());
+
+ }
}
}
diff --git a/FreeSql.Tests/FreeSql.Tests/ClickHouse/CollectDataEntity.cs b/FreeSql.Tests/FreeSql.Tests/ClickHouse/CollectDataEntity.cs
index 07abf7ff..0e8548e1 100644
--- a/FreeSql.Tests/FreeSql.Tests/ClickHouse/CollectDataEntity.cs
+++ b/FreeSql.Tests/FreeSql.Tests/ClickHouse/CollectDataEntity.cs
@@ -113,10 +113,11 @@ namespace XY.Model.Business
/// 数值或状态是否变更
///
public bool IsValueOrStateChanged { get; set; }
-
+
///
/// 采集数值
///
+ [Column(StringLength = 18)]
public decimal? NumericValue { get; set; }
///
diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml
index 06ac1dc3..9c849a52 100644
--- a/FreeSql/FreeSql.xml
+++ b/FreeSql/FreeSql.xml
@@ -3172,6 +3172,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>
+
+
+
+
+
+
+
+
可自定义解析表达式
@@ -4045,6 +4216,12 @@
超时
+
+
+ 获取资源
+
+
+
使用完毕后,归还资源
@@ -4115,6 +4292,12 @@
资源对象
+
+
+ 从对象池获取对象成功的时候触发,通过该方法统计或初始化对象
+
+ 资源对象
+
归还对象给对象池的时候触发
diff --git a/Providers/FreeSql.Provider.ClickHouse/ClickHouseCodeFirst.cs b/Providers/FreeSql.Provider.ClickHouse/ClickHouseCodeFirst.cs
index da491174..8f006685 100644
--- a/Providers/FreeSql.Provider.ClickHouse/ClickHouseCodeFirst.cs
+++ b/Providers/FreeSql.Provider.ClickHouse/ClickHouseCodeFirst.cs
@@ -35,6 +35,7 @@ namespace FreeSql.ClickHouse
{ typeof(double).FullName, CsToDb.New(DbType.Double, "Float64", "Float64", false, false, 0) },{ typeof(double?).FullName, CsToDb.New(DbType.Double, "Float64", "Nullable(Float64)", false, true, null) },
{ typeof(float).FullName, CsToDb.New(DbType.Single, "Float32","Float32", false, false, 0) },{ typeof(float?).FullName, CsToDb.New(DbType.Single, "Float32","Nullable(Float32)", false, true, null) },
+ { typeof(decimal).FullName, CsToDb.New(DbType.Decimal, "Decimal128(19)","Decimal128(19)", false, false, 0) },{ typeof(decimal?).FullName, CsToDb.New(DbType.Decimal, "Nullable(Decimal128(19))","Nullable(Decimal128(19))", false, true, null) },
{ typeof(DateTime).FullName, CsToDb.New(DbType.DateTime, "DateTime('Asia/Shanghai')", "DateTime('Asia/Shanghai')", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, CsToDb.New(DbType.DateTime, "DateTime('Asia/Shanghai')", "Nullable(DateTime('Asia/Shanghai'))", false, true, null) },
@@ -114,13 +115,14 @@ namespace FreeSql.ClickHouse
foreach (var uk in tb.Indexes)
{
sb.Append(" \r\n ");
- sb.Append("INDEX ").Append(_commonUtils.QuoteSqlName(ReplaceIndexName(uk.Name, tbname[1]))).Append("(");
+ sb.Append("INDEX ").Append(_commonUtils.QuoteSqlName(ReplaceIndexName(uk.Name, tbname[1])));
foreach (var tbcol in uk.Columns)
{
+ sb.Append(" ");
sb.Append(_commonUtils.QuoteSqlName(tbcol.Column.Attribute.Name));
- sb.Append("TYPE set(8192) GRANULARITY 5, ");
+ sb.Append("TYPE set(8192) GRANULARITY 5, ");
}
- sb.Remove(sb.Length - 2, 2).Append("),");
+ sb.Remove(sb.Length - 2, 2);
}
sb.Remove(sb.Length - 1, 1);
sb.Append("\r\n) ");
diff --git a/Providers/FreeSql.Provider.ClickHouse/ClickHouseDbFirst.cs b/Providers/FreeSql.Provider.ClickHouse/ClickHouseDbFirst.cs
index c0c6da19..92e57371 100644
--- a/Providers/FreeSql.Provider.ClickHouse/ClickHouseDbFirst.cs
+++ b/Providers/FreeSql.Provider.ClickHouse/ClickHouseDbFirst.cs
@@ -67,6 +67,9 @@ namespace FreeSql.ClickHouse
case "Float32":
case "float":
case "nullable(float32)": return DbType.Single;
+ case "decimal":
+ case "decimal128":
+ case "nullable(decimal128)": return DbType.Decimal;
case "date":
case "nullable(date)": return DbType.Date;
case "datetime":
@@ -103,6 +106,7 @@ namespace FreeSql.ClickHouse
{ (int)DbType.Double, new DbToCs("(double?)", "double.Parse({0})", "{0}.ToString()", "double?", typeof(double), typeof(double?), "{0}.Value", "GetDouble") },
{ (int)DbType.Single, new DbToCs("(float?)", "float.Parse({0})", "{0}.ToString()", "float?", typeof(float), typeof(float?), "{0}.Value", "GetFloat") },
+ { (int)DbType.Decimal, new DbToCs("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") },
{ (int)DbType.Date, new DbToCs("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
{ (int)DbType.Date, new DbToCs("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
diff --git a/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs b/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs
index ba173483..dc5ab194 100644
--- a/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs
+++ b/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs
@@ -35,7 +35,7 @@ namespace FreeSql.ClickHouse
case "System.Byte": return $"cast({getExp(operandExp)} as Int8)";
case "System.Char": return $"substr(cast({getExp(operandExp)} as String), 1, 1)";
case "System.DateTime": return $"cast({getExp(operandExp)} as DateTime)";
- case "System.Decimal": return $"cast({getExp(operandExp)} as Float64)";
+ case "System.Decimal": return $"cast({getExp(operandExp)} as Decimal128(19))";
case "System.Double": return $"cast({getExp(operandExp)} as Float64)";
case "System.Int16": return $"cast({getExp(operandExp)} as Int16)";
case "System.Int32": return $"cast({getExp(operandExp)} as Int32)";
@@ -63,7 +63,7 @@ namespace FreeSql.ClickHouse
case "System.Byte": return $"cast({getExp(callExp.Arguments[0])} as Int8)";
case "System.Char": return $"substr(cast({getExp(callExp.Arguments[0])} as String), 1, 1)";
case "System.DateTime": return $"cast({getExp(callExp.Arguments[0])} as DateTime)";
- case "System.Decimal": return $"cast({getExp(callExp.Arguments[0])} as Float64)";
+ case "System.Decimal": return $"cast({getExp(callExp.Arguments[0])} as Decimal128(19))";
case "System.Double": return $"cast({getExp(callExp.Arguments[0])} as Float64)";
case "System.Int16": return $"cast({getExp(callExp.Arguments[0])} as Int16)";
case "System.Int32": return $"cast({getExp(callExp.Arguments[0])} as Int32)";
@@ -556,7 +556,7 @@ namespace FreeSql.ClickHouse
case "ToByte": return $"cast({getExp(exp.Arguments[0])} as Int8)";
case "ToChar": return $"substr(cast({getExp(exp.Arguments[0])} as String), 1, 1)";
case "ToDateTime": return $"cast({getExp(exp.Arguments[0])} as DateTime)";
- case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as Float64)";
+ case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as Decimal128(19))";
case "ToDouble": return $"cast({getExp(exp.Arguments[0])} as Float64)";
case "ToInt16":
case "ToInt32":
diff --git a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseInsert.cs b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseInsert.cs
index 5666ca8c..ce6b2f9c 100644
--- a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseInsert.cs
+++ b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseInsert.cs
@@ -55,7 +55,6 @@ namespace FreeSql.ClickHouse.Curd
{
try
{
- Debug.WriteLine($"开始执行时间:{DateTime.Now}");
before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, null, _params);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
using var bulkCopyInterface = new ClickHouseBulkCopy(_orm.Ado.MasterPool.Get().Value as ClickHouseConnection)
@@ -170,9 +169,9 @@ namespace FreeSql.ClickHouse.Curd
#if net40
#else
- public override Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(_batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, _batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, cancellationToken);
- public override Task ExecuteIdentityAsync(CancellationToken cancellationToken = default) => base.SplitExecuteIdentityAsync(_batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, _batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, cancellationToken);
- public override Task> ExecuteInsertedAsync(CancellationToken cancellationToken = default) => base.SplitExecuteInsertedAsync(_batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, _batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, cancellationToken);
+ public override Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => SplitExecuteAffrowsAsync(_batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, _batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, cancellationToken);
+ public override Task ExecuteIdentityAsync(CancellationToken cancellationToken = default) => SplitExecuteIdentityAsync(_batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, _batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, cancellationToken);
+ public override Task> ExecuteInsertedAsync(CancellationToken cancellationToken = default) => SplitExecuteInsertedAsync(_batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, _batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, cancellationToken);
async protected override Task RawExecuteIdentityAsync(CancellationToken cancellationToken = default)
{
@@ -255,7 +254,8 @@ namespace FreeSql.ClickHouse.Curd
if (ss.Length == 1)
{
_batchProgress?.Invoke(new BatchProgressStatus(_source, 1, 1));
- ret = await this.RawExecuteAffrowsAsync(cancellationToken);
+ await this.RawExecuteAffrowsAsync(cancellationToken);
+ ret = _source.Count;
ClearData();
return ret;
}
@@ -269,7 +269,8 @@ namespace FreeSql.ClickHouse.Curd
{
_source = ss[a];
_batchProgress?.Invoke(new BatchProgressStatus(_source, a + 1, ss.Length));
- ret += await this.RawExecuteAffrowsAsync(cancellationToken);
+ await this.RawExecuteAffrowsAsync(cancellationToken);
+ ret += _source.Count;
}
}
catch (Exception ex)
diff --git a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs
index 703ff6af..9e69b3c9 100644
--- a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs
+++ b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs
@@ -293,18 +293,20 @@ namespace FreeSql.ClickHouse.Curd
#if net40
#else
- public override Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000, cancellationToken);
- public override Task> ExecuteUpdatedAsync(CancellationToken cancellationToken = default) => base.SplitExecuteUpdatedAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000, cancellationToken);
+ public override Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => SplitExecuteAffrowsAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000, cancellationToken);
+ public override Task> ExecuteUpdatedAsync(CancellationToken cancellationToken = default) => SplitExecuteUpdatedAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000, cancellationToken);
protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.ClickHouse.Custom 未实现该功能 未实现该功能");
async protected override Task SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
+
{
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0;
if (ss.Length <= 1)
{
if (_source?.Any() == true) _batchProgress?.Invoke(new BatchProgressStatus(_source, 1, 1));
- ret = await this.RawExecuteAffrowsAsync(cancellationToken);
+ await this.RawExecuteAffrowsAsync(cancellationToken);
+ ret = _source.Count;
ClearData();
return ret;
}
@@ -319,7 +321,8 @@ namespace FreeSql.ClickHouse.Curd
{
_source = ss[a];
_batchProgress?.Invoke(new BatchProgressStatus(_source, a + 1, ss.Length));
- ret += await this.RawExecuteAffrowsAsync(cancellationToken);
+ await this.RawExecuteAffrowsAsync(cancellationToken);
+ ret += _source.Count;
}
}
catch (Exception ex)