diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index bdd16ff9..da7ace6b 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -538,14 +538,5 @@ - - - 批量注入 Repository,可以参考代码自行调整 - - - - - - diff --git a/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickHouseTest1.cs b/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickHouseTest1.cs index 55133c34..22cece67 100644 --- a/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickHouseTest1.cs +++ b/FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickHouseTest1.cs @@ -3,6 +3,9 @@ using System.Collections.Generic; using System.Reflection; using System.Text; using Xunit; +using System.Linq; +using System.Collections; +using System.Diagnostics; namespace FreeSql.Tests.MySql { @@ -32,13 +35,18 @@ namespace FreeSql.Tests.MySql public int? Points { get; set; } } [FreeSql.DataAnnotations.Table(Name = "ClickHouseTest")] - public class TestClickHouse + public class TestClickHouse : IEnumerable { [FreeSql.DataAnnotations.Column(IsPrimary = true)] [Now] public long Id { get; set; } public string Name { get; set; } + public IEnumerator GetEnumerator() + { + yield return Id; + yield return Name; + } } class NowAttribute: Attribute { } @@ -73,9 +81,10 @@ namespace FreeSql.Tests.MySql [Fact] public void TestInsert() { + Stopwatch stopwatch =new Stopwatch(); var fsql = g.clickHouse; List list=new List(); - for (int i = 0; i < 1000; i++) + for (int i = 0; i < 1000000; i++) { list.Add(new TestClickHouse() { @@ -83,9 +92,13 @@ namespace FreeSql.Tests.MySql Name = $"测试{i}" }); } + fsql.Delete().Where(t => 1 == 1).ExecuteAffrows(); + stopwatch.Start(); fsql.Insert(list).ExecuteAffrows(); - var items = fsql.Select().Where(o=>o.Id>900).OrderByDescending(o=>o.Id).ToList(); - Assert.Equal(100, items.Count); + stopwatch.Stop(); + Debug.WriteLine(list.Count+"条用时:" +stopwatch.ElapsedMilliseconds.ToString()); + //var items = fsql.Select().Where(o=>o.Id>900).OrderByDescending(o=>o.Id).ToList(); + //Assert.Equal(100, items.Count); } [Fact] diff --git a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseInsert.cs b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseInsert.cs index 6ddbb87b..57f606bb 100644 --- a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseInsert.cs +++ b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseInsert.cs @@ -1,9 +1,12 @@ -using FreeSql.Internal; +using ClickHouse.Client.ADO; +using ClickHouse.Client.Copy; +using FreeSql.Internal; using FreeSql.Internal.Model; using System; using System.Collections.Generic; using System.Data; using System.Data.Common; +using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -30,9 +33,9 @@ namespace FreeSql.ClickHouse.Curd internal Dictionary InternalIgnore => _ignore; internal void InternalClearData() => ClearData(); - public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchValuesLimit > 0 ? _batchValuesLimit : 5000, _batchParameterLimit > 0 ? _batchParameterLimit : 3000); - public override long ExecuteIdentity() => base.SplitExecuteIdentity(_batchValuesLimit > 0 ? _batchValuesLimit : 5000, _batchParameterLimit > 0 ? _batchParameterLimit : 3000); - public override List ExecuteInserted() => base.SplitExecuteInserted(_batchValuesLimit > 0 ? _batchValuesLimit : 5000, _batchParameterLimit > 0 ? _batchParameterLimit : 3000); + public override int ExecuteAffrows() => base.SplitExecuteAffrows(int.MaxValue, int.MaxValue); + public override long ExecuteIdentity() => base.SplitExecuteIdentity(int.MaxValue, int.MaxValue); + public override List ExecuteInserted() => base.SplitExecuteInserted(int.MaxValue, int.MaxValue); public override string ToSql() @@ -42,6 +45,81 @@ namespace FreeSql.ClickHouse.Curd return $"INSERT IGNORE INTO {sql.Substring(12)}"; } + protected override int RawExecuteAffrows() + { + var affrows = 0; + Exception exception = null; + Aop.CurdBeforeEventArgs before=null; + if (_source.Count>1) + { + try + { + 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) + { + DestinationTableName = _table.DbName, + BatchSize = _source.Count + }; + bulkCopyInterface.WriteToServerAsync(ToDataTable(),default).Wait(); + return affrows; + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, affrows); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + } + else + { + var sql = this.ToSql(); + before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + try + { + affrows = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _commandTimeout, _params); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, affrows); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + return affrows; + } + } + + private IDictionary GetValue(T u, System.Reflection.PropertyInfo[] columns) + { + try + { + Dictionary dic = new Dictionary(); + foreach (var item in columns) + { + object v = null; + if (u != null) + { + v = item.GetValue(u); + } + dic.TryAdd(item.Name, v); + } + return dic; + } + catch (Exception e) + { + throw; + } + } + protected override long RawExecuteIdentity() { var sql = this.ToSql(); diff --git a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs index a284c98d..16745836 100644 --- a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs +++ b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs @@ -24,7 +24,11 @@ namespace FreeSql.ClickHouse.Curd internal Dictionary InternalIgnore => _ignore; public override string ToSql() { - return base.ToSql()?.Replace("UPDATE", "ALTER TABLE").Replace("SET", "UPDATE"); + 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 source) => _source = source; internal string InternalWhereCaseSource(string CsName, Func thenValue) => WhereCaseSource(CsName, thenValue);