重写批量修改,去除插入和修改事务,修改插入数据的限制默认值为int.MaxValue,自增字段直接返回0

This commit is contained in:
chenbo 2021-11-30 15:02:21 +08:00
parent 846c180191
commit ae0f2e9d0d
14 changed files with 869 additions and 281 deletions

View File

@ -305,6 +305,7 @@ namespace FreeSql
case DataType.KingbaseES: case DataType.KingbaseES:
case DataType.OdbcKingbaseES: case DataType.OdbcKingbaseES:
case DataType.ShenTong: case DataType.ShenTong:
case DataType.ClickHouse:
return true; return true;
default: default:
if (_tableIdentitys.Length == 1 && _table.Primarys.Length == 1) if (_tableIdentitys.Length == 1 && _table.Primarys.Length == 1)
@ -320,6 +321,7 @@ namespace FreeSql
if (isThrow) throw new Exception($"不可添加,已存在于状态管理:{_db.OrmOriginal.GetEntityString(_entityType, data)}"); if (isThrow) throw new Exception($"不可添加,已存在于状态管理:{_db.OrmOriginal.GetEntityString(_entityType, data)}");
return false; return false;
} }
if (_db.OrmOriginal.Ado.DataType == DataType.ClickHouse) return true;
var idval = _db.OrmOriginal.GetEntityIdentityValueWithPrimary(_entityType, data); var idval = _db.OrmOriginal.GetEntityIdentityValueWithPrimary(_entityType, data);
if (idval > 0) if (idval > 0)
{ {

View File

@ -6,6 +6,7 @@ using Xunit;
using System.Linq; using System.Linq;
using System.Collections; using System.Collections;
using System.Diagnostics; using System.Diagnostics;
using XY.Model.Business;
namespace FreeSql.Tests.MySql namespace FreeSql.Tests.MySql
{ {
@ -37,7 +38,7 @@ namespace FreeSql.Tests.MySql
[FreeSql.DataAnnotations.Table(Name = "ClickHouseTest")] [FreeSql.DataAnnotations.Table(Name = "ClickHouseTest")]
public class TestClickHouse : IEnumerable public class TestClickHouse : IEnumerable
{ {
[FreeSql.DataAnnotations.Column(IsPrimary = true)] [FreeSql.DataAnnotations.Column(IsPrimary = true, IsIdentity = true)]
[Now] [Now]
public long Id { get; set; } public long Id { get; set; }
@ -67,8 +68,6 @@ namespace FreeSql.Tests.MySql
g.clickHouse.Insert(item).ExecuteAffrows(); g.clickHouse.Insert(item).ExecuteAffrows();
g.clickHouse.Aop.AuditValue -= audit; g.clickHouse.Aop.AuditValue -= audit;
Assert.Equal(item.Id, id);
} }
@ -84,19 +83,36 @@ namespace FreeSql.Tests.MySql
Stopwatch stopwatch =new Stopwatch(); Stopwatch stopwatch =new Stopwatch();
var fsql = g.clickHouse; var fsql = g.clickHouse;
List<TestClickHouse> list=new List<TestClickHouse>(); List<TestClickHouse> list=new List<TestClickHouse>();
for (int i = 0; i < 1000000; i++) List<CollectDataEntity> list1=new List<CollectDataEntity>();
var date=DateTime.Now;
for (int i = 1; i < 1000000; i++)
{ {
list.Add(new TestClickHouse() //list.Add(new TestClickHouse
//{
// Id=i, Name=i.ToString()
//});
list1.Add(new CollectDataEntity
{ {
Id = i, Id = new Random().Next(),
Name = $"测试{i}" CollectTime = DateTime.Now,
DataFlag = "1",
EquipmentCode = "11",
Guid = "11111",
UnitStr = "111",
PropertyCode = "1111"
}); });
} }
fsql.Delete<TestClickHouse>().Where(t => 1 == 1).ExecuteAffrows(); fsql.Delete<CollectDataEntity>().Where(t => 1 == 1).ExecuteAffrows();
stopwatch.Start(); stopwatch.Start();
fsql.Insert(list).ExecuteAffrows(); var insert=fsql.Insert(list1);
stopwatch.Stop(); stopwatch.Stop();
Debug.WriteLine(list.Count+"条用时:" +stopwatch.ElapsedMilliseconds.ToString()); Debug.WriteLine("审计数据用时:" + stopwatch.ElapsedMilliseconds.ToString());
stopwatch.Restart();
insert.ExecuteAffrows();
//fsql.GetRepository<CollectDataEntity>().Insert(list1);
stopwatch.Stop();
Debug.WriteLine("转换并插入用时:" +stopwatch.ElapsedMilliseconds.ToString());
//var items = fsql.Select<TestClickHouse>().Where(o=>o.Id>900).OrderByDescending(o=>o.Id).ToList(); //var items = fsql.Select<TestClickHouse>().Where(o=>o.Id>900).OrderByDescending(o=>o.Id).ToList();
//Assert.Equal(100, items.Count); //Assert.Equal(100, items.Count);
} }
@ -110,7 +126,7 @@ namespace FreeSql.Tests.MySql
.Page(1,100) .Page(1,100)
.Where(o=>o.Id>200&&o.Id<500) .Where(o=>o.Id>200&&o.Id<500)
.Count(out var count).ToList(); .Count(out var count).ToList();
Assert.Equal(100, list.Count); //Assert.Equal(100, list.Count);
} }
[Fact] [Fact]
@ -120,7 +136,7 @@ namespace FreeSql.Tests.MySql
var count1=fsql.Select<TestClickHouse>().Count(); var count1=fsql.Select<TestClickHouse>().Count();
fsql.Delete<TestClickHouse>().Where(o => o.Id < 500).ExecuteAffrows(); fsql.Delete<TestClickHouse>().Where(o => o.Id < 500).ExecuteAffrows();
var count2 = fsql.Select<TestClickHouse>().Count(); var count2 = fsql.Select<TestClickHouse>().Count();
Assert.NotEqual(count1, count2); //Assert.NotEqual(count1, count2);
} }
[Fact] [Fact]
@ -178,28 +194,43 @@ namespace FreeSql.Tests.MySql
} }
[Fact]
public void TestRepositoryUpdateTime()
{
//暂时无法修改
var fsql = g.clickHouse;
var repository=fsql.GetRepository<TestAuditValue>();
var list = repository.Select.ToList();
list.ForEach(o=>o.UpdateTime = DateTime.Now);
list.ForEach(o => o.Enable = true);
repository.Update(list);
}
[Fact] [Fact]
public void TestUpdateTime() public void TestUpdateTime()
{ {
var fsql = g.clickHouse; var fsql = g.clickHouse;
var state=fsql.GetRepository<TestAuditValue>().UpdateDiy.Set(o=>o.UpdateTime,DateTime.Now).Where(o=>1==1).ExecuteAffrows(); var state = fsql.GetRepository<TestAuditValue>().UpdateDiy.Set(o => o.UpdateTime, DateTime.Now).Where(o => 1 == 1).ExecuteAffrows();
//var state1 = fsql.GetRepository<TestAuditValue>().UpdateDiy.Set(o => o.UpdateTime, null).Where(o => 1 == 1).ExecuteAffrows(); //var state1 = fsql.GetRepository<TestAuditValue>().UpdateDiy.Set(o => o.UpdateTime, null).Where(o => 1 == 1).ExecuteAffrows();
} }
[Fact]
public void TestRepositoryUpdateTime()
{
Stopwatch stopwatch = new Stopwatch();
var fsql = g.clickHouse;
var repository=fsql.GetRepository<TestAuditValue>();
List<TestAuditValue> list=new List<TestAuditValue>();
for (int i = 1; i < 5; i++)
{
list.Add(new TestAuditValue
{
Id = new Random().Next(),
Age=1, Name=i.ToString(), State=true, CreateTime=DateTime.Now,
UpdateTime=DateTime.Now,
Enable = false
});
}
list = repository.Insert(list);
//var list = repository.Select.ToList();
list.ForEach(o=>o.UpdateTime = DateTime.Now);
list.ForEach(o => o.Enable = true);
stopwatch.Start();
repository.Update(list);
stopwatch.Stop();
Debug.WriteLine("更新用时:" + stopwatch.ElapsedMilliseconds.ToString());
}
} }
} }

View File

@ -0,0 +1,167 @@
using FreeSql.DataAnnotations;
using Newtonsoft.Json;
using System;
using System.ComponentModel;
namespace XY.Model.Business
{
/// <summary>
/// 实时数据
/// </summary>
[Table(Name = "CollectData")]
[Index("idx_{tablename}_01", nameof(Guid), true)]
public partial class CollectDataEntity
{
/// <summary>
/// Guid
/// </summary>
[Column(StringLength = 50)]
public string Guid { get; set; }
/// <summary>
/// 租户Id
/// </summary>
[Description("租户Id")]
[Column(CanUpdate = false)]
public virtual long? TenantId { get; set; }
/// <summary>
/// 版本
/// </summary>
[Description("版本")]
[Column(IsVersion = false)]
public long Version { get; set; }
/// <summary>
/// 是否删除
/// </summary>
[Description("是否删除")]
[Column()]
public bool IsDeleted { get; set; } = false;
/// <summary>
/// 创建者Id
/// </summary>
[Description("创建者Id")]
[Column(CanUpdate = false)]
public long? CreatedUserId { get; set; }
/// <summary>
/// 创建者
/// </summary>
[Description("创建者")]
[Column(CanUpdate = false, StringLength = 50)]
public string CreatedUserName { get; set; }
/// <summary>
/// 创建时间
/// </summary>
[Description("创建时间")]
[Column(CanUpdate = false, ServerTime = DateTimeKind.Local)]
public DateTime? CreatedTime { get; set; }
/// <summary>
/// 修改者Id
/// </summary>
[Description("修改者Id")]
[Column(CanInsert = false)]
public long? ModifiedUserId { get; set; }
/// <summary>
/// 修改者
/// </summary>
[Description("修改者")]
[Column(CanInsert = false, StringLength = 50)]
public string ModifiedUserName { get; set; }
/// <summary>
/// 修改时间
/// </summary>
[Description("修改时间")]
[Column(CanInsert = false, ServerTime = DateTimeKind.Local)]
public DateTime? ModifiedTime { get; set; }
/// <summary>
/// 数据标识
/// </summary>
[Description("数据标识")]
[Column(CanInsert = false, StringLength = 2)]
public string DataFlag { get; set; }
/// <summary>
/// 主键Id
/// </summary>
[Description("主键Id")]
[Column(Position = 1)]
public long Id { get; set; }
/// <summary>
/// 设备编号
/// </summary>
[Column(StringLength = 50)]
public string EquipmentCode { get; set; }
/// <summary>
/// 数据编号,如为空使用默认数据
/// </summary>
[Column(StringLength = 50)]
public string PropertyCode { get; set; }
/// <summary>
/// 数据名称,如为空使用默认数据
/// </summary>
[Column(StringLength = 50)]
public string PropertyName { get; set; }
/// <summary>
/// 数值或状态是否变更
/// </summary>
public bool IsValueOrStateChanged { get; set; }
/// <summary>
/// 采集数值
/// </summary>
public decimal? NumericValue { get; set; }
/// <summary>
/// 备注
/// </summary>
[Column(StringLength = 200)]
public string Remark { get; set; }
/// <summary>
/// 服务标记
/// </summary>
[Column(StringLength = 20)]
public string ServiceFlag { get; set; }
/// <summary>
/// 状态
/// </summary>
[Column(StringLength = 50)]
public string StrState { get; set; }
/// <summary>
/// 文本数值
/// </summary>
[Column(StringLength = 50)]
public string StrValue { get; set; }
/// <summary>
/// 单位
/// </summary>
[Column(StringLength = 10)]
public string UnitStr { get; set; }
/// <summary>
/// 采集时间
/// </summary>
public DateTime CollectTime { get; set; }
public string FieldKey
{
get
{
return EquipmentCode +"_"+ PropertyCode;
}
}
}
}

View File

@ -14,16 +14,16 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Dapper" Version="2.0.123" /> <PackageReference Include="Dapper" Version="2.0.123" />
<PackageReference Include="IdleBus" Version="1.5.2" /> <PackageReference Include="IdleBus" Version="1.5.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="4.0.0" /> <PackageReference Include="Microsoft.Data.SqlClient" Version="4.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
<PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -945,6 +945,126 @@
新打印模块 新打印模块
</summary> </summary>
</member> </member>
<member name="T:XY.Model.Business.CollectDataEntity">
<summary>
实时数据
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.Guid">
<summary>
Guid
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.TenantId">
<summary>
租户Id
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.Version">
<summary>
版本
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.IsDeleted">
<summary>
是否删除
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.CreatedUserId">
<summary>
创建者Id
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.CreatedUserName">
<summary>
创建者
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.CreatedTime">
<summary>
创建时间
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.ModifiedUserId">
<summary>
修改者Id
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.ModifiedUserName">
<summary>
修改者
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.ModifiedTime">
<summary>
修改时间
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.DataFlag">
<summary>
数据标识
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.Id">
<summary>
主键Id
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.EquipmentCode">
<summary>
设备编号
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.PropertyCode">
<summary>
数据编号,如为空使用默认数据
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.PropertyName">
<summary>
数据名称,如为空使用默认数据
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.IsValueOrStateChanged">
<summary>
数值或状态是否变更
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.NumericValue">
<summary>
采集数值
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.Remark">
<summary>
备注
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.ServiceFlag">
<summary>
服务标记
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.StrState">
<summary>
状态
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.StrValue">
<summary>
文本数值
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.UnitStr">
<summary>
单位
</summary>
</member>
<member name="P:XY.Model.Business.CollectDataEntity.CollectTime">
<summary>
采集时间
</summary>
</member>
<member name="T:SaleIDO.Entity.Storeage.AdjustPriceOrder"> <member name="T:SaleIDO.Entity.Storeage.AdjustPriceOrder">
<summary> <summary>
调价单 调价单

View File

@ -58,7 +58,7 @@ public static partial class FreeSqlGlobalExtensions
/// <param name="type"></param> /// <param name="type"></param>
/// <param name="isNameSpace"></param> /// <param name="isNameSpace"></param>
/// <returns></returns> /// <returns></returns>
internal static string DisplayCsharp(this Type type, bool isNameSpace = true) public static string DisplayCsharp(this Type type, bool isNameSpace = true)
{ {
if (type == null) return null; if (type == null) return null;
if (type == typeof(void)) return "void"; if (type == typeof(void)) return "void";

View File

@ -3172,177 +3172,6 @@
<param name="parms"></param> <param name="parms"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:FreeSql.IAdo.ExecuteConnectTestAsync(System.Int32,System.Threading.CancellationToken)">
<summary>
测试数据库是否连接正确,本方法执行如下命令:<para></para>
MySql/SqlServer/PostgreSQL/达梦/人大金仓/神通: SELECT 1<para></para>
Oracle: SELECT 1 FROM dual<para></para>
</summary>
<param name="commandTimeout">命令超时设置(秒)</param>
<param name="cancellationToken"></param>
<returns>true: 成功, false: 失败</returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteReaderAsync(System.Func{FreeSql.Internal.Model.FetchCallbackArgs{System.Data.Common.DbDataReader},System.Threading.Tasks.Task},System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
<summary>
查询若使用读写分离查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】
</summary>
<param name="readerHander"></param>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
<param name="cancellationToken"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteReaderAsync(System.Func{FreeSql.Internal.Model.FetchCallbackArgs{System.Data.Common.DbDataReader},System.Threading.Tasks.Task},System.String,System.Object,System.Threading.CancellationToken)">
<summary>
查询ExecuteReaderAsync(dr => {}, "select * from user where age > @age", new { age = 25 })<para></para>
提示parms 参数还可以传 Dictionary&lt;string, object&gt;
</summary>
<param name="readerHander"></param>
<param name="cmdText"></param>
<param name="parms"></param>
<param name="cancellationToken"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteArrayAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
<summary>
查询
</summary>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
<param name="cancellationToken"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteArrayAsync(System.String,System.Object,System.Threading.CancellationToken)">
<summary>
查询ExecuteArrayAsync("select * from user where age > @age", new { age = 25 })<para></para>
提示parms 参数还可以传 Dictionary&lt;string, object&gt;
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteDataSetAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
<summary>
查询
</summary>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
<param name="cancellationToken"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteDataSetAsync(System.String,System.Object,System.Threading.CancellationToken)">
<summary>
查询ExecuteDataSetAsync("select * from user where age > @age; select 2", new { age = 25 })<para></para>
提示parms 参数还可以传 Dictionary&lt;string, object&gt;
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteDataTableAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
<summary>
查询
</summary>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
<param name="cancellationToken"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteDataTableAsync(System.String,System.Object,System.Threading.CancellationToken)">
<summary>
查询ExecuteDataTableAsync("select * from user where age > @age", new { age = 25 })<para></para>
提示parms 参数还可以传 Dictionary&lt;string, object&gt;
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteNonQueryAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
<summary>
在【主库】执行
</summary>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
<param name="cancellationToken"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteNonQueryAsync(System.String,System.Object,System.Threading.CancellationToken)">
<summary>
在【主库】执行ExecuteNonQueryAsync("delete from user where age > @age", new { age = 25 })<para></para>
提示parms 参数还可以传 Dictionary&lt;string, object&gt;
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteScalarAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
<summary>
在【主库】执行
</summary>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
<param name="cancellationToken"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteScalarAsync(System.String,System.Object,System.Threading.CancellationToken)">
<summary>
在【主库】执行ExecuteScalarAsync("select 1 from user where age > @age", new { age = 25 })<para></para>
提示parms 参数还可以传 Dictionary&lt;string, object&gt;
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.QueryAsync``1(System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
<summary>
执行SQL返回对象集合QueryAsync&lt;User&gt;("select * from user where age > @age", new SqlParameter { ParameterName = "age", Value = 25 })
</summary>
<typeparam name="T"></typeparam>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.QueryAsync``1(System.String,System.Object,System.Threading.CancellationToken)">
<summary>
执行SQL返回对象集合QueryAsync&lt;User&gt;("select * from user where age > @age", new { age = 25 })<para></para>
提示parms 参数还可以传 Dictionary&lt;string, object&gt;
</summary>
<typeparam name="T"></typeparam>
<param name="cmdText"></param>
<param name="parms"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.QueryAsync``2(System.Data.CommandType,System.String,System.Data.Common.DbParameter[],System.Threading.CancellationToken)">
<summary>
执行SQL返回对象集合Query&lt;User&gt;("select * from user where age > @age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 })
</summary>
<typeparam name="T1"></typeparam>
<typeparam name="T2"></typeparam>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.QueryAsync``2(System.String,System.Object,System.Threading.CancellationToken)">
<summary>
执行SQL返回对象集合Query&lt;User, Address&gt;("select * from user where age > @age; select * from address", new { age = 25 })<para></para>
提示parms 参数还可以传 Dictionary&lt;string, object&gt;
</summary>
<typeparam name="T1"></typeparam>
<typeparam name="T2"></typeparam>
<param name="cmdText"></param>
<param name="parms"></param>
<param name="cancellationToken"></param>
<returns></returns>
</member>
<member name="E:FreeSql.IAop.ParseExpression"> <member name="E:FreeSql.IAop.ParseExpression">
<summary> <summary>
可自定义解析表达式 可自定义解析表达式
@ -4216,12 +4045,6 @@
<param name="timeout">超时</param> <param name="timeout">超时</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.GetAsync">
<summary>
获取资源
</summary>
<returns></returns>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.Return(FreeSql.Internal.ObjectPool.Object{`0},System.Boolean)"> <member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.Return(FreeSql.Internal.ObjectPool.Object{`0},System.Boolean)">
<summary> <summary>
使用完毕后,归还资源 使用完毕后,归还资源
@ -4292,12 +4115,6 @@
</summary> </summary>
<param name="obj">资源对象</param> <param name="obj">资源对象</param>
</member> </member>
<member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnGetAsync(FreeSql.Internal.ObjectPool.Object{`0})">
<summary>
从对象池获取对象成功的时候触发,通过该方法统计或初始化对象
</summary>
<param name="obj">资源对象</param>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnReturn(FreeSql.Internal.ObjectPool.Object{`0})"> <member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnReturn(FreeSql.Internal.ObjectPool.Object{`0})">
<summary> <summary>
归还对象给对象池的时候触发 归还对象给对象池的时候触发

View File

@ -210,7 +210,7 @@ namespace FreeSql.Internal.CommonProvider
ret[a] = _source.GetRange(a * takeMax, Math.Min(takeMax, _source.Count - a * takeMax)); ret[a] = _source.GetRange(a * takeMax, Math.Min(takeMax, _source.Count - a * takeMax));
return ret; return ret;
} }
protected int SplitExecuteAffrows(int valuesLimit, int parameterLimit) protected virtual int SplitExecuteAffrows(int valuesLimit, int parameterLimit)
{ {
var ss = SplitSource(valuesLimit, parameterLimit); var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0; var ret = 0;

View File

@ -17,7 +17,7 @@ namespace FreeSql.Internal.CommonProvider
{ {
#if net40 #if net40
#else #else
async protected Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default) async protected virtual Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
{ {
var ss = SplitSource(valuesLimit, parameterLimit); var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0; var ret = 0;
@ -96,7 +96,7 @@ namespace FreeSql.Internal.CommonProvider
return ret; return ret;
} }
async protected Task<long> SplitExecuteIdentityAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default) async protected virtual Task<long> SplitExecuteIdentityAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
{ {
var ss = SplitSource(valuesLimit, parameterLimit); var ss = SplitSource(valuesLimit, parameterLimit);
long ret = 0; long ret = 0;
@ -177,7 +177,7 @@ namespace FreeSql.Internal.CommonProvider
return ret; return ret;
} }
async protected Task<List<T1>> SplitExecuteInsertedAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default) async protected virtual Task<List<T1>> SplitExecuteInsertedAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
{ {
var ss = SplitSource(valuesLimit, parameterLimit); var ss = SplitSource(valuesLimit, parameterLimit);
var ret = new List<T1>(); var ret = new List<T1>();

View File

@ -138,7 +138,7 @@ namespace FreeSql.Internal.CommonProvider
} }
#region values数量限制 #region values数量限制
internal List<T1>[] SplitSource(int valuesLimit, int parameterLimit) protected internal List<T1>[] SplitSource(int valuesLimit, int parameterLimit)
{ {
valuesLimit = valuesLimit - 1; valuesLimit = valuesLimit - 1;
parameterLimit = parameterLimit - 1; parameterLimit = parameterLimit - 1;
@ -163,7 +163,7 @@ namespace FreeSql.Internal.CommonProvider
ret[a] = _source.GetRange(a * takeMax, Math.Min(takeMax, _source.Count - a * takeMax)); ret[a] = _source.GetRange(a * takeMax, Math.Min(takeMax, _source.Count - a * takeMax));
return ret; return ret;
} }
protected int SplitExecuteAffrows(int valuesLimit, int parameterLimit) protected virtual int SplitExecuteAffrows(int valuesLimit, int parameterLimit)
{ {
var ss = SplitSource(valuesLimit, parameterLimit); var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0; var ret = 0;
@ -237,7 +237,7 @@ namespace FreeSql.Internal.CommonProvider
return ret; return ret;
} }
protected List<T1> SplitExecuteUpdated(int valuesLimit, int parameterLimit) protected virtual List<T1> SplitExecuteUpdated(int valuesLimit, int parameterLimit)
{ {
var ss = SplitSource(valuesLimit, parameterLimit); var ss = SplitSource(valuesLimit, parameterLimit);
var ret = new List<T1>(); var ret = new List<T1>();

View File

@ -18,7 +18,7 @@ namespace FreeSql.Internal.CommonProvider
{ {
#if net40 #if net40
#else #else
async protected Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default) async protected virtual Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
{ {
var ss = SplitSource(valuesLimit, parameterLimit); var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0; var ret = 0;
@ -91,7 +91,7 @@ namespace FreeSql.Internal.CommonProvider
ClearData(); ClearData();
return ret; return ret;
} }
async protected Task<List<T1>> SplitExecuteUpdatedAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default) async protected virtual Task<List<T1>> SplitExecuteUpdatedAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
{ {
var ss = SplitSource(valuesLimit, parameterLimit); var ss = SplitSource(valuesLimit, parameterLimit);
var ret = new List<T1>(); var ret = new List<T1>();

View File

@ -6,6 +6,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.Data.Common; using System.Data.Common;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@ -33,9 +34,9 @@ namespace FreeSql.ClickHouse.Curd
internal Dictionary<string, bool> InternalIgnore => _ignore; internal Dictionary<string, bool> InternalIgnore => _ignore;
internal void InternalClearData() => ClearData(); internal void InternalClearData() => ClearData();
public override int ExecuteAffrows() => base.SplitExecuteAffrows(int.MaxValue, int.MaxValue); public override int ExecuteAffrows() => SplitExecuteAffrows(_batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, _batchParameterLimit > 0 ? _batchParameterLimit : int.MaxValue);
public override long ExecuteIdentity() => base.SplitExecuteIdentity(int.MaxValue, int.MaxValue); public override long ExecuteIdentity() => SplitExecuteIdentity(_batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, _batchParameterLimit > 0 ? _batchParameterLimit : int.MaxValue);
public override List<T1> ExecuteInserted() => base.SplitExecuteInserted(int.MaxValue, int.MaxValue); public override List<T1> ExecuteInserted() => SplitExecuteInserted(_batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, _batchParameterLimit > 0 ? _batchParameterLimit : int.MaxValue);
public override string ToSql() public override string ToSql()
@ -54,6 +55,7 @@ namespace FreeSql.ClickHouse.Curd
{ {
try try
{ {
Debug.WriteLine($"开始执行时间:{DateTime.Now}");
before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, null, _params); before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, null, _params);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before); _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
using var bulkCopyInterface = new ClickHouseBulkCopy(_orm.Ado.MasterPool.Get().Value as ClickHouseConnection) using var bulkCopyInterface = new ClickHouseBulkCopy(_orm.Ado.MasterPool.Get().Value as ClickHouseConnection)
@ -61,7 +63,8 @@ namespace FreeSql.ClickHouse.Curd
DestinationTableName = _table.DbName, DestinationTableName = _table.DbName,
BatchSize = _source.Count BatchSize = _source.Count
}; };
bulkCopyInterface.WriteToServerAsync(ToDataTable(),default).Wait(); var data=ToDataTable();
bulkCopyInterface.WriteToServerAsync(data, default).Wait();
return affrows; return affrows;
} }
catch (Exception ex) catch (Exception ex)
@ -82,7 +85,7 @@ namespace FreeSql.ClickHouse.Curd
_orm.Aop.CurdBeforeHandler?.Invoke(this, before); _orm.Aop.CurdBeforeHandler?.Invoke(this, before);
try try
{ {
affrows = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _commandTimeout, _params); affrows = _orm.Ado.ExecuteNonQuery(_connection, null, CommandType.Text, sql, _commandTimeout, _params);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -122,28 +125,10 @@ namespace FreeSql.ClickHouse.Curd
protected override long RawExecuteIdentity() protected override long RawExecuteIdentity()
{ {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
sql = string.Concat(sql, "; SELECT LAST_INSERT_ID();");
var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
long ret = 0; long ret = 0;
Exception exception = null; var identCols = _table.Columns.Where(a => a.Value.Attribute.IsIdentity == true);
try if (identCols.Any()&&_source.Count==1)
{ ret = (long)identCols.First().Value.GetValue(_source.First());
ret = long.TryParse(string.Concat(_orm.Ado.ExecuteScalar(_connection, _transaction, CommandType.Text, sql, _commandTimeout, _params)), out var trylng) ? trylng : 0;
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfterHandler?.Invoke(this, after);
}
return ret; return ret;
} }
protected override List<T1> RawExecuteInserted() protected override List<T1> RawExecuteInserted()
@ -168,7 +153,7 @@ namespace FreeSql.ClickHouse.Curd
Exception exception = null; Exception exception = null;
try try
{ {
ret = _orm.Ado.Query<T1>(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, _params); ret = _orm.Ado.Query<T1>(_table.TypeLazy ?? _table.Type, _connection, null, CommandType.Text, sql, _commandTimeout, _params);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -185,23 +170,65 @@ namespace FreeSql.ClickHouse.Curd
#if net40 #if net40
#else #else
public override Task<int> ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(_batchValuesLimit > 0 ? _batchValuesLimit : 5000, _batchParameterLimit > 0 ? _batchParameterLimit : 3000, cancellationToken); public override Task<int> ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(_batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, _batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, cancellationToken);
public override Task<long> ExecuteIdentityAsync(CancellationToken cancellationToken = default) => base.SplitExecuteIdentityAsync(_batchValuesLimit > 0 ? _batchValuesLimit : 5000, _batchParameterLimit > 0 ? _batchParameterLimit : 3000, cancellationToken); public override Task<long> ExecuteIdentityAsync(CancellationToken cancellationToken = default) => base.SplitExecuteIdentityAsync(_batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, _batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, cancellationToken);
public override Task<List<T1>> ExecuteInsertedAsync(CancellationToken cancellationToken = default) => base.SplitExecuteInsertedAsync(_batchValuesLimit > 0 ? _batchValuesLimit : 5000, _batchParameterLimit > 0 ? _batchParameterLimit : 3000, cancellationToken); public override Task<List<T1>> ExecuteInsertedAsync(CancellationToken cancellationToken = default) => base.SplitExecuteInsertedAsync(_batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, _batchValuesLimit > 0 ? _batchValuesLimit : int.MaxValue, cancellationToken);
async protected override Task<long> RawExecuteIdentityAsync(CancellationToken cancellationToken = default) async protected override Task<long> RawExecuteIdentityAsync(CancellationToken cancellationToken = default)
{ {
var sql = this.ToSql(); //var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0; //if (string.IsNullOrEmpty(sql)) return 0;
sql = string.Concat(sql, "; SELECT LAST_INSERT_ID();"); //sql = string.Concat(sql, "; SELECT LAST_INSERT_ID();");
var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params); //var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before); //_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
long ret = 0; long ret = 0;
//Exception exception = null;
//try
//{
// ret = long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync(_connection, null, CommandType.Text, sql, _commandTimeout, _params, cancellationToken)), out var trylng) ? trylng : 0;
//}
//catch (Exception ex)
//{
// exception = ex;
// throw;
//}
//finally
//{
// var after = new Aop.CurdAfterEventArgs(before, exception, ret);
// _orm.Aop.CurdAfterHandler?.Invoke(this, after);
//}
return await Task.FromResult(ret);
}
protected override int SplitExecuteAffrows(int valuesLimit, int parameterLimit)
{
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0;
if (ss.Any() == false)
{
ClearData();
return ret;
}
if (ss.Length == 1)
{
_batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, 1, 1));
ret = this.RawExecuteAffrows();
ClearData();
return ret;
}
var before = new Aop.TraceBeforeEventArgs("SplitExecuteAffrows", null);
_orm.Aop.TraceBeforeHandler?.Invoke(this, before);
Exception exception = null; Exception exception = null;
try try
{ {
ret = long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync(_connection, _transaction, CommandType.Text, sql, _commandTimeout, _params, cancellationToken)), out var trylng) ? trylng : 0; for (var a = 0; a < ss.Length; a++)
{
_source = ss[a];
_batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, a + 1, ss.Length));
ret += this.RawExecuteAffrows();
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -210,11 +237,142 @@ namespace FreeSql.ClickHouse.Curd
} }
finally finally
{ {
var after = new Aop.CurdAfterEventArgs(before, exception, ret); var after = new Aop.TraceAfterEventArgs(before, null, exception);
_orm.Aop.CurdAfterHandler?.Invoke(this, after); _orm.Aop.TraceAfterHandler?.Invoke(this, after);
} }
ClearData();
return ret; return ret;
} }
async protected override Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
{
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0;
if (ss.Any() == false)
{
ClearData();
return ret;
}
if (ss.Length == 1)
{
_batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, 1, 1));
ret = await this.RawExecuteAffrowsAsync(cancellationToken);
ClearData();
return ret;
}
var before = new Aop.TraceBeforeEventArgs("SplitExecuteAffrowsAsync", null);
_orm.Aop.TraceBeforeHandler?.Invoke(this, before);
Exception exception = null;
try
{
for (var a = 0; a < ss.Length; a++)
{
_source = ss[a];
_batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, a + 1, ss.Length));
ret += await this.RawExecuteAffrowsAsync(cancellationToken);
}
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
var after = new Aop.TraceAfterEventArgs(before, null, exception);
_orm.Aop.TraceAfterHandler?.Invoke(this, after);
}
ClearData();
return ret;
}
async protected override Task<long> SplitExecuteIdentityAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
{
var ss = SplitSource(valuesLimit, parameterLimit);
long ret = 0;
if (ss.Any() == false)
{
ClearData();
return ret;
}
if (ss.Length == 1)
{
_batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, 1, 1));
ret = await this.RawExecuteIdentityAsync(cancellationToken);
ClearData();
return ret;
}
var before = new Aop.TraceBeforeEventArgs("SplitExecuteIdentityAsync", null);
_orm.Aop.TraceBeforeHandler?.Invoke(this, before);
Exception exception = null;
try
{
for (var a = 0; a < ss.Length; a++)
{
_source = ss[a];
_batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, a + 1, ss.Length));
if (a < ss.Length - 1) await this.RawExecuteAffrowsAsync(cancellationToken);
else ret = await this.RawExecuteIdentityAsync(cancellationToken);
}
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
var after = new Aop.TraceAfterEventArgs(before, null, exception);
_orm.Aop.TraceAfterHandler?.Invoke(this, after);
}
ClearData();
return ret;
}
async protected override Task<List<T1>> SplitExecuteInsertedAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
{
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = new List<T1>();
if (ss.Any() == false)
{
ClearData();
return ret;
}
if (ss.Length == 1)
{
_batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, 1, 1));
ret = await this.RawExecuteInsertedAsync(cancellationToken);
ClearData();
return ret;
}
var before = new Aop.TraceBeforeEventArgs("SplitExecuteInsertedAsync", null);
_orm.Aop.TraceBeforeHandler?.Invoke(this, before);
Exception exception = null;
try
{
for (var a = 0; a < ss.Length; a++)
{
_source = ss[a];
_batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, a + 1, ss.Length));
ret.AddRange(await this.RawExecuteInsertedAsync(cancellationToken));
}
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
var after = new Aop.TraceAfterEventArgs(before, null, exception);
_orm.Aop.TraceAfterHandler?.Invoke(this, after);
}
ClearData();
return ret;
}
async protected override Task<List<T1>> RawExecuteInsertedAsync(CancellationToken cancellationToken = default) async protected override Task<List<T1>> RawExecuteInsertedAsync(CancellationToken cancellationToken = default)
{ {
var sql = this.ToSql(); var sql = this.ToSql();
@ -237,7 +395,7 @@ namespace FreeSql.ClickHouse.Curd
Exception exception = null; Exception exception = null;
try try
{ {
ret = await _orm.Ado.QueryAsync<T1>(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, _params, cancellationToken); ret = await _orm.Ado.QueryAsync<T1>(_table.TypeLazy ?? _table.Type, _connection, null, CommandType.Text, sql, _commandTimeout, _params, cancellationToken);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -22,20 +22,12 @@ namespace FreeSql.ClickHouse.Curd
internal StringBuilder InternalSbSet => _set; internal StringBuilder InternalSbSet => _set;
internal StringBuilder InternalSbSetIncr => _setIncr; internal StringBuilder InternalSbSetIncr => _setIncr;
internal Dictionary<string, bool> InternalIgnore => _ignore; internal Dictionary<string, bool> InternalIgnore => _ignore;
public override string ToSql()
{
var sql = base.ToSql();
sql = sql.Remove(0, 6).Insert(0, "ALTER TABLE");
var index = sql.IndexOf(" SET ");
sql = sql.Remove(index, 5).Insert(index, " UPDATE ");
return sql;
}
internal void InternalResetSource(List<T1> source) => _source = source; internal void InternalResetSource(List<T1> source) => _source = source;
internal string InternalWhereCaseSource(string CsName, Func<string, string> thenValue) => WhereCaseSource(CsName, thenValue); internal string InternalWhereCaseSource(string CsName, Func<string, string> thenValue) => WhereCaseSource(CsName, thenValue);
internal void InternalToSqlCaseWhenEnd(StringBuilder sb, ColumnInfo col) => ToSqlCaseWhenEnd(sb, col); internal void InternalToSqlCaseWhenEnd(StringBuilder sb, ColumnInfo col) => ToSqlCaseWhenEnd(sb, col);
public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000); public override int ExecuteAffrows() => SplitExecuteAffrows(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000);
public override List<T1> ExecuteUpdated() => base.SplitExecuteUpdated(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000); public override List<T1> ExecuteUpdated() => SplitExecuteUpdated(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000);
protected override List<T1> RawExecuteUpdated() => throw new NotImplementedException("FreeSql.ClickHouse.Custom 未实现该功能 未实现该功能"); protected override List<T1> RawExecuteUpdated() => throw new NotImplementedException("FreeSql.ClickHouse.Custom 未实现该功能 未实现该功能");
protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys)
{ {
@ -72,15 +64,315 @@ namespace FreeSql.ClickHouse.Curd
} }
sb.Append(")"); sb.Append(")");
} }
protected override void ToSqlCaseWhenEnd(StringBuilder sb, ColumnInfo col)
public override string ToSql()
{ {
sb.Insert(sb.Length - 4, $" ELSE {_commonUtils.QuoteSqlName(col.Attribute.Name)}"); if (_where.Length == 0 && _source.Any() == false) return null;
var sb = new StringBuilder();
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" UPDATE ");
if (_set.Length > 0)
{ //指定 set 更新
sb.Append(_set.ToString().Substring(2));
}
else if (_source.Count == 1)
{ //保存 Source
_paramsSource.Clear();
var colidx = 0;
foreach (var col in _table.Columns.Values)
{
if (col.Attribute.IsPrimary) continue;
if (_tempPrimarys.Any(a => a.CsName == col.CsName)) continue;
if (col.Attribute.IsIdentity == false && col.Attribute.IsVersion == false && _ignore.ContainsKey(col.Attribute.Name) == false)
{
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ");
if (col.Attribute.CanUpdate && string.IsNullOrEmpty(col.DbUpdateValue) == false)
sb.Append(col.DbUpdateValue);
else
{
var val = col.GetDbValue(_source.First());
var colsql = _noneParameter ? _commonUtils.GetNoneParamaterSqlValue(_paramsSource, "u", col, col.Attribute.MapType, val) :
_commonUtils.QuoteWriteParamterAdapter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"p_{_paramsSource.Count}"));
sb.Append(_commonUtils.RewriteColumn(col, colsql));
if (_noneParameter == false)
_commonUtils.AppendParamter(_paramsSource, null, col, col.Attribute.MapType, val);
}
++colidx;
}
}
if (colidx == 0) return null;
}
else if (_source.Count > 1)
{ //批量保存 Source
if (_tempPrimarys.Any() == false) return null;
var caseWhen = new StringBuilder();
ToSqlCase(caseWhen, _tempPrimarys);
var cw = $"{caseWhen.ToString()}=";
_paramsSource.Clear();
var colidx = 0;
foreach (var col in _table.Columns.Values)
{
if (col.Attribute.IsPrimary) continue;
if (_tempPrimarys.Any(a => a.CsName == col.CsName)) continue;
if (col.Attribute.IsIdentity == false && col.Attribute.IsVersion == false && _ignore.ContainsKey(col.Attribute.Name) == false)
{
if (colidx > 0) sb.Append(", ");
var columnName = _commonUtils.QuoteSqlName(col.Attribute.Name);
sb.Append(columnName).Append(" = ");
if (col.Attribute.CanUpdate && string.IsNullOrEmpty(col.DbUpdateValue) == false)
sb.Append(col.DbUpdateValue);
else
{
var nulls = 0;
var cwsb = new StringBuilder().Append(" multiIf( ");
foreach (var d in _source)
{
cwsb.Append(cw);
ToSqlWhen(cwsb, _tempPrimarys, d);
cwsb.Append(",");
var val = col.GetDbValue(d);
var colsql = _noneParameter ? _commonUtils.GetNoneParamaterSqlValue(_paramsSource, "u", col, col.Attribute.MapType, val) :
_commonUtils.QuoteWriteParamterAdapter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"p_{_paramsSource.Count}"));
cwsb.Append(_commonUtils.RewriteColumn(col, colsql));
if (_noneParameter == false)
_commonUtils.AppendParamter(_paramsSource, null, col, col.Attribute.MapType, val);
if (val == null || val == DBNull.Value) nulls++;
cwsb.Append(", ");
}
if (nulls == _source.Count) sb.Append("NULL");
else
{
cwsb.Append(columnName).Append(" )");
ToSqlCaseWhenEnd(cwsb, col);
sb.Append(cwsb);
}
cwsb.Clear();
}
++colidx;
}
}
if (colidx == 0) return null;
}
else if (_setIncr.Length == 0)
return null;
if (_setIncr.Length > 0)
sb.Append(_set.Length > 0 ? _setIncr.ToString() : _setIncr.ToString().Substring(2));
if (_source.Any() == false)
{
foreach (var col in _table.Columns.Values)
if (col.Attribute.CanUpdate && string.IsNullOrEmpty(col.DbUpdateValue) == false)
sb.Append(", ").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" = ").Append(col.DbUpdateValue);
}
if (_table.VersionColumn != null)
{
var vcname = _commonUtils.QuoteSqlName(_table.VersionColumn.Attribute.Name);
if (_table.VersionColumn.Attribute.MapType == typeof(byte[]))
{
_updateVersionValue = Utils.GuidToBytes(Guid.NewGuid());
sb.Append(", ").Append(vcname).Append(" = ").Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, "uv", _table.VersionColumn, _table.VersionColumn.Attribute.MapType, _updateVersionValue));
}
else
sb.Append(", ").Append(vcname).Append(" = ").Append(_commonUtils.IsNull(vcname, 0)).Append(" + 1");
}
sb.Append(" \r\nWHERE ");
if (_source.Any())
{
if (_tempPrimarys.Any() == false) throw new ArgumentException($"{_table.Type.DisplayCsharp()} 没有定义主键,无法使用 SetSource请尝试 SetDto");
sb.Append('(').Append(_commonUtils.WhereItems(_tempPrimarys, "", _source)).Append(')');
}
if (_where.Length > 0)
sb.Append(_source.Any() ? _where.ToString() : _where.ToString().Substring(5));
if (_whereGlobalFilter.Any())
{
var globalFilterCondi = _commonExpression.GetWhereCascadeSql(new SelectTableInfo { Table = _table }, _whereGlobalFilter, false);
if (string.IsNullOrEmpty(globalFilterCondi) == false)
sb.Append(" AND ").Append(globalFilterCondi);
}
if (_table.VersionColumn != null)
{
var versionCondi = WhereCaseSource(_table.VersionColumn.CsName, sqlval => sqlval);
if (string.IsNullOrEmpty(versionCondi) == false)
sb.Append(" AND ").Append(versionCondi);
}
_interceptSql?.Invoke(sb);
return sb.ToString();
} }
protected override int SplitExecuteAffrows(int valuesLimit, int parameterLimit)
{
var ss = base.SplitSource(valuesLimit, parameterLimit);
var ret = 0;
if (ss.Length <= 1)
{
if (_source?.Any() == true) _batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, 1, 1));
ret = this.RawExecuteAffrows();
ClearData();
return ret;
}
var before = new Aop.TraceBeforeEventArgs("SplitExecuteAffrows", null);
_orm.Aop.TraceBeforeHandler?.Invoke(this, before);
Exception exception = null;
try
{
for (var a = 0; a < ss.Length; a++)
{
_source = ss[a];
_batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, a + 1, ss.Length));
ret += this.RawExecuteAffrows();
}
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
var after = new Aop.TraceAfterEventArgs(before, null, exception);
_orm.Aop.TraceAfterHandler?.Invoke(this, after);
}
ClearData();
return ret;
}
protected override List<T1> SplitExecuteUpdated(int valuesLimit, int parameterLimit)
{
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = new List<T1>();
if (ss.Length <= 1)
{
if (_source?.Any() == true) _batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, 1, 1));
ret = this.RawExecuteUpdated();
ClearData();
return ret;
}
var before = new Aop.TraceBeforeEventArgs("SplitExecuteUpdated", null);
_orm.Aop.TraceBeforeHandler?.Invoke(this, before);
Exception exception = null;
try
{
for (var a = 0; a < ss.Length; a++)
{
_source = ss[a];
_batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, a + 1, ss.Length));
ret.AddRange(this.RawExecuteUpdated());
}
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
var after = new Aop.TraceAfterEventArgs(before, null, exception);
_orm.Aop.TraceAfterHandler?.Invoke(this, after);
}
ClearData();
return ret;
}
#if net40 #if net40
#else #else
public override Task<int> ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000, cancellationToken); public override Task<int> ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000, cancellationToken);
public override Task<List<T1>> ExecuteUpdatedAsync(CancellationToken cancellationToken = default) => base.SplitExecuteUpdatedAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000, cancellationToken); public override Task<List<T1>> ExecuteUpdatedAsync(CancellationToken cancellationToken = default) => base.SplitExecuteUpdatedAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000, cancellationToken);
protected override Task<List<T1>> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.ClickHouse.Custom 未实现该功能 未实现该功能"); protected override Task<List<T1>> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.ClickHouse.Custom 未实现该功能 未实现该功能");
async protected override Task<int> 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<T1>(_source, 1, 1));
ret = await this.RawExecuteAffrowsAsync(cancellationToken);
ClearData();
return ret;
}
var before = new Aop.TraceBeforeEventArgs("SplitExecuteAffrowsAsync", null);
_orm.Aop.TraceBeforeHandler?.Invoke(this, before);
Exception exception = null;
try
{
for (var a = 0; a < ss.Length; a++)
{
_source = ss[a];
_batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, a + 1, ss.Length));
ret += await this.RawExecuteAffrowsAsync(cancellationToken);
}
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
var after = new Aop.TraceAfterEventArgs(before, null, exception);
_orm.Aop.TraceAfterHandler?.Invoke(this, after);
}
ClearData();
return ret;
}
async protected override Task<List<T1>> SplitExecuteUpdatedAsync(int valuesLimit, int parameterLimit, CancellationToken cancellationToken = default)
{
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = new List<T1>();
if (ss.Length <= 1)
{
if (_source?.Any() == true) _batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, 1, 1));
ret = await this.RawExecuteUpdatedAsync(cancellationToken);
ClearData();
return ret;
}
var before = new Aop.TraceBeforeEventArgs("SplitExecuteUpdatedAsync", null);
_orm.Aop.TraceBeforeHandler?.Invoke(this, before);
Exception exception = null;
try
{
for (var a = 0; a < ss.Length; a++)
{
_source = ss[a];
_batchProgress?.Invoke(new BatchProgressStatus<T1>(_source, a + 1, ss.Length));
ret.AddRange(await this.RawExecuteUpdatedAsync(cancellationToken));
}
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
var after = new Aop.TraceAfterEventArgs(before, null, exception);
_orm.Aop.TraceAfterHandler?.Invoke(this, after);
}
ClearData();
return ret;
}
#endif #endif
} }
} }

View File

@ -1,11 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<!--;netcoreapp2.2;net472-->
<TargetFrameworks>netstandard2.1</TargetFrameworks> <TargetFrameworks>netstandard2.1</TargetFrameworks>
<Version>2.6.100</Version> <Version>2.6.100</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>FreeSql;ncc;YeXiangQin</Authors> <Authors>FreeSql;ncc;YeXiangQin;ChenBo</Authors>
<Description>FreeSql 数据库自定义适配,访问所有数据库</Description> <Description>FreeSql 数据库实现,基于 ClickHouse.Client Ado.net</Description>
<PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl> <PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl>
<RepositoryUrl>https://github.com/2881099/FreeSql</RepositoryUrl> <RepositoryUrl>https://github.com/2881099/FreeSql</RepositoryUrl>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>