mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 10:42:52 +08:00
Merge branch 'master' of https://github.com/dotnetcore/FreeSql
This commit is contained in:
commit
5210723caa
@ -11,7 +11,7 @@
|
||||
<!--
|
||||
经常出于版本交叉问题,暂时关闭,在每个项目上设置版本号
|
||||
<PropertyGroup>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
-->
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
using FreeSql;
|
||||
using FreeSql.DataAnnotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
@ -57,3 +58,11 @@ public class User1 : BaseEntity<User1, Guid>
|
||||
[MaxLength(4000)]
|
||||
public string Description { get; set; }
|
||||
}
|
||||
|
||||
public class IdentityTable
|
||||
{
|
||||
[Column(IsIdentity = true, IsPrimary = true)]
|
||||
public int id { get; set; }
|
||||
|
||||
public string name { get; set; }
|
||||
}
|
@ -451,10 +451,10 @@ namespace base_entity
|
||||
//.UseSlaveWeight(10, 1, 1, 5)
|
||||
|
||||
|
||||
//.UseConnectionString(FreeSql.DataType.Firebird, @"database=localhost:D:\fbdata\EXAMPLES.fdb;user=sysdba;password=123456;max pool size=5")
|
||||
.UseConnectionString(FreeSql.DataType.Firebird, @"database=localhost:D:\fbdata\EXAMPLES.fdb;user=sysdba;password=123456;max pool size=5")
|
||||
.UseQuoteSqlName(false)
|
||||
|
||||
|
||||
.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;min pool size=1;Max pool size=2")
|
||||
//.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;min pool size=1;Max pool size=2")
|
||||
|
||||
//.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3;TrustServerCertificate=true")
|
||||
|
||||
@ -480,13 +480,52 @@ namespace base_entity
|
||||
|
||||
//.UseConnectionString(FreeSql.DataType.OdbcDameng, "Driver={DM8 ODBC DRIVER};Server=127.0.0.1:5236;Persist Security Info=False;Trusted_Connection=Yes;UID=USER1;PWD=123456789")
|
||||
|
||||
.UseMonitorCommand(cmd => Console.WriteLine(cmd.CommandText + "\r\n"))
|
||||
.UseMonitorCommand(cmd =>
|
||||
{
|
||||
Console.WriteLine(cmd.CommandText + "\r\n");
|
||||
cmd.CommandText = null; //不执行
|
||||
})
|
||||
.UseLazyLoading(true)
|
||||
//.UseGenerateCommandParameterWithLambda(true)
|
||||
.Build();
|
||||
BaseEntity.Initialization(fsql, () => _asyncUow.Value);
|
||||
#endregion
|
||||
|
||||
var groupsql01 = fsql.Select<User1>()
|
||||
.GroupBy(a => new
|
||||
{
|
||||
djjg = a.Id,
|
||||
qllx = a.Nickname,
|
||||
hjhs = a.GroupId
|
||||
})
|
||||
.ToSql(g => new
|
||||
{
|
||||
g.Key.djjg,
|
||||
g.Key.qllx,
|
||||
xhjsl = g.Count(g.Key.djjg),
|
||||
hjzhs = g.Sum(g.Key.hjhs),
|
||||
blywsl = g.Count()
|
||||
}, FieldAliasOptions.AsProperty);
|
||||
|
||||
using (var uow = fsql.CreateUnitOfWork())
|
||||
{
|
||||
uow.Orm.Select<User1>().ForUpdate().ToList();
|
||||
}
|
||||
|
||||
var listaaaddd = new List<User1>();
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
listaaaddd.Add(new User1 { Nickname = $"测试文本:{i}" });
|
||||
}
|
||||
fsql.Select<User1>();
|
||||
fsql.Transaction(() =>
|
||||
{
|
||||
|
||||
fsql.Insert(listaaaddd).ExecuteAffrows(); //加在事务里就出错
|
||||
});
|
||||
|
||||
fsql.Select<IdentityTable>().Count();
|
||||
|
||||
var dkdksql = fsql.Select<User1>().WithLock().From<UserGroup>()
|
||||
.InnerJoin<UserGroup>((user, usergroup) => user.GroupId == usergroup.Id && usergroup.GroupName == "xxx")
|
||||
.ToSql();
|
||||
|
@ -15,15 +15,16 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FreeSql;
|
||||
using FreeSql.Internal.CommonProvider;
|
||||
|
||||
namespace orm_vs
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static IFreeSql fsql = new FreeSql.FreeSqlBuilder()
|
||||
.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=tedb;Pooling=true;Max Pool Size=20")
|
||||
//.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=20")
|
||||
//.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=20")
|
||||
.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=tedb1;Pooling=true;Max Pool Size=21;TrustServerCertificate=true")
|
||||
//.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=21;AllowLoadLocalInfile=true;")
|
||||
//.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=21")
|
||||
.UseAutoSyncStructure(false)
|
||||
.UseNoneCommandParameter(true)
|
||||
//.UseConfigEntityFromDbFirst(true)
|
||||
@ -35,11 +36,11 @@ namespace orm_vs
|
||||
{
|
||||
var db = new SqlSugarClient(new ConnectionConfig()
|
||||
{
|
||||
ConnectionString = "Data Source=.;Integrated Security=True;Initial Catalog=tedb;Pooling=true;Min Pool Size=20;Max Pool Size=20",
|
||||
ConnectionString = "Data Source=.;Integrated Security=True;Initial Catalog=tedb1;Pooling=true;Min Pool Size=20;Max Pool Size=20;TrustServerCertificate=true",
|
||||
DbType = DbType.SqlServer,
|
||||
//ConnectionString = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Min Pool Size=20;Max Pool Size=20",
|
||||
//ConnectionString = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Min Pool Size=20;Max Pool Size=20;AllowLoadLocalInfile=true;",
|
||||
//DbType = DbType.MySql,
|
||||
//ConnectionString = "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=21",
|
||||
//ConnectionString = "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=20",
|
||||
//DbType = DbType.PostgreSQL,
|
||||
IsAutoCloseConnection = true,
|
||||
InitKeyType = InitKeyType.Attribute
|
||||
@ -58,18 +59,15 @@ namespace orm_vs
|
||||
public DbSet<PatientExamination_2022> PatientExamination_2022s { get; set; }
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
optionsBuilder.UseSqlServer(@"Data Source=.;Integrated Security=True;Initial Catalog=tedb;Pooling=true;Min Pool Size=21;Max Pool Size=21");
|
||||
//optionsBuilder.UseMySql("Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Min Pool Size=21;Max Pool Size=21");
|
||||
//optionsBuilder.UseNpgsql("Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=21");
|
||||
optionsBuilder.UseSqlServer(@"Data Source=.;Integrated Security=True;Initial Catalog=tedb1;Pooling=true;Min Pool Size=19;Max Pool Size=19;TrustServerCertificate=true");
|
||||
//var connectionString = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Min Pool Size=19;Max Pool Size=19";
|
||||
//optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
|
||||
//optionsBuilder.UseNpgsql("Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=19");
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
modelBuilder.Entity<Song>()
|
||||
.Property(a => a.create_time)
|
||||
.HasConversion(a => int.Parse(a.ToString()), a => new DateTime(a));
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +134,7 @@ namespace orm_vs
|
||||
}
|
||||
static void TestDapperSelectPatientExamination_2022()
|
||||
{
|
||||
using (var conn = new SqlConnection("Data Source=.;Integrated Security=True;Initial Catalog=tedb;Pooling=true;Min Pool Size=21;Max Pool Size=22"))
|
||||
using (var conn = new SqlConnection("Data Source=.;Integrated Security=True;Initial Catalog=tedb1;Pooling=true;Min Pool Size=21;Max Pool Size=22"))
|
||||
{
|
||||
var list = conn.Query<PatientExamination_2022>("select top 40000 * from PatientExamination_2022");
|
||||
}
|
||||
@ -145,28 +143,28 @@ namespace orm_vs
|
||||
static DbConnection fsqlConn = null;
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var count = 0;
|
||||
var sws = new List<long>();
|
||||
Console.WriteLine("观察查询4万条记录内存,按 Enter 进入下一次,按任易键即出程序。。。");
|
||||
//while(Console.ReadKey().Key == ConsoleKey.Enter)
|
||||
//using (var fcon = fsql.Ado.MasterPool.Get())
|
||||
//{
|
||||
//fsqlConn = fcon.Value;
|
||||
for (var a = 0; a < 80; a++)
|
||||
{
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
TestFreeSqlSelectPatientExamination_2022();
|
||||
//TestEfSelectPatientExamination_2022();
|
||||
//TestSqlSugarSelectPatientExamination_2022();
|
||||
//TestDapperSelectPatientExamination_2022();
|
||||
sw.Stop();
|
||||
sws.Add(sw.ElapsedMilliseconds);
|
||||
Console.WriteLine($"第 {++count} 次,查询4万条记录, {sw.ElapsedMilliseconds}ms,平均 {(long)sws.Average()}ms");
|
||||
}
|
||||
//}
|
||||
Console.ReadKey();
|
||||
fsql.Dispose();
|
||||
return;
|
||||
//var count = 0;
|
||||
//var sws = new List<long>();
|
||||
//Console.WriteLine("观察查询4万条记录内存,按 Enter 进入下一次,按任易键即出程序。。。");
|
||||
////while(Console.ReadKey().Key == ConsoleKey.Enter)
|
||||
////using (var fcon = fsql.Ado.MasterPool.Get())
|
||||
////{
|
||||
// //fsqlConn = fcon.Value;
|
||||
// for (var a = 0; a < 80; a++)
|
||||
// {
|
||||
// Stopwatch sw = Stopwatch.StartNew();
|
||||
// TestFreeSqlSelectPatientExamination_2022();
|
||||
// //TestEfSelectPatientExamination_2022();
|
||||
// //TestSqlSugarSelectPatientExamination_2022();
|
||||
// //TestDapperSelectPatientExamination_2022();
|
||||
// sw.Stop();
|
||||
// sws.Add(sw.ElapsedMilliseconds);
|
||||
// Console.WriteLine($"第 {++count} 次,查询4万条记录, {sw.ElapsedMilliseconds}ms,平均 {(long)sws.Average()}ms");
|
||||
// }
|
||||
////}
|
||||
//Console.ReadKey();
|
||||
//fsql.Dispose();
|
||||
//return;
|
||||
|
||||
//fsql.CodeFirst.SyncStructure(typeof(Song), typeof(Song_tag), typeof(Tag));
|
||||
//sugar.CodeFirst.InitTables(typeof(Song), typeof(Song_tag), typeof(Tag));
|
||||
@ -186,13 +184,6 @@ namespace orm_vs
|
||||
var sb = new StringBuilder();
|
||||
var time = new Stopwatch();
|
||||
|
||||
var sql222 = fsql.Select<Song>().Where(a => DateTime.Now.Subtract(a.create_time.Value).TotalHours > 0).ToSql();
|
||||
|
||||
var conModels = new List<IConditionalModel>();
|
||||
conModels.Add(new ConditionalModel { FieldName = "`id` = 1 or 1=1; delete from song_tag; -- ", ConditionalType = ConditionalType.Equal, FieldValue = "1" });
|
||||
|
||||
var student = sugar.Queryable<Song>().Where(conModels).ToList();
|
||||
|
||||
|
||||
#region ET test
|
||||
////var t31 = fsql.Select<xxx>().ToList();
|
||||
@ -483,23 +474,10 @@ namespace orm_vs
|
||||
|
||||
#endregion
|
||||
|
||||
var testlist1 = fsql.Select<Song>().OrderBy(a => a.id).ToList();
|
||||
var testlist2 = new List<Song>();
|
||||
fsql.Select<Song>().OrderBy(a => a.id).ToChunk(2, fetch =>
|
||||
sugar.Aop.OnLogExecuted = (s, e) =>
|
||||
{
|
||||
testlist2.AddRange(fetch.Object);
|
||||
});
|
||||
|
||||
var testlist22 = new List<object>();
|
||||
fsql.Select<Song, Song_tag>().LeftJoin((a, b) => a.id == b.song_id).ToChunk((a, b) => new { a.title, a.create_time, b.tag_id }, 2, fetch =>
|
||||
{
|
||||
testlist22.AddRange(fetch.Object);
|
||||
});
|
||||
|
||||
//sugar.Aop.OnLogExecuted = (s, e) =>
|
||||
//{
|
||||
// Trace.WriteLine(s);
|
||||
//};
|
||||
Trace.WriteLine(s);
|
||||
};
|
||||
//测试前清空数据
|
||||
fsql.Delete<Song>().Where(a => a.id > 0).ExecuteAffrows();
|
||||
sugar.Deleteable<Song>().Where(a => a.id > 0).ExecuteCommand();
|
||||
@ -548,10 +526,10 @@ namespace orm_vs
|
||||
sb.Clear();
|
||||
|
||||
Console.WriteLine("更新:");
|
||||
Update(sb, 100, 1);
|
||||
Update(sb, 10, 1);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
Update(sb, 100, 10);
|
||||
Update(sb, 10, 10);
|
||||
Console.Write(sb.ToString());
|
||||
sb.Clear();
|
||||
|
||||
@ -598,21 +576,21 @@ namespace orm_vs
|
||||
sw.Stop();
|
||||
sb.AppendLine($"EFCore Select {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms .net5.0无效");
|
||||
|
||||
sw.Restart();
|
||||
using (var conn = fsql.Ado.MasterPool.Get())
|
||||
{
|
||||
for (var a = 0; a < forTime; a++)
|
||||
Dapper.SqlMapper.Query<Song>(conn.Value, $"select top {size} * from freesql_song").ToList();
|
||||
}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"Dapper Select {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms\r\n");
|
||||
//sw.Restart();
|
||||
//using (var conn = fsql.Ado.MasterPool.Get())
|
||||
//{
|
||||
// for (var a = 0; a < forTime; a++)
|
||||
// Dapper.SqlMapper.Query<Song>(conn.Value, $"select * from freesql_song limit {size}").ToList();
|
||||
//}
|
||||
//sw.Stop();
|
||||
//sb.AppendLine($"Dapper Select {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms\r\n");
|
||||
}
|
||||
|
||||
static void Insert(StringBuilder sb, int forTime, int size)
|
||||
{
|
||||
var songs = Enumerable.Range(0, size).Select(a => new Song
|
||||
{
|
||||
create_time = DateTime.Now,
|
||||
create_time = DateTime.Now.ToString(),
|
||||
is_deleted = false,
|
||||
title = $"Insert_{a}",
|
||||
url = $"Url_{a}"
|
||||
@ -647,6 +625,7 @@ namespace orm_vs
|
||||
try
|
||||
{
|
||||
for (var a = 0; a < forTime; a++)
|
||||
//sugar.Fastest<Song>().BulkCopy(songs.ToList());
|
||||
sugar.Insertable(songs.ToArray()).ExecuteCommand();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -682,7 +661,61 @@ namespace orm_vs
|
||||
fsql.Update<Song>().SetSource(songs).ExecuteAffrows();
|
||||
}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"FreeSql Update {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
sb.AppendLine($"FreeSql Update1 {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
|
||||
songs = fsql.Select<Song>().Limit(size).ToList();
|
||||
sw.Restart();
|
||||
for (var a = 0; a < forTime; a++)
|
||||
{
|
||||
fsql.Update<Song>().SetSource(songs).ExecuteSqlBulkCopy();
|
||||
}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"FreeSql BulkCopyUpdate {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
// songs = fsql.Select<Song>().Limit(size).ToList();
|
||||
// sw.Restart();
|
||||
// for (var a = 0; a < forTime; a++)
|
||||
// {
|
||||
// //fsql.Update<Song>().SetSource(songs).ExecuteAffrows();
|
||||
// var iou = fsql.InsertOrUpdate<Song>() as InsertOrUpdateProvider<Song>;
|
||||
// var dbsql = new StringBuilder();
|
||||
// var dbparms = new List<DbParameter>();
|
||||
// iou.WriteSourceSelectUnionAll(songs, dbsql, dbparms);
|
||||
|
||||
// var sql = $@"update freesql_song a
|
||||
//inner join ( {dbsql} ) b on b.id = a.id
|
||||
//set a.create_time = b.create_time, a.is_deleted = b.is_deleted, a.title = b.title, a.url = b.url";
|
||||
// fsql.Ado.ExecuteNonQuery(System.Data.CommandType.Text, sql, dbparms.ToArray());
|
||||
// }
|
||||
// sw.Stop();
|
||||
// sb.AppendLine($"FreeSql Update2(update inner join) {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
// songs = fsql.Select<Song>().Limit(size).ToList();
|
||||
// sw.Restart();
|
||||
// for (var a = 0; a < forTime; a++)
|
||||
// {
|
||||
// var isdroped = false;
|
||||
// var tempTableName = $"#Temp_freesql_song";
|
||||
// fsql.Ado.ExecuteNonQuery($"select * into {tempTableName} from [freesql_song] where 1=2");
|
||||
// try
|
||||
// {
|
||||
// fsql.Insert(songs).AsTable(tempTableName).ExecuteMySqlBulkCopy();
|
||||
// var sql = $@"update freesql_song a
|
||||
//inner join {tempTableName} b on b.id = a.id;
|
||||
//set a.create_time = b.create_time, a.is_deleted = b.is_deleted, a.title = b.title, a.url = b.url
|
||||
//; drop table {tempTableName}; ";
|
||||
// fsql.Ado.ExecuteNonQuery(System.Data.CommandType.Text, sql);
|
||||
// isdroped = true;
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// if (isdroped == false)
|
||||
// fsql.Ado.ExecuteNonQuery($"drop table {tempTableName}");
|
||||
// }
|
||||
// }
|
||||
// sw.Stop();
|
||||
// sb.AppendLine($"FreeSql Update3(update inner join #temp) {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms");
|
||||
|
||||
songs = sugar.Queryable<Song>().Take(size).ToList();
|
||||
sw.Restart();
|
||||
@ -690,7 +723,7 @@ namespace orm_vs
|
||||
try
|
||||
{
|
||||
for (var a = 0; a < forTime; a++)
|
||||
sugar.Updateable(songs).ExecuteCommand();
|
||||
sugar.Fastest<Song>().BulkUpdate(songs);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -699,21 +732,21 @@ namespace orm_vs
|
||||
sw.Stop();
|
||||
sb.AppendLine($"SqlSugar Update {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms" + (sugarEx != null ? $"成绩无效,错误:{sugarEx.Message}" : ""));
|
||||
|
||||
using (var db = new SongContext())
|
||||
{
|
||||
songs = db.Songs.Take(size).AsNoTracking().ToList();
|
||||
}
|
||||
sw.Restart();
|
||||
for (var a = 0; a < forTime; a++)
|
||||
{
|
||||
//using (var db = new SongContext())
|
||||
//{
|
||||
// songs = db.Songs.Take(size).AsNoTracking().ToList();
|
||||
//}
|
||||
//sw.Restart();
|
||||
//for (var a = 0; a < forTime; a++)
|
||||
//{
|
||||
|
||||
using (var db = new SongContext())
|
||||
{
|
||||
//db.Configuration.AutoDetectChangesEnabled = false;
|
||||
//db.Songs.UpdateRange(songs.ToArray());
|
||||
//db.SaveChanges();
|
||||
}
|
||||
}
|
||||
// using (var db = new SongContext())
|
||||
// {
|
||||
// //db.Configuration.AutoDetectChangesEnabled = false;
|
||||
// //db.Songs.UpdateRange(songs.ToArray());
|
||||
// //db.SaveChanges();
|
||||
// }
|
||||
//}
|
||||
sw.Stop();
|
||||
sb.AppendLine($"EFCore Update {size}条数据,循环{forTime}次,耗时{sw.ElapsedMilliseconds}ms .net5.0无效\r\n");
|
||||
}
|
||||
@ -729,7 +762,7 @@ namespace orm_vs
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int id { get; set; }
|
||||
public DateTime? create_time { get; set; }
|
||||
public string create_time { get; set; }
|
||||
public bool? is_deleted { get; set; }
|
||||
public string title { get; set; }
|
||||
public string url { get; set; }
|
||||
|
@ -2,20 +2,20 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper" Version="2.0.35" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.4" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.0" />
|
||||
<PackageReference Include="sqlSugarCore" Version="5.0.8" />
|
||||
<PackageReference Include="Dapper" Version="2.0.123" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.0" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="7.0.0-alpha.1" />
|
||||
<PackageReference Include="sqlSugarCore" Version="5.1.3.38" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\FreeSql\FreeSql.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.MySql\FreeSql.Provider.MySql.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.MySqlConnector\FreeSql.Provider.MySqlConnector.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.PostgreSQL\FreeSql.Provider.PostgreSQL.csproj" />
|
||||
<ProjectReference Include="..\..\Providers\FreeSql.Provider.SqlServer\FreeSql.Provider.SqlServer.csproj" />
|
||||
</ItemGroup>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<Title>$(AssemblyName)</Title>
|
||||
<IsPackable>true</IsPackable>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -22,6 +22,7 @@ namespace FreeSql.Generator
|
||||
string ArgsConnectionString { get; }
|
||||
string ArgsFilter { get; }
|
||||
string ArgsMatch { get; }
|
||||
string ArgsJson { get; }
|
||||
string ArgsFileName { get; }
|
||||
bool ArgsReadKey { get; }
|
||||
internal string ArgsOutput { get; private set; }
|
||||
@ -62,6 +63,7 @@ new Colorful.Formatter("v" + string.Join(".", typeof(ConsoleApp).Assembly.GetNam
|
||||
ArgsNameSpace = "MyProject";
|
||||
ArgsFilter = "";
|
||||
ArgsMatch = "";
|
||||
ArgsJson = "Newtonsoft.Json";
|
||||
ArgsFileName = "{name}.cs";
|
||||
ArgsReadKey = true;
|
||||
Action<string> setArgsOutput = value =>
|
||||
@ -94,7 +96,7 @@ new Colorful.Formatter("v" + string.Join(".", typeof(ConsoleApp).Assembly.GetNam
|
||||
|
||||
-NameOptions * 4个布尔值对应:
|
||||
首字母大写
|
||||
首字母大写,其他小写
|
||||
首字母大写,其他小写
|
||||
全部小写
|
||||
下划线转驼峰
|
||||
|
||||
@ -116,6 +118,8 @@ new Colorful.Formatter("v" + string.Join(".", typeof(ConsoleApp).Assembly.GetNam
|
||||
如果不想生成视图和存储过程 -Filter View+StoreProcedure
|
||||
|
||||
-Match 表名或正则表达式,只生成匹配的表,如:dbo\.TB_.+
|
||||
-Json NTJ、STJ、NONE
|
||||
Newtonsoft.Json、System.Text.Json、不生成
|
||||
|
||||
-FileName 文件名,默认:{name}.cs
|
||||
-Output 保存路径,默认为当前 shell 所在目录
|
||||
@ -196,6 +200,18 @@ new Colorful.Formatter("推荐在实体类目录创建 gen.bat,双击它重新
|
||||
if (Regex.IsMatch("", ArgsMatch)) { } //throw
|
||||
a++;
|
||||
break;
|
||||
case "-json":
|
||||
switch(args[a + 1].Trim().ToLower())
|
||||
{
|
||||
case "none":
|
||||
ArgsJson = "";
|
||||
break;
|
||||
case "stj":
|
||||
ArgsJson = "System.Text.Json";
|
||||
break;
|
||||
}
|
||||
a++;
|
||||
break;
|
||||
case "-filename":
|
||||
ArgsFileName = args[a + 1];
|
||||
a++;
|
||||
|
@ -13,7 +13,7 @@
|
||||
<PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/2881099/FreeSql</RepositoryUrl>
|
||||
<PackageTags>FreeSql DbFirst 实体生成器</PackageTags>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -83,6 +83,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "aspnetcore_transaction", "E
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Extensions.AggregateRoot", "Extensions\FreeSql.Extensions.AggregateRoot\FreeSql.Extensions.AggregateRoot.csproj", "{5C78C4CE-3CDC-49C3-AF34-556567B95F2A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "orm_vs", "Examples\orm_vs\orm_vs.csproj", "{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -453,6 +455,18 @@ Global
|
||||
{5C78C4CE-3CDC-49C3-AF34-556567B95F2A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{5C78C4CE-3CDC-49C3-AF34-556567B95F2A}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5C78C4CE-3CDC-49C3-AF34-556567B95F2A}.Release|x86.Build.0 = Release|Any CPU
|
||||
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -484,10 +498,11 @@ Global
|
||||
{19D2E22A-B000-46B6-AFC8-60BF01A51C9A} = {2A381C57-2697-427B-9F10-55DA11FD02E4}
|
||||
{28163C3B-B2E6-432D-AAC3-F5F19374BE31} = {94C8A78D-AA15-47B2-A348-530CD86BFC1B}
|
||||
{5C78C4CE-3CDC-49C3-AF34-556567B95F2A} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
|
||||
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D} = {94C8A78D-AA15-47B2-A348-530CD86BFC1B}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
RESX_NeutralResourcesLanguage = en-US
|
||||
RESX_PrefixTranslations = True
|
||||
SolutionGuid = {089687FA-5D21-40AC-BA8A-AA0D1E1H7F98}
|
||||
RESX_PrefixTranslations = True
|
||||
RESX_NeutralResourcesLanguage = en-US
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@ -17,7 +17,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -70,7 +70,10 @@ namespace FreeSql
|
||||
{
|
||||
var db = _resolveDbContext?.Invoke();
|
||||
db?.FlushCommand();
|
||||
var select = _originalFsql.Select<T1>().WithTransaction(_resolveUnitOfWork?.Invoke()?.GetOrBeginTransaction(false));
|
||||
var uow = _resolveUnitOfWork?.Invoke();
|
||||
var uowIsolationLevel = uow?.IsolationLevel ?? IsolationLevel.Unspecified;
|
||||
var select = _originalFsql.Select<T1>().WithTransaction(uow?.GetOrBeginTransaction(uowIsolationLevel != IsolationLevel.Unspecified));
|
||||
(select as Select0Provider)._resolveHookTransaction = () => uow?.GetOrBeginTransaction();
|
||||
if (db?.Options.EnableGlobalFilter == false) select.DisableGlobalFilter();
|
||||
return select;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using FreeSql.Internal.CommonProvider;
|
||||
using System.Data;
|
||||
|
||||
namespace FreeSql
|
||||
{
|
||||
@ -34,7 +35,9 @@ namespace FreeSql
|
||||
protected virtual ISelect<TEntity> OrmSelect(object dywhere)
|
||||
{
|
||||
DbContextFlushCommand(); //查询前先提交,否则会出脏读
|
||||
var select = _db.OrmOriginal.Select<TEntity>().AsType(_entityType).WithTransaction(_uow?.GetOrBeginTransaction(false)).TrackToList(TrackToList).WhereDynamic(dywhere);
|
||||
var uowIsolationLevel = _uow?.IsolationLevel ?? IsolationLevel.Unspecified;
|
||||
var select = _db.OrmOriginal.Select<TEntity>().AsType(_entityType).WithTransaction(_uow?.GetOrBeginTransaction(uowIsolationLevel != IsolationLevel.Unspecified)).TrackToList(TrackToList).WhereDynamic(dywhere);
|
||||
(select as Select0Provider)._resolveHookTransaction = () => _uow?.GetOrBeginTransaction();
|
||||
if (_db.Options.EnableGlobalFilter == false) select.DisableGlobalFilter();
|
||||
return select;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -733,15 +733,6 @@
|
||||
<param name="modelBuilder"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSqlDbContextExtensions.ApplyConfigurationsFromAssembly(FreeSql.ICodeFirst,System.Reflection.Assembly,System.Func{System.Type,System.Boolean})">
|
||||
<summary>
|
||||
根据Assembly扫描所有继承IEntityTypeConfiguration<T>的配置类
|
||||
</summary>
|
||||
<param name="codeFirst"></param>
|
||||
<param name="assembly"></param>
|
||||
<param name="predicate"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSqlDbContextExtensions.CreateDbContext(IFreeSql)">
|
||||
<summary>
|
||||
创建普通数据上下文档对象
|
||||
@ -800,14 +791,5 @@
|
||||
<param name="that"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{FreeSql.FluentDataFilter},System.Reflection.Assembly[])">
|
||||
<summary>
|
||||
批量注入 Repository,可以参考代码自行调整
|
||||
</summary>
|
||||
<param name="services"></param>
|
||||
<param name="globalDataFilter"></param>
|
||||
<param name="assemblies"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1,4 +1,4 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using FreeSql.DataAnnotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -181,6 +181,32 @@ namespace FreeSql.Tests.MySqlConnector
|
||||
Assert.Equal(TestEnumInserTbType.sum211, g.mysql.Select<TestEnumInsertTb>().Where(a => a.id == id).First()?.type);
|
||||
}
|
||||
|
||||
|
||||
[Table(Name = "tb_topic_insertbulk")]
|
||||
class TopicBulk
|
||||
{
|
||||
[Column(IsIdentity = true, IsPrimary = true)]
|
||||
public int Id { get; set; }
|
||||
public int Clicks { get; set; }
|
||||
public string Title { get; set; }
|
||||
public DateTime CreateTime { get; set; }
|
||||
}
|
||||
[Fact]
|
||||
public void ExecuteMySqlBulkCopy()
|
||||
{
|
||||
g.mysql.Delete<TopicBulk>().Where(a => true).ExecuteAffrows();
|
||||
var items = new List<TopicBulk>();
|
||||
for (var a = 0; a < 10; a++) items.Add(new TopicBulk { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now });
|
||||
|
||||
g.mysql.Insert(items).ExecuteMySqlBulkCopy();
|
||||
|
||||
items = g.mysql.Select<TopicBulk>().OrderByDescending(a => a.Id).Limit(1000).ToList();
|
||||
g.mysql.Update<TopicBulk>().SetSource(items).ExecuteMySqlBulkCopy();
|
||||
g.mysql.Update<TopicBulk>().SetSource(items, a => new { a.Id, a.Clicks }).ExecuteMySqlBulkCopy();
|
||||
g.mysql.Update<TopicBulk>().SetSource(items).UpdateColumns(a => new { a.Title }).ExecuteMySqlBulkCopy();
|
||||
g.mysql.Update<TopicBulk>().SetSource(items, a => new { a.Id, a.Clicks }).UpdateColumns(a => new { a.Title }).ExecuteMySqlBulkCopy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsTable()
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using FreeSql.DataAnnotations;
|
||||
using MySqlConnector;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Xunit;
|
||||
@ -19,11 +20,17 @@ namespace FreeSql.Tests.MySqlConnectorMapType
|
||||
[Fact]
|
||||
public void DateTimeToDateTimeOffSet()
|
||||
{
|
||||
|
||||
//MySqlDateTime dt1 = new MySqlDateTime(DateTime.Now);
|
||||
//System.Convert.ChangeType(dt1, typeof(DateTimeOffset)); // System.Exception : Specified cast is not valid.
|
||||
|
||||
|
||||
//insert
|
||||
var orm = g.mysql;
|
||||
orm.Delete<DateTimeOffSetTestMap>().Where(a => true).ExecuteAffrows();
|
||||
var item = new DateTimeOffSetTestMap { dtos_to_dt = DateTimeOffset.Now, dtosnullable_to_dt = DateTimeOffset.Now };
|
||||
Assert.Equal(1, orm.Insert<DateTimeOffSetTestMap>().AppendData(item).ExecuteAffrows());
|
||||
var find = orm.Select<DateTimeOffSetTestMap>().Where(a => a.id == item.id).First();
|
||||
var find = orm.Select<DateTimeOffSetTestMap>().Where(a => a.id == item.id).First(); // System.Exception : Specified cast is not valid.
|
||||
Assert.NotNull(find);
|
||||
Assert.Equal(item.id, find.id);
|
||||
Assert.Equal(item.dtos_to_dt.ToString("g"), find.dtos_to_dt.ToString("g"));
|
||||
|
@ -8,7 +8,7 @@ public class g
|
||||
{
|
||||
|
||||
static Lazy<IFreeSql> mysqlLazy = new Lazy<IFreeSql>(() => new FreeSql.FreeSqlBuilder()
|
||||
.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd_mysqlconnector;Charset=utf8;SslMode=none;Max pool size=10;AllowLoadLocalInfile=true")
|
||||
.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd_mysqlconnector;Charset=utf8;SslMode=none;Max pool size=10;AllowLoadLocalInfile=true;AllowZeroDateTime=True ")
|
||||
//.UseConnectionFactory(FreeSql.DataType.MySql, () => new MySql.Data.MySqlClient.MySqlConnection("Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd_mysqlconnector;Charset=utf8;SslMode=none;"))
|
||||
//.UseConnectionString(FreeSql.DataType.MySql, "Data Source=192.168.164.10;Port=33061;User ID=root;Password=root;Initial Catalog=cccddd_mysqlconnector;Charset=utf8;SslMode=none;Max pool size=10")
|
||||
.UseAutoSyncStructure(true)
|
||||
|
27
FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickHouseTest2.cs
Normal file
27
FreeSql.Tests/FreeSql.Tests/ClickHouse/ClickHouseTest2.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using FreeSql.DataAnnotations;
|
||||
using Xunit;
|
||||
|
||||
namespace FreeSql.Tests.ClickHouse
|
||||
{
|
||||
public class ClickHouseTest2
|
||||
{
|
||||
private static IFreeSql fsql = new FreeSqlBuilder().UseConnectionString(DataType.ClickHouse,
|
||||
"Host=127.0.0.1;Port=8123;Database=test;Compress=True;Min Pool Size=1")
|
||||
.UseMonitorCommand(cmd => Console.WriteLine($"线程:{cmd.CommandText}\r\n"))
|
||||
.UseNoneCommandParameter(true)
|
||||
.Build();
|
||||
[Fact]
|
||||
public void CodeFirst()
|
||||
{
|
||||
fsql.CodeFirst.SyncStructure(typeof(CollectDataEntityUpdate01));
|
||||
}
|
||||
}
|
||||
}
|
237
FreeSql.Tests/FreeSql.Tests/ClickHouse/CollectDataEntity2.cs
Normal file
237
FreeSql.Tests/FreeSql.Tests/ClickHouse/CollectDataEntity2.cs
Normal file
@ -0,0 +1,237 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace FreeSql.Tests.ClickHouse
|
||||
{
|
||||
/// <summary>
|
||||
/// 实时数据
|
||||
/// </summary>
|
||||
[Index("idx_{tablename}_01", nameof(Guid), true)]
|
||||
[Index("idx_{tablename}_02", nameof(TenantId), true)]
|
||||
//复合索引
|
||||
[Index("idx_{tablename}_03", $"{nameof(CreatedUserId)},{nameof(Version)}", false)]
|
||||
[Table(OldName = "CollectDataEntityUpdate")]
|
||||
public partial class CollectDataEntityUpdate01
|
||||
{
|
||||
/// <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, OldName = "CreatedUserNameUpdate")]
|
||||
public string CreatedUserNameUpdate01
|
||||
{
|
||||
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, IsPrimary = true)]
|
||||
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>
|
||||
[Column(StringLength = 18)]
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -4,6 +4,126 @@
|
||||
<name>FreeSql.Tests</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01">
|
||||
<summary>
|
||||
实时数据
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.Guid">
|
||||
<summary>
|
||||
Guid
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.TenantId">
|
||||
<summary>
|
||||
租户Id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.Version">
|
||||
<summary>
|
||||
版本
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.IsDeleted">
|
||||
<summary>
|
||||
是否删除
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.CreatedUserId">
|
||||
<summary>
|
||||
创建者Id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.CreatedUserNameUpdate01">
|
||||
<summary>
|
||||
创建者
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.CreatedTime">
|
||||
<summary>
|
||||
创建时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.ModifiedUserId">
|
||||
<summary>
|
||||
修改者Id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.ModifiedUserName">
|
||||
<summary>
|
||||
修改者
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.ModifiedTime">
|
||||
<summary>
|
||||
修改时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.DataFlag">
|
||||
<summary>
|
||||
数据标识
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.Id">
|
||||
<summary>
|
||||
主键Id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.EquipmentCode">
|
||||
<summary>
|
||||
设备编号
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.PropertyCode">
|
||||
<summary>
|
||||
数据编号,如为空使用默认数据
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.PropertyName">
|
||||
<summary>
|
||||
数据名称,如为空使用默认数据
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.IsValueOrStateChanged">
|
||||
<summary>
|
||||
数值或状态是否变更
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.NumericValue">
|
||||
<summary>
|
||||
采集数值
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.Remark">
|
||||
<summary>
|
||||
备注
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.ServiceFlag">
|
||||
<summary>
|
||||
服务标记
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.StrState">
|
||||
<summary>
|
||||
状态
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.StrValue">
|
||||
<summary>
|
||||
文本数值
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.UnitStr">
|
||||
<summary>
|
||||
单位
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.ClickHouse.CollectDataEntityUpdate01.CollectTime">
|
||||
<summary>
|
||||
采集时间
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.Tests.Firebird.FirebirdCodeFirstTest.AddUniquesInfo.id">
|
||||
<summary>
|
||||
编号
|
||||
|
@ -15,14 +15,13 @@ namespace FreeSql.Tests.MySql
|
||||
public void InsertOrUpdate_OnePrimary()
|
||||
{
|
||||
fsql.Delete<tbiou02>().Where("1=1").ExecuteAffrows();
|
||||
var iou = fsql.InsertOrUpdate<tbiou02>().SetSource(fsql.Select<tbiou022>().ToSql(a => new { id = a.id + 1, name = "xxx" }, FieldAliasOptions.AsProperty));
|
||||
var iou = fsql.InsertOrUpdate<tbiou02>().SetSource(fsql.Select<tbiou022>().ToSql(a => new { id = a.id + 1, name = "'xxx'" }, FieldAliasOptions.AsProperty));
|
||||
var sql = iou.ToSql();
|
||||
Assert.Equal(@"INSERT INTO `tbiou02`(`id`, `name`)
|
||||
SELECT (a.`id` + 1) `id`, xxx `name`
|
||||
SELECT (a.`id` + 1) `id`, 'xxx' `name`
|
||||
FROM `tbiou022` a
|
||||
ON DUPLICATE KEY UPDATE
|
||||
`name` = VALUES(`name`)", sql);
|
||||
Assert.Equal(0, iou.ExecuteAffrows());
|
||||
|
||||
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "01" });
|
||||
sql = iou.ToSql();
|
||||
|
@ -1,4 +1,4 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using FreeSql.DataAnnotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -11,7 +11,7 @@ namespace FreeSql.Tests.PostgreSQL
|
||||
|
||||
IInsert<Topic> insert => g.pgsql.Insert<Topic>();
|
||||
|
||||
[Table(Name = "tb_topic_insert")]
|
||||
[Table(Name = "tb_topic_insert2")]
|
||||
class Topic
|
||||
{
|
||||
[Column(IsIdentity = true, IsPrimary = true)]
|
||||
@ -137,6 +137,35 @@ namespace FreeSql.Tests.PostgreSQL
|
||||
insert.AppendData(items.First()).ExecuteInserted();
|
||||
}
|
||||
|
||||
|
||||
[Table(Name = "tb_topic_insert_pgcopy")]
|
||||
class TopicPgCopy
|
||||
{
|
||||
[Column(IsIdentity = true, IsPrimary = true)]
|
||||
public int Id { get; set; }
|
||||
public int Clicks { get; set; }
|
||||
public TestTypeInfo Type { get; set; }
|
||||
public string Title { get; set; }
|
||||
public DateTime CreateTime { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExecutePgCopy()
|
||||
{
|
||||
var maxId = g.pgsql.Select<TopicPgCopy>().Max(a => a.Id);
|
||||
var items = new List<TopicPgCopy>();
|
||||
for (var a = 0; a < 10; a++) items.Add(new TopicPgCopy { Id = maxId + a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now });
|
||||
|
||||
g.pgsql.Insert(items).InsertIdentity().ExecutePgCopy();
|
||||
|
||||
items = g.pgsql.Select<TopicPgCopy>().OrderByDescending(a => a.Id).Limit(1000).ToList();
|
||||
var sql = g.pgsql.Insert(items).InsertIdentity().NoneParameter().ToSql();
|
||||
g.pgsql.Update<TopicPgCopy>().SetSource(items).ExecutePgCopy();
|
||||
g.pgsql.Update<TopicPgCopy>().SetSource(items, a => new { a.Id, a.Clicks }).ExecutePgCopy();
|
||||
g.pgsql.Update<TopicPgCopy>().SetSource(items).UpdateColumns(a => new { a.Title }).ExecutePgCopy();
|
||||
g.pgsql.Update<TopicPgCopy>().SetSource(items, a => new { a.Id, a.Clicks }).UpdateColumns(a => new { a.Title }).ExecutePgCopy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsTable()
|
||||
{
|
||||
|
@ -227,12 +227,19 @@ namespace FreeSql.Tests.SqlServer
|
||||
[Fact]
|
||||
public void ExecuteSqlBulkCopy()
|
||||
{
|
||||
var maxId = g.pgsql.Select<Topic>().Max(a => a.Id);
|
||||
var items = new List<Topic>();
|
||||
for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now });
|
||||
for (var a = 0; a < 10; a++) items.Add(new Topic { Id = maxId + a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now });
|
||||
|
||||
insert.AppendData(items).InsertIdentity().ExecuteSqlBulkCopy();
|
||||
//insert.AppendData(items).IgnoreColumns(a => new { a.CreateTime, a.Clicks }).ExecuteSqlBulkCopy();
|
||||
// System.NotSupportedException:“DataSet does not support System.Nullable<>.”
|
||||
|
||||
items = g.sqlserver.Select<Topic>().OrderByDescending(a => a.Id).Limit(1000).ToList();
|
||||
g.sqlserver.Update<Topic>().SetSource(items).ExecuteSqlBulkCopy();
|
||||
g.sqlserver.Update<Topic>().SetSource(items, a => new { a.Id, a.TypeGuid }).ExecuteSqlBulkCopy();
|
||||
g.sqlserver.Update<Topic>().SetSource(items).UpdateColumns(a => new { a.Title }).ExecuteSqlBulkCopy();
|
||||
g.sqlserver.Update<Topic>().SetSource(items, a => new { a.Id, a.TypeGuid }).UpdateColumns(a => new { a.Title }).ExecuteSqlBulkCopy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -896,7 +896,7 @@ SELECT ");
|
||||
static void LocalReplaceDictDBNullValue(Dictionary<string, object> dict)
|
||||
{
|
||||
if (dict == null) return;
|
||||
var keys = dict.Keys;
|
||||
var keys = dict.Keys.ToArray();
|
||||
foreach (var key in keys)
|
||||
{
|
||||
var val = dict[key];
|
||||
|
@ -17,7 +17,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1336,7 +1336,7 @@
|
||||
</summary>
|
||||
<param name="dataType">数据库类型</param>
|
||||
<param name="connectionString">数据库连接串</param>
|
||||
<param name="providerType">提供者的类型,一般不需要指定,如果一直提示“缺少 FreeSql 数据库实现包:FreeSql.Provider.MySql.dll,可前往 nuget 下载”的错误,说明反射获取不到类型,此时该参数可排上用场</param>
|
||||
<param name="providerType">提供者的类型,一般不需要指定,如果一直提示“缺少 FreeSql 数据库实现包:FreeSql.Provider.MySql.dll,可前往 nuget 下载”的错误,说明反射获取不到类型,此时该参数可排上用场<para></para>例如:typeof(FreeSql.SqlServer.SqlServerProvider<>)</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.FreeSqlBuilder.UseSlave(System.String[])">
|
||||
@ -1352,7 +1352,7 @@
|
||||
</summary>
|
||||
<param name="dataType">数据库类型</param>
|
||||
<param name="connectionFactory">数据库连接对象创建器</param>
|
||||
<param name="providerType">提供者的类型,一般不需要指定,如果一直提示“缺少 FreeSql 数据库实现包:FreeSql.Provider.MySql.dll,可前往 nuget 下载”的错误,说明反射获取不到类型,此时该参数可排上用场</param>
|
||||
<param name="providerType">提供者的类型,一般不需要指定,如果一直提示“缺少 FreeSql 数据库实现包:FreeSql.Provider.MySql.dll,可前往 nuget 下载”的错误,说明反射获取不到类型,此时该参数可排上用场<para></para>例如:typeof(FreeSql.SqlServer.SqlServerProvider<>)</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.FreeSqlBuilder.UseAutoSyncStructure(System.Boolean)">
|
||||
@ -1413,6 +1413,15 @@
|
||||
<param name="convertType"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.FreeSqlBuilder.UseQuoteSqlName(System.Boolean)">
|
||||
<summary>
|
||||
SQL名称是否使用 [] `` ""<para></para>
|
||||
true: SELECT .. FROM [table]<para></para>
|
||||
false: SELECT .. FROM table
|
||||
</summary>
|
||||
<param name="value"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.FreeSqlBuilder.UseMappingPriority(FreeSql.Internal.MappingPriorityType,FreeSql.Internal.MappingPriorityType,FreeSql.Internal.MappingPriorityType)">
|
||||
<summary>
|
||||
指定映射优先级<para></para>
|
||||
@ -1439,29 +1448,6 @@
|
||||
<param name="value"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.FreeSqlBuilder.UseSyncStructureToLower(System.Boolean)">
|
||||
<summary>
|
||||
转小写同步结构
|
||||
</summary>
|
||||
<param name="value">true:转小写, false:不转</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.FreeSqlBuilder.UseSyncStructureToUpper(System.Boolean)">
|
||||
<summary>
|
||||
转大写同步结构
|
||||
</summary>
|
||||
<param name="value">true:转大写, false:不转</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.FreeSqlBuilder.UseEntityPropertyNameConvert(FreeSql.Internal.StringConvertType)">
|
||||
<summary>
|
||||
自动转换实体属性名称 Entity Property -> Db Filed
|
||||
<para></para>
|
||||
*不会覆盖 [Column] 特性设置的Name
|
||||
</summary>
|
||||
<param name="convertType"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.IDelete`1.WithTransaction(System.Data.Common.DbTransaction)">
|
||||
<summary>
|
||||
指定事务对象
|
||||
@ -4174,46 +4160,6 @@
|
||||
BigApple -> bigapple
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:FreeSql.Internal.StringConvertType.None">
|
||||
<summary>
|
||||
不进行任何处理
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:FreeSql.Internal.StringConvertType.PascalCaseToUnderscore">
|
||||
<summary>
|
||||
将帕斯卡命名字符串转换为下划线分隔字符串
|
||||
<para></para>
|
||||
BigApple -> Big_Apple
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:FreeSql.Internal.StringConvertType.PascalCaseToUnderscoreWithUpper">
|
||||
<summary>
|
||||
将帕斯卡命名字符串转换为下划线分隔字符串,且转换为全大写
|
||||
<para></para>
|
||||
BigApple -> BIG_APPLE
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:FreeSql.Internal.StringConvertType.PascalCaseToUnderscoreWithLower">
|
||||
<summary>
|
||||
将帕斯卡命名字符串转换为下划线分隔字符串,且转换为全小写
|
||||
<para></para>
|
||||
BigApple -> big_apple
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:FreeSql.Internal.StringConvertType.Upper">
|
||||
<summary>
|
||||
将字符串转换为大写
|
||||
<para></para>
|
||||
BigApple -> BIGAPPLE
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:FreeSql.Internal.StringConvertType.Lower">
|
||||
<summary>
|
||||
将字符串转换为小写
|
||||
<para></para>
|
||||
BigApple -> bigapple
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:FreeSql.Internal.GlobalFilter.Apply``1(System.String,System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
|
||||
<summary>
|
||||
创建一个过滤器<para></para>
|
||||
|
@ -18,15 +18,13 @@ namespace FreeSql
|
||||
int[] _slaveWeights;
|
||||
Func<DbConnection> _connectionFactory;
|
||||
bool _isAutoSyncStructure = false;
|
||||
bool _isSyncStructureToLower = false;
|
||||
bool _isSyncStructureToUpper = false;
|
||||
bool _isConfigEntityFromDbFirst = false;
|
||||
bool _isNoneCommandParameter = false;
|
||||
bool _isGenerateCommandParameterWithLambda = false;
|
||||
bool _isLazyLoading = false;
|
||||
bool _isExitAutoDisposePool = true;
|
||||
bool _isQuoteSqlName = true;
|
||||
MappingPriorityType[] _mappingPriorityTypes;
|
||||
StringConvertType _entityPropertyConvertType = StringConvertType.None;
|
||||
NameConvertType _nameConvertType = NameConvertType.None;
|
||||
Action<DbCommand> _aopCommandExecuting = null;
|
||||
Action<DbCommand, string> _aopCommandExecuted = null;
|
||||
@ -37,7 +35,7 @@ namespace FreeSql
|
||||
/// </summary>
|
||||
/// <param name="dataType">数据库类型</param>
|
||||
/// <param name="connectionString">数据库连接串</param>
|
||||
/// <param name="providerType">提供者的类型,一般不需要指定,如果一直提示“缺少 FreeSql 数据库实现包:FreeSql.Provider.MySql.dll,可前往 nuget 下载”的错误,说明反射获取不到类型,此时该参数可排上用场</param>
|
||||
/// <param name="providerType">提供者的类型,一般不需要指定,如果一直提示“缺少 FreeSql 数据库实现包:FreeSql.Provider.MySql.dll,可前往 nuget 下载”的错误,说明反射获取不到类型,此时该参数可排上用场<para></para>例如:typeof(FreeSql.SqlServer.SqlServerProvider<>)</param>
|
||||
/// <returns></returns>
|
||||
public FreeSqlBuilder UseConnectionString(DataType dataType, string connectionString, Type providerType = null)
|
||||
{
|
||||
@ -69,7 +67,7 @@ namespace FreeSql
|
||||
/// </summary>
|
||||
/// <param name="dataType">数据库类型</param>
|
||||
/// <param name="connectionFactory">数据库连接对象创建器</param>
|
||||
/// <param name="providerType">提供者的类型,一般不需要指定,如果一直提示“缺少 FreeSql 数据库实现包:FreeSql.Provider.MySql.dll,可前往 nuget 下载”的错误,说明反射获取不到类型,此时该参数可排上用场</param>
|
||||
/// <param name="providerType">提供者的类型,一般不需要指定,如果一直提示“缺少 FreeSql 数据库实现包:FreeSql.Provider.MySql.dll,可前往 nuget 下载”的错误,说明反射获取不到类型,此时该参数可排上用场<para></para>例如:typeof(FreeSql.SqlServer.SqlServerProvider<>)</param>
|
||||
/// <returns></returns>
|
||||
public FreeSqlBuilder UseConnectionFactory(DataType dataType, Func<DbConnection> connectionFactory, Type providerType = null)
|
||||
{
|
||||
@ -161,6 +159,18 @@ namespace FreeSql
|
||||
_nameConvertType = convertType;
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// SQL名称是否使用 [] `` ""<para></para>
|
||||
/// true: SELECT .. FROM [table]<para></para>
|
||||
/// false: SELECT .. FROM table
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public FreeSqlBuilder UseQuoteSqlName(bool value)
|
||||
{
|
||||
_isQuoteSqlName = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定映射优先级<para></para>
|
||||
@ -337,8 +347,6 @@ namespace FreeSql
|
||||
{
|
||||
ret.CodeFirst.IsAutoSyncStructure = _isAutoSyncStructure;
|
||||
|
||||
ret.CodeFirst.IsSyncStructureToLower = _isSyncStructureToLower;
|
||||
ret.CodeFirst.IsSyncStructureToUpper = _isSyncStructureToUpper;
|
||||
ret.CodeFirst.IsConfigEntityFromDbFirst = _isConfigEntityFromDbFirst;
|
||||
ret.CodeFirst.IsNoneCommandParameter = _isNoneCommandParameter;
|
||||
ret.CodeFirst.IsGenerateCommandParameterWithLambda = _isGenerateCommandParameterWithLambda;
|
||||
@ -352,7 +360,6 @@ namespace FreeSql
|
||||
if (_aopCommandExecuted != null)
|
||||
ret.Aop.CommandAfter += new EventHandler<Aop.CommandAfterEventArgs>((s, e) => _aopCommandExecuted?.Invoke(e.Command, e.Log));
|
||||
|
||||
this.EntityPropertyNameConvert(ret);
|
||||
//添加实体属性名全局AOP转换处理
|
||||
if (_nameConvertType != NameConvertType.None)
|
||||
{
|
||||
@ -517,6 +524,8 @@ namespace FreeSql
|
||||
if (_slaveWeights != null)
|
||||
for (var x = 0; x < _slaveWeights.Length; x++)
|
||||
ret.Ado.SlavePools[x].Policy.Weight = _slaveWeights[x];
|
||||
|
||||
(ret.Select<object>() as Select0Provider)._commonUtils.IsQuoteSqlName = _isQuoteSqlName;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -1,80 +0,0 @@
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using FreeSql.DataAnnotations;
|
||||
using FreeSql.Internal;
|
||||
|
||||
namespace FreeSql
|
||||
{
|
||||
partial class FreeSqlBuilder
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 转小写同步结构
|
||||
/// </summary>
|
||||
/// <param name="value">true:转小写, false:不转</param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("请使用 UseNameConvert(NameConvertType.ToLower),或者 fsql.CodeFirst.IsSyncStructureToLower = value")]
|
||||
public FreeSqlBuilder UseSyncStructureToLower(bool value)
|
||||
{
|
||||
_isSyncStructureToLower = value;
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// 转大写同步结构
|
||||
/// </summary>
|
||||
/// <param name="value">true:转大写, false:不转</param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("请使用 UseNameConvert(NameConvertType.ToUpper),或者 fsql.CodeFirst.IsSyncStructureToUpper = value")]
|
||||
public FreeSqlBuilder UseSyncStructureToUpper(bool value)
|
||||
{
|
||||
_isSyncStructureToUpper = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自动转换实体属性名称 Entity Property -> Db Filed
|
||||
/// <para></para>
|
||||
/// *不会覆盖 [Column] 特性设置的Name
|
||||
/// </summary>
|
||||
/// <param name="convertType"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("请使用 UseNameConvert 功能")]
|
||||
public FreeSqlBuilder UseEntityPropertyNameConvert(StringConvertType convertType)
|
||||
{
|
||||
_entityPropertyConvertType = convertType;
|
||||
return this;
|
||||
}
|
||||
|
||||
void EntityPropertyNameConvert(IFreeSql fsql)
|
||||
{
|
||||
//添加实体属性名全局AOP转换处理
|
||||
if (_entityPropertyConvertType != StringConvertType.None)
|
||||
{
|
||||
string PascalCaseToUnderScore(string str) => string.IsNullOrWhiteSpace(str) ? str : string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x.ToString() : x.ToString()));
|
||||
|
||||
switch (_entityPropertyConvertType)
|
||||
{
|
||||
case StringConvertType.Lower:
|
||||
fsql.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = e.ModifyResult.Name?.ToLower();
|
||||
break;
|
||||
case StringConvertType.Upper:
|
||||
fsql.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = e.ModifyResult.Name?.ToUpper();
|
||||
break;
|
||||
case StringConvertType.PascalCaseToUnderscore:
|
||||
fsql.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.ModifyResult.Name);
|
||||
break;
|
||||
case StringConvertType.PascalCaseToUnderscoreWithLower:
|
||||
fsql.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.ModifyResult.Name)?.ToLower();
|
||||
break;
|
||||
case StringConvertType.PascalCaseToUnderscoreWithUpper:
|
||||
fsql.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = PascalCaseToUnderScore(e.ModifyResult.Name)?.ToUpper();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ public static class FreeUtil
|
||||
{
|
||||
|
||||
private static DateTime dt1970 = new DateTime(1970, 1, 1);
|
||||
private static ThreadLocal<Random> rnd = new ThreadLocal<Random>(() => new Random());
|
||||
internal static ThreadLocal<Random> rnd = new ThreadLocal<Random>(() => new Random());
|
||||
private static readonly int __staticMachine = ((0x00ffffff & Environment.MachineName.GetHashCode()) +
|
||||
#if NETSTANDARD1_5 || NETSTANDARD1_6
|
||||
1
|
||||
|
@ -277,15 +277,23 @@ namespace FreeSql.Internal
|
||||
return false;
|
||||
}
|
||||
if (parent.CsType == null) parent.CsType = exp.Type;
|
||||
var pdbfield = parent.DbField = ExpressionLambdaToSql(exp, getTSC());
|
||||
if (parent.MapType == null || _tables?.Any(a => a.Table?.IsRereadSql == true) == true)
|
||||
try
|
||||
{
|
||||
var findcol = SearchColumnByField(_tables, null, parent.DbField);
|
||||
if (parent.MapType == null) parent.MapType = findcol?.Attribute.MapType ?? exp.Type;
|
||||
if (findcol != null) pdbfield = _common.RereadColumn(findcol, pdbfield);
|
||||
var pdbfield = parent.DbField = ExpressionLambdaToSql(exp, getTSC());
|
||||
if (parent.MapType == null || _tables?.Any(a => a.Table?.IsRereadSql == true) == true)
|
||||
{
|
||||
var findcol = SearchColumnByField(_tables, null, parent.DbField);
|
||||
if (parent.MapType == null) parent.MapType = findcol?.Attribute.MapType ?? exp.Type;
|
||||
if (findcol != null) pdbfield = _common.RereadColumn(findcol, pdbfield);
|
||||
}
|
||||
field.Append(", ").Append(pdbfield);
|
||||
LocalSetFieldAlias(ref index, _tables != null ||
|
||||
SelectGroupingProvider._ParseExpOnlyDbField.Value != pdbfield);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SelectGroupingProvider._ParseExpOnlyDbField.Value = null;
|
||||
}
|
||||
field.Append(", ").Append(pdbfield);
|
||||
LocalSetFieldAlias(ref index, true);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
@ -923,7 +931,16 @@ namespace FreeSql.Internal
|
||||
return $"not({ExpressionLambdaToSql(notExp, tsc)})";
|
||||
case ExpressionType.Quote: return ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, tsc);
|
||||
case ExpressionType.Lambda: return ExpressionLambdaToSql((exp as LambdaExpression)?.Body, tsc);
|
||||
case ExpressionType.Invoke: return formatSql(Expression.Lambda(exp).Compile().DynamicInvoke(), tsc.mapType, tsc.mapColumnTmp, tsc.dbParams);
|
||||
//case ExpressionType.Invoke: return formatSql(Expression.Lambda(exp).Compile().DynamicInvoke(), tsc.mapType, tsc.mapColumnTmp, tsc.dbParams);
|
||||
case ExpressionType.Invoke:
|
||||
var invokeExp = exp as InvocationExpression;
|
||||
var invokeReplaceVistor = new FreeSql.Internal.CommonExpression.ReplaceVisitor();
|
||||
var invokeReplaceExp = invokeExp.Expression;
|
||||
var invokeLambdaExp = invokeReplaceExp as LambdaExpression;
|
||||
var len = Math.Min(invokeExp.Arguments.Count, invokeLambdaExp.Parameters.Count);
|
||||
for (var a = 0; a < len; a++)
|
||||
invokeReplaceExp = invokeReplaceVistor.Modify(invokeReplaceExp, invokeLambdaExp.Parameters[a], invokeExp.Arguments[a]);
|
||||
return ExpressionLambdaToSql(invokeReplaceExp, tsc);
|
||||
case ExpressionType.TypeAs:
|
||||
case ExpressionType.Convert:
|
||||
case ExpressionType.ConvertChecked:
|
||||
|
@ -33,7 +33,6 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public CommonUtils _util { get; set; }
|
||||
protected int slaveUnavailables = 0;
|
||||
private object slaveLock = new object();
|
||||
private Random slaveRandom = new Random();
|
||||
protected Func<DbTransaction> ResolveTransaction;
|
||||
|
||||
public AdoProvider(DataType dataType, string connectionString, string[] slaveConnectionStrings)
|
||||
@ -52,7 +51,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
TimeSpan ts = DateTime.Now.Subtract(dt);
|
||||
if (ex == null && ts.TotalMilliseconds > 100)
|
||||
Trace.WriteLine(logtxt.Insert(0, $"{pool?.Policy.Name}(执行SQL)语句耗时过长{ts.TotalMilliseconds}ms\r\n{cmd.CommandText}\r\n").ToString());
|
||||
logtxt.Insert(0, $"{pool?.Policy.Name}(执行SQL)语句耗时过长{ts.TotalMilliseconds}ms\r\n{cmd.CommandText}\r\n").ToString();
|
||||
else
|
||||
logtxt.Insert(0, $"{pool?.Policy.Name}(执行SQL)耗时{ts.TotalMilliseconds}ms\r\n{cmd.CommandText}\r\n").ToString();
|
||||
}
|
||||
@ -69,7 +68,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
log.Append(parm.ParameterName.PadRight(20, ' ')).Append(" = ").Append((parm.Value ?? DBNull.Value) == DBNull.Value ? "NULL" : parm.Value).Append("\r\n");
|
||||
|
||||
log.Append(ex.Message);
|
||||
Trace.WriteLine(log.ToString());
|
||||
//Trace.WriteLine(log.ToString());
|
||||
|
||||
if (cmd.Transaction != null)
|
||||
{
|
||||
@ -152,6 +151,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -195,6 +195,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -212,6 +213,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -263,6 +265,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -280,6 +283,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -297,6 +301,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -354,6 +359,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -371,6 +377,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -388,6 +395,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -405,6 +413,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -468,6 +477,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -485,6 +495,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -502,6 +513,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -519,6 +531,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -536,6 +549,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -584,7 +598,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
if (availables.Count == 1) pool = availables[0];
|
||||
else
|
||||
{
|
||||
var rnd = slaveRandom.Next(availables.Sum(a => a.Policy.Weight));
|
||||
var rnd = FreeUtil.rnd.Value.Next(availables.Sum(a => a.Policy.Weight));
|
||||
for(var a = 0; a < availables.Count; a++)
|
||||
{
|
||||
rnd -= availables[a].Policy.Weight;
|
||||
@ -601,6 +615,14 @@ namespace FreeSql.Internal.CommonProvider
|
||||
|
||||
Object<DbConnection> conn = null;
|
||||
var pc = PrepareCommand(connection, transaction, cmdType, cmdText, cmdTimeout, cmdParms, logtxt);
|
||||
if (string.IsNullOrEmpty(pc.cmd.CommandText)) //被拦截 CommandBefore
|
||||
{
|
||||
LoggerException(pool, pc, null, dt, logtxt);
|
||||
pc.cmd.Parameters.Clear();
|
||||
if (DataType == DataType.Sqlite) pc.cmd.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsTracePerformance)
|
||||
{
|
||||
logtxt.Append("PrepareCommand: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
|
||||
@ -785,8 +807,11 @@ namespace FreeSql.Internal.CommonProvider
|
||||
Exception ex = null;
|
||||
try
|
||||
{
|
||||
if (pc.cmd.Connection == null) pc.cmd.Connection = (conn = this.MasterPool.Get()).Value;
|
||||
val = pc.cmd.ExecuteNonQuery();
|
||||
if (string.IsNullOrEmpty(pc.cmd.CommandText) == false) //是否被拦截 CommandBefore
|
||||
{
|
||||
if (pc.cmd.Connection == null) pc.cmd.Connection = (conn = this.MasterPool.Get()).Value;
|
||||
val = pc.cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
@ -821,8 +846,11 @@ namespace FreeSql.Internal.CommonProvider
|
||||
Exception ex = null;
|
||||
try
|
||||
{
|
||||
if (pc.cmd.Connection == null) pc.cmd.Connection = (conn = this.MasterPool.Get()).Value;
|
||||
val = pc.cmd.ExecuteScalar();
|
||||
if (string.IsNullOrEmpty(pc.cmd.CommandText) == false) //是否被拦截 CommandBefore
|
||||
{
|
||||
if (pc.cmd.Connection == null) pc.cmd.Connection = (conn = this.MasterPool.Get()).Value;
|
||||
val = pc.cmd.ExecuteScalar();
|
||||
}
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
|
@ -67,6 +67,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -111,6 +112,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -128,6 +130,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -180,6 +183,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -197,6 +201,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -214,6 +219,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -272,6 +278,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -289,6 +296,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -306,6 +314,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -323,6 +332,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -387,6 +397,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -404,6 +415,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -421,6 +433,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -438,6 +451,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -455,6 +469,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
for (var a = 0; a < fetch.Object.FieldCount; a++)
|
||||
{
|
||||
var name = fetch.Object.GetName(a);
|
||||
if (DataType == DataType.ClickHouse && name.Contains(".")) name = name.Substring(name.IndexOf('.') + 1);
|
||||
if (dic.ContainsKey(name)) continue;
|
||||
sbflag.Append(name).Append(":").Append(a).Append(",");
|
||||
dic.Add(name, a);
|
||||
@ -501,13 +516,34 @@ namespace FreeSql.Internal.CommonProvider
|
||||
if (availables.Any())
|
||||
{
|
||||
isSlave = true;
|
||||
pool = availables.Count == 1 ? this.SlavePools[0] : availables[slaveRandom.Next(availables.Count)];
|
||||
if (availables.Count == 1) pool = availables[0];
|
||||
else
|
||||
{
|
||||
var rnd = FreeUtil.rnd.Value.Next(availables.Sum(a => a.Policy.Weight));
|
||||
for (var a = 0; a < availables.Count; a++)
|
||||
{
|
||||
rnd -= availables[a].Policy.Weight;
|
||||
if (rnd < 0)
|
||||
{
|
||||
pool = availables[a];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object<DbConnection> conn = null;
|
||||
var pc = await PrepareCommandAsync(connection, transaction, cmdType, cmdText, cmdTimeout, cmdParms, logtxt, cancellationToken);
|
||||
if (string.IsNullOrEmpty(pc.cmd.CommandText)) //被拦截 CommandBefore
|
||||
{
|
||||
LoggerException(pool, pc, null, dt, logtxt);
|
||||
pc.cmd.Parameters.Clear();
|
||||
if (DataType == DataType.Sqlite) pc.cmd.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsTracePerformance)
|
||||
{
|
||||
logtxt.Append("PrepareCommand: ").Append(DateTime.Now.Subtract(logtxt_dt).TotalMilliseconds).Append("ms Total: ").Append(DateTime.Now.Subtract(dt).TotalMilliseconds).Append("ms\r\n");
|
||||
@ -690,8 +726,11 @@ namespace FreeSql.Internal.CommonProvider
|
||||
Exception ex = null;
|
||||
try
|
||||
{
|
||||
if (pc.cmd.Connection == null) pc.cmd.Connection = (conn = await this.MasterPool.GetAsync()).Value;
|
||||
val = await pc.cmd.ExecuteNonQueryAsync(cancellationToken);
|
||||
if (string.IsNullOrEmpty(pc.cmd.CommandText) == false) //是否被拦截 CommandBefore
|
||||
{
|
||||
if (pc.cmd.Connection == null) pc.cmd.Connection = (conn = await this.MasterPool.GetAsync()).Value;
|
||||
val = await pc.cmd.ExecuteNonQueryAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
@ -726,8 +765,11 @@ namespace FreeSql.Internal.CommonProvider
|
||||
Exception ex = null;
|
||||
try
|
||||
{
|
||||
if (pc.cmd.Connection == null) pc.cmd.Connection = (conn = await this.MasterPool.GetAsync()).Value;
|
||||
val = await pc.cmd.ExecuteScalarAsync(cancellationToken);
|
||||
if (string.IsNullOrEmpty(pc.cmd.CommandText) == false) //是否被拦截 CommandBefore
|
||||
{
|
||||
if (pc.cmd.Connection == null) pc.cmd.Connection = (conn = await this.MasterPool.GetAsync()).Value;
|
||||
val = await pc.cmd.ExecuteScalarAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
|
@ -53,7 +53,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine($"数据库出错(开启事务){ex.Message} \r\n{ex.StackTrace}");
|
||||
//Trace.WriteLine($"数据库出错(开启事务){ex.Message} \r\n{ex.StackTrace}");
|
||||
MasterPool.Return(conn);
|
||||
var after = new Aop.TraceAfterEventArgs(before, "", ex);
|
||||
_util?._orm?.Aop.TraceAfterHandler?.Invoke(this, after);
|
||||
@ -83,7 +83,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
if (tran.Transaction.Connection != null) //用户自行 Commit、Rollback
|
||||
{
|
||||
Trace.WriteLine($"线程{tran.Connection.LastGetThreadId}事务{remark}");
|
||||
//Trace.WriteLine($"线程{tran.Connection.LastGetThreadId}事务{remark}");
|
||||
if (isCommit) tran.Transaction.Commit();
|
||||
else tran.Transaction.Rollback();
|
||||
}
|
||||
@ -91,7 +91,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
catch (Exception ex2)
|
||||
{
|
||||
ex = ex2;
|
||||
Trace.WriteLine($"数据库出错({remark}事务):{ex.Message} {ex.StackTrace}");
|
||||
//Trace.WriteLine($"数据库出错({remark}事务):{ex.Message} {ex.StackTrace}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -25,6 +25,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public DbConnection _connection;
|
||||
public int _commandTimeout = 0;
|
||||
public Action<StringBuilder> _interceptSql;
|
||||
public bool _isAutoSyncStructure;
|
||||
}
|
||||
|
||||
public abstract partial class DeleteProvider<T1> : DeleteProvider, IDelete<T1>
|
||||
@ -35,8 +36,9 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_commonUtils = commonUtils;
|
||||
_commonExpression = commonExpression;
|
||||
_table = _commonUtils.GetTableByEntity(typeof(T1));
|
||||
_isAutoSyncStructure = _orm.CodeFirst.IsAutoSyncStructure;
|
||||
this.Where(_commonUtils.WhereObject(_table, "", dywhere));
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure<T1>();
|
||||
if (_isAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure<T1>();
|
||||
_whereGlobalFilter = _orm.GlobalFilter.GetFilters();
|
||||
}
|
||||
|
||||
@ -51,7 +53,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public IDelete<T1> WithTransaction(DbTransaction transaction)
|
||||
{
|
||||
_transaction = transaction;
|
||||
_connection = _transaction?.Connection;
|
||||
if (transaction != null) _connection = transaction.Connection;
|
||||
return this;
|
||||
}
|
||||
public IDelete<T1> WithConnection(DbConnection connection)
|
||||
@ -145,7 +147,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
if (string.IsNullOrEmpty(newname)) return _table.DbName;
|
||||
if (_orm.CodeFirst.IsSyncStructureToLower) newname = newname.ToLower();
|
||||
if (_orm.CodeFirst.IsSyncStructureToUpper) newname = newname.ToUpper();
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table.Type, newname);
|
||||
if (_isAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table.Type, newname);
|
||||
return newname;
|
||||
}
|
||||
public IDelete<T1> AsTable(Func<string, string> tableRule)
|
||||
@ -164,7 +166,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
if (entityType == _table.Type) return this;
|
||||
var newtb = _commonUtils.GetTableByEntity(entityType);
|
||||
_table = newtb ?? throw new Exception(CoreStrings.Type_AsType_Parameter_Error("IDelete"));
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType);
|
||||
if (_isAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public IInsertOrUpdate<T1> WithTransaction(DbTransaction transaction)
|
||||
{
|
||||
_transaction = transaction;
|
||||
_connection = _transaction?.Connection;
|
||||
if (transaction != null) _connection = transaction.Connection;
|
||||
return this;
|
||||
}
|
||||
public IInsertOrUpdate<T1> WithConnection(DbConnection connection)
|
||||
@ -290,6 +290,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public abstract string ToSql();
|
||||
public int ExecuteAffrows()
|
||||
{
|
||||
if (_sourceSql != null) return this.RawExecuteAffrows();
|
||||
var affrows = 0;
|
||||
var ss = SplitSourceByIdentityValueIsNull(_source);
|
||||
try
|
||||
@ -408,6 +409,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
}
|
||||
async public Task<int> ExecuteAffrowsAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (_sourceSql != null) return this.RawExecuteAffrows();
|
||||
var affrows = 0;
|
||||
var ss = SplitSourceByIdentityValueIsNull(_source);
|
||||
try
|
||||
|
@ -31,6 +31,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public DbTransaction _transaction;
|
||||
public DbConnection _connection;
|
||||
public int _commandTimeout = 0;
|
||||
public bool _isAutoSyncStructure;
|
||||
}
|
||||
|
||||
public abstract partial class InsertProvider<T1> : InsertProvider, IInsert<T1> where T1 : class
|
||||
@ -46,7 +47,8 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_commonExpression = commonExpression;
|
||||
_table = _commonUtils.GetTableByEntity(typeof(T1));
|
||||
_noneParameter = _orm.CodeFirst.IsNoneCommandParameter;
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure<T1>();
|
||||
_isAutoSyncStructure = _orm.CodeFirst.IsAutoSyncStructure;
|
||||
if (_isAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure<T1>();
|
||||
IgnoreCanInsert();
|
||||
_sourceOld = _source;
|
||||
}
|
||||
@ -78,7 +80,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public IInsert<T1> WithTransaction(DbTransaction transaction)
|
||||
{
|
||||
_transaction = transaction;
|
||||
_connection = _transaction?.Connection;
|
||||
if (transaction != null) _connection = transaction.Connection;
|
||||
return this;
|
||||
}
|
||||
public IInsert<T1> WithConnection(DbConnection connection)
|
||||
@ -568,7 +570,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
if (string.IsNullOrEmpty(newname)) return tbname;
|
||||
if (_orm.CodeFirst.IsSyncStructureToLower) newname = newname.ToLower();
|
||||
if (_orm.CodeFirst.IsSyncStructureToUpper) newname = newname.ToUpper();
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table?.Type, newname);
|
||||
if (_isAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table?.Type, newname);
|
||||
return newname;
|
||||
}
|
||||
public IInsert<T1> AsTable(Func<string, string> tableRule)
|
||||
@ -588,7 +590,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
if (entityType == _table.Type) return this;
|
||||
var newtb = _commonUtils.GetTableByEntity(entityType);
|
||||
_table = newtb ?? throw new Exception(CoreStrings.Type_AsType_Parameter_Error("IInsert"));
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType);
|
||||
if (_isAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType);
|
||||
IgnoreCanInsert();
|
||||
return this;
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public Func<bool> _cancel;
|
||||
public bool _is_AsTreeCte;
|
||||
public BaseDiyMemberExpression _diymemexpWithTempQuery;
|
||||
public Func<DbTransaction> _resolveHookTransaction;
|
||||
|
||||
public bool IsDefaultSqlContent => _distinct == false && _is_AsTreeCte == false && _tables.Count == 1 && _where.Length == 0 && _join.Length == 0 &&
|
||||
string.IsNullOrWhiteSpace(_orderby) && string.IsNullOrWhiteSpace(_groupby) && string.IsNullOrWhiteSpace(_tosqlAppendContent) &&
|
||||
@ -557,7 +558,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public TSelect WithTransaction(DbTransaction transaction)
|
||||
{
|
||||
_transaction = transaction;
|
||||
_connection = _transaction?.Connection;
|
||||
if (transaction != null) _connection = transaction.Connection;
|
||||
return this as TSelect;
|
||||
}
|
||||
public TSelect WithConnection(DbConnection connection)
|
||||
@ -1187,8 +1188,9 @@ namespace FreeSql.Internal.CommonProvider
|
||||
}
|
||||
public TSelect ForUpdate(bool noawait = false)
|
||||
{
|
||||
if (_transaction == null && _orm.Ado.TransactionCurrentThread == null)
|
||||
throw new Exception($"{CoreStrings.Begin_Transaction_Then_ForUpdate}");
|
||||
if (_transaction == null && _orm.Ado.TransactionCurrentThread != null) this.WithTransaction(_orm.Ado.TransactionCurrentThread);
|
||||
if (_transaction == null && _resolveHookTransaction != null) this.WithTransaction(_resolveHookTransaction());
|
||||
if (_transaction == null) throw new Exception($"{CoreStrings.Begin_Transaction_Then_ForUpdate}");
|
||||
switch (_orm.Ado.DataType)
|
||||
{
|
||||
case DataType.MySql:
|
||||
|
@ -31,6 +31,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_tables = tables;
|
||||
}
|
||||
|
||||
public static ThreadLocal<string> _ParseExpOnlyDbField = new ThreadLocal<string>();
|
||||
public override string ParseExp(Expression[] members)
|
||||
{
|
||||
ParseExpMapResult = null;
|
||||
@ -52,7 +53,11 @@ namespace FreeSql.Internal.CommonProvider
|
||||
}
|
||||
ParseExpMapResult = read;
|
||||
if (!_addFieldAlias) return read.DbField;
|
||||
if (_comonExp.EndsWithDbNestedField(read.DbField, read.DbNestedField) == false) return $"{read.DbField}{_comonExp._common.FieldAsAlias(read.DbNestedField)}";
|
||||
if (_comonExp.EndsWithDbNestedField(read.DbField, read.DbNestedField) == false)
|
||||
{
|
||||
_ParseExpOnlyDbField.Value = read.DbField;
|
||||
return $"{read.DbField}{_comonExp._common.FieldAsAlias(read.DbNestedField)}";
|
||||
}
|
||||
return read.DbField;
|
||||
case "Value":
|
||||
var curtables = _tables;
|
||||
|
@ -1,5 +1,6 @@
|
||||
using FreeSql.Extensions.EntityUtil;
|
||||
using FreeSql.Internal.Model;
|
||||
using FreeSql.Internal.ObjectPool;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
@ -37,6 +38,96 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public int _commandTimeout = 0;
|
||||
public Action<StringBuilder> _interceptSql;
|
||||
public object _updateVersionValue;
|
||||
public bool _isAutoSyncStructure;
|
||||
|
||||
|
||||
public static int ExecuteBulkUpdate<T1>(UpdateProvider<T1> update, NativeTuple<string, string, string, string, string[]> state, Action<IInsert<T1>> funcBulkCopy) where T1 : class
|
||||
{
|
||||
if (update._source.Any() != true || update._tempPrimarys.Any() == false) return 0;
|
||||
var fsql = update._orm;
|
||||
var connection = update._connection;
|
||||
var transaction = update._transaction;
|
||||
|
||||
Object<DbConnection> poolConn = null;
|
||||
if (connection == null)
|
||||
{
|
||||
poolConn = fsql.Ado.MasterPool.Get();
|
||||
connection = poolConn.Value;
|
||||
}
|
||||
try
|
||||
{
|
||||
var droped = false;
|
||||
fsql.Ado.CommandFluent(state.Item1).WithConnection(connection).WithTransaction(transaction).ExecuteNonQuery();
|
||||
try
|
||||
{
|
||||
var insert = fsql.Insert<T1>(update._source)
|
||||
.AsType(update._table.Type)
|
||||
.WithConnection(connection)
|
||||
.WithTransaction(transaction)
|
||||
.InsertIdentity()
|
||||
.InsertColumns(state.Item5)
|
||||
.AsTable(state.Item4);
|
||||
(insert as InsertProvider)._isAutoSyncStructure = false;
|
||||
funcBulkCopy(insert);
|
||||
var affrows = fsql.Ado.CommandFluent(state.Item2 + ";\r\n" + state.Item3).WithConnection(connection).WithTransaction(transaction).ExecuteNonQuery();
|
||||
droped = true;
|
||||
return affrows;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (droped == false) fsql.Ado.CommandFluent(state.Item3).WithConnection(connection).WithTransaction(transaction).ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
poolConn?.Dispose();
|
||||
}
|
||||
}
|
||||
#if net40
|
||||
#else
|
||||
async public static Task<int> ExecuteBulkUpdateAsync<T1>(UpdateProvider<T1> update, NativeTuple<string, string, string, string, string[]> state, Func<IInsert<T1>, Task> funcBulkCopy) where T1 : class
|
||||
{
|
||||
if (update._source.Any() != true || update._tempPrimarys.Any() == false) return 0;
|
||||
var fsql = update._orm;
|
||||
var connection = update._connection;
|
||||
var transaction = update._transaction;
|
||||
|
||||
Object<DbConnection> poolConn = null;
|
||||
if (connection == null)
|
||||
{
|
||||
poolConn = await fsql.Ado.MasterPool.GetAsync();
|
||||
connection = poolConn.Value;
|
||||
}
|
||||
try
|
||||
{
|
||||
var droped = false;
|
||||
await fsql.Ado.CommandFluent(state.Item1).WithConnection(connection).WithTransaction(transaction).ExecuteNonQueryAsync();
|
||||
try
|
||||
{
|
||||
var insert = fsql.Insert<T1>(update._source)
|
||||
.AsType(update._table.Type)
|
||||
.WithConnection(connection)
|
||||
.WithTransaction(transaction)
|
||||
.InsertIdentity()
|
||||
.InsertColumns(state.Item5)
|
||||
.AsTable(state.Item4);
|
||||
(insert as InsertProvider)._isAutoSyncStructure = false;
|
||||
await funcBulkCopy(insert);
|
||||
var affrows = await fsql.Ado.CommandFluent(state.Item2 + ";\r\n" + state.Item3).WithConnection(connection).WithTransaction(transaction).ExecuteNonQueryAsync();
|
||||
droped = true;
|
||||
return affrows;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (droped == false) await fsql.Ado.CommandFluent(state.Item3).WithConnection(connection).WithTransaction(transaction).ExecuteNonQueryAsync();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
poolConn?.Dispose();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public abstract partial class UpdateProvider<T1> : UpdateProvider, IUpdate<T1>
|
||||
@ -54,8 +145,9 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_tempPrimarys = _table?.Primarys ?? new ColumnInfo[0];
|
||||
_versionColumn = _table?.VersionColumn;
|
||||
_noneParameter = _orm.CodeFirst.IsNoneCommandParameter;
|
||||
_isAutoSyncStructure = _orm.CodeFirst.IsAutoSyncStructure;
|
||||
this.Where(_commonUtils.WhereObject(_table, "", dywhere));
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure<T1>();
|
||||
if (_isAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure<T1>();
|
||||
IgnoreCanUpdate();
|
||||
_whereGlobalFilter = _orm.GlobalFilter.GetFilters();
|
||||
_sourceOld = _source;
|
||||
@ -95,7 +187,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public IUpdate<T1> WithTransaction(DbTransaction transaction)
|
||||
{
|
||||
_transaction = transaction;
|
||||
_connection = _transaction?.Connection;
|
||||
if (transaction != null) _connection = transaction.Connection;
|
||||
return this;
|
||||
}
|
||||
public IUpdate<T1> WithConnection(DbConnection connection)
|
||||
@ -797,7 +889,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
if (string.IsNullOrEmpty(newname)) return _table.DbName;
|
||||
if (_orm.CodeFirst.IsSyncStructureToLower) newname = newname.ToLower();
|
||||
if (_orm.CodeFirst.IsSyncStructureToUpper) newname = newname.ToUpper();
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table.Type, newname);
|
||||
if (_isAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table.Type, newname);
|
||||
return newname;
|
||||
}
|
||||
public IUpdate<T1> AsTable(Func<string, string> tableRule)
|
||||
@ -818,7 +910,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_table = newtb ?? throw new Exception(CoreStrings.Type_AsType_Parameter_Error("IUpdate"));
|
||||
_tempPrimarys = _table.Primarys;
|
||||
_versionColumn = _ignoreVersion ? null : _table.VersionColumn;
|
||||
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType);
|
||||
if (_isAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType);
|
||||
IgnoreCanUpdate();
|
||||
return this;
|
||||
}
|
||||
|
@ -28,7 +28,14 @@ namespace FreeSql.Internal
|
||||
public abstract DbParameter AppendParamter(List<DbParameter> _params, string parameterName, ColumnInfo col, Type type, object value);
|
||||
public abstract DbParameter[] GetDbParamtersByObject(string sql, object obj);
|
||||
public abstract string FormatSql(string sql, params object[] args);
|
||||
public abstract string QuoteSqlName(params string[] name);
|
||||
|
||||
public bool IsQuoteSqlName = true;
|
||||
public string QuoteSqlName(params string[] name) {
|
||||
if (IsQuoteSqlName) return QuoteSqlNameAdapter(name);
|
||||
if (name == null) return "";
|
||||
return string.Join(".", name);
|
||||
}
|
||||
public abstract string QuoteSqlNameAdapter(params string[] name);
|
||||
public abstract string TrimQuoteSqlName(string name);
|
||||
public abstract string[] SplitTableName(string name);
|
||||
public static string[] GetSplitTableNames(string name, char leftQuote, char rightQuote, int size)
|
||||
|
@ -79,47 +79,4 @@ namespace FreeSql.Internal
|
||||
ToLower
|
||||
}
|
||||
|
||||
public enum StringConvertType
|
||||
{
|
||||
/// <summary>
|
||||
/// 不进行任何处理
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 将帕斯卡命名字符串转换为下划线分隔字符串
|
||||
/// <para></para>
|
||||
/// BigApple -> Big_Apple
|
||||
/// </summary>
|
||||
PascalCaseToUnderscore,
|
||||
|
||||
/// <summary>
|
||||
/// 将帕斯卡命名字符串转换为下划线分隔字符串,且转换为全大写
|
||||
/// <para></para>
|
||||
/// BigApple -> BIG_APPLE
|
||||
/// </summary>
|
||||
PascalCaseToUnderscoreWithUpper,
|
||||
|
||||
/// <summary>
|
||||
/// 将帕斯卡命名字符串转换为下划线分隔字符串,且转换为全小写
|
||||
/// <para></para>
|
||||
/// BigApple -> big_apple
|
||||
/// </summary>
|
||||
PascalCaseToUnderscoreWithLower,
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转换为大写
|
||||
/// <para></para>
|
||||
/// BigApple -> BIGAPPLE
|
||||
/// </summary>
|
||||
Upper,
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转换为小写
|
||||
/// <para></para>
|
||||
/// BigApple -> bigapple
|
||||
/// </summary>
|
||||
Lower
|
||||
}
|
||||
|
||||
}
|
@ -250,6 +250,29 @@ namespace FreeSql.Internal.ObjectPool
|
||||
catch { }
|
||||
}
|
||||
|
||||
public void AutoFree()
|
||||
{
|
||||
if (running == false) return;
|
||||
if (UnavailableException != null) return;
|
||||
|
||||
var list = new List<Object<T>>();
|
||||
while (_freeObjects.TryPop(out var obj))
|
||||
list.Add(obj);
|
||||
foreach (var obj in list)
|
||||
{
|
||||
if (obj != null && obj.Value == null ||
|
||||
obj != null && Policy.IdleTimeout > TimeSpan.Zero && DateTime.Now.Subtract(obj.LastReturnTime) > Policy.IdleTimeout)
|
||||
{
|
||||
if (obj.Value != null)
|
||||
{
|
||||
Return(obj, true);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Return(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取可用资源,或创建资源
|
||||
/// </summary>
|
||||
|
@ -516,7 +516,9 @@ namespace FreeSql.Internal
|
||||
foreach (var col in trytb.Primarys)
|
||||
{
|
||||
col.Attribute.IsNullable = false;
|
||||
col.Attribute.DbType = col.Attribute.DbType.Replace("NOT NULL", "").Replace(" NULL", "").Trim() + " NOT NULL"; //sqlite 主键也可以插入 null
|
||||
col.Attribute.DbType = col.Attribute.DbType.Replace("NOT NULL", "").Replace(" NULL", "").Trim();
|
||||
if (common._orm.Ado.DataType == DataType.Sqlite)
|
||||
col.Attribute.DbType += " NOT NULL"; //sqlite 主键也可以插入 null
|
||||
}
|
||||
foreach (var col in trytb.Columns.Values)
|
||||
{
|
||||
@ -1544,6 +1546,13 @@ namespace FreeSql.Internal
|
||||
case DataType.GBase:
|
||||
if (dr.IsDBNull(index)) return null;
|
||||
break;
|
||||
case DataType.MySql:
|
||||
if (dr.GetFieldType(index).FullName == "MySqlConnector.MySqlDateTime")
|
||||
{
|
||||
if (dr.IsDBNull(index)) return null;
|
||||
return dr.GetDateTime(index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return dr.GetValue(index);
|
||||
}
|
||||
|
@ -12,43 +12,76 @@ using ClickHouse.Client.ADO;
|
||||
|
||||
namespace FreeSql.ClickHouse
|
||||
{
|
||||
|
||||
class ClickHouseCodeFirst : Internal.CommonProvider.CodeFirstProvider
|
||||
{
|
||||
public ClickHouseCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) : base(orm,
|
||||
commonUtils, commonExpression)
|
||||
{
|
||||
}
|
||||
|
||||
public ClickHouseCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) : base(orm, commonUtils, commonExpression) { }
|
||||
|
||||
static object _dicCsToDbLock = new object();
|
||||
|
||||
static Dictionary<string, CsToDb<DbType>> _dicCsToDb = new Dictionary<string, CsToDb<DbType>>() {
|
||||
{ typeof(bool).FullName, CsToDb.New(DbType.SByte, "Int8","Int8", null, false, false) },{ typeof(bool?).FullName, CsToDb.New(DbType.SByte, "Int8","Nullable(Int8)", null, true, null) },
|
||||
|
||||
{ typeof(sbyte).FullName, CsToDb.New(DbType.SByte, "Int8", "Int8", false, false, 0) },{ typeof(sbyte?).FullName, CsToDb.New(DbType.SByte, "Int8", "Nullable(Int8)", false, true, null) },
|
||||
{ typeof(short).FullName, CsToDb.New(DbType.Int16, "Int16","Int16", false, false, 0) },{ typeof(short?).FullName, CsToDb.New(DbType.Int16, "Int16", "Nullable(Int16)", false, true, null) },
|
||||
{ typeof(int).FullName, CsToDb.New(DbType.Int32, "Int32", "Int32", false, false, 0) },{ typeof(int?).FullName, CsToDb.New(DbType.Int32, "Int32", "Nullable(Int32)", false, true, null) },
|
||||
{ typeof(long).FullName, CsToDb.New(DbType.Int64, "Int64","Int64", false, false, 0) },{ typeof(long?).FullName, CsToDb.New(DbType.Int64, "Int64","Nullable(Int64)", false, true, null) },
|
||||
|
||||
{ typeof(byte).FullName, CsToDb.New(DbType.Byte, "UInt8","UInt8", true, false, 0) },{ typeof(byte?).FullName, CsToDb.New(DbType.Byte, "UInt8","Nullable(UInt8)", true, true, null) },
|
||||
{ typeof(ushort).FullName, CsToDb.New(DbType.UInt16, "UInt16","UInt16", true, false, 0) },{ typeof(ushort?).FullName, CsToDb.New(DbType.UInt16, "UInt16", "Nullable(UInt16)", true, true, null) },
|
||||
{ typeof(uint).FullName, CsToDb.New(DbType.UInt32, "UInt32", "UInt32", true, false, 0) },{ typeof(uint?).FullName, CsToDb.New(DbType.UInt32, "UInt32", "Nullable(UInt32)", true, true, null) },
|
||||
{ typeof(ulong).FullName, CsToDb.New(DbType.UInt64, "UInt64", "UInt64", true, false, 0) },{ typeof(ulong?).FullName, CsToDb.New(DbType.UInt64, "UInt64", "Nullable(UInt64)", true, true, null) },
|
||||
static Dictionary<string, CsToDb<DbType>> _dicCsToDb = new Dictionary<string, CsToDb<DbType>>()
|
||||
{
|
||||
{ typeof(bool).FullName, CsToDb.New(DbType.SByte, "Int8", "Int8", null, false, false) },
|
||||
{ typeof(bool?).FullName, CsToDb.New(DbType.SByte, "Int8", "Nullable(Int8)", null, true, null) },
|
||||
|
||||
{ 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(sbyte).FullName, CsToDb.New(DbType.SByte, "Int8", "Int8", false, false, 0) },
|
||||
{ typeof(sbyte?).FullName, CsToDb.New(DbType.SByte, "Int8", "Nullable(Int8)", false, true, null) },
|
||||
{ typeof(short).FullName, CsToDb.New(DbType.Int16, "Int16", "Int16", false, false, 0) },
|
||||
{ typeof(short?).FullName, CsToDb.New(DbType.Int16, "Int16", "Nullable(Int16)", false, true, null) },
|
||||
{ typeof(int).FullName, CsToDb.New(DbType.Int32, "Int32", "Int32", false, false, 0) },
|
||||
{ typeof(int?).FullName, CsToDb.New(DbType.Int32, "Int32", "Nullable(Int32)", false, true, null) },
|
||||
{ typeof(long).FullName, CsToDb.New(DbType.Int64, "Int64", "Int64", false, false, 0) },
|
||||
{ typeof(long?).FullName, CsToDb.New(DbType.Int64, "Int64", "Nullable(Int64)", 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) },
|
||||
{ typeof(byte).FullName, CsToDb.New(DbType.Byte, "UInt8", "UInt8", true, false, 0) },
|
||||
{ typeof(byte?).FullName, CsToDb.New(DbType.Byte, "UInt8", "Nullable(UInt8)", true, true, null) },
|
||||
{ typeof(ushort).FullName, CsToDb.New(DbType.UInt16, "UInt16", "UInt16", true, false, 0) },
|
||||
{ typeof(ushort?).FullName, CsToDb.New(DbType.UInt16, "UInt16", "Nullable(UInt16)", true, true, null) },
|
||||
{ typeof(uint).FullName, CsToDb.New(DbType.UInt32, "UInt32", "UInt32", true, false, 0) },
|
||||
{ typeof(uint?).FullName, CsToDb.New(DbType.UInt32, "UInt32", "Nullable(UInt32)", true, true, null) },
|
||||
{ typeof(ulong).FullName, CsToDb.New(DbType.UInt64, "UInt64", "UInt64", true, false, 0) },
|
||||
{ typeof(ulong?).FullName, CsToDb.New(DbType.UInt64, "UInt64", "Nullable(UInt64)", true, true, null) },
|
||||
|
||||
{ typeof(string).FullName, CsToDb.New(DbType.String, "String", "String", false, null, "") },
|
||||
{ typeof(char).FullName, CsToDb.New(DbType.String, "String", "String", false, false, "") },{ typeof(char?).FullName, CsToDb.New(DbType.Single, "String","Nullable(String)", false, true, null) },
|
||||
{ typeof(Guid).FullName, CsToDb.New(DbType.String, "String", "String", false, false, Guid.Empty) },{ typeof(Guid?).FullName, CsToDb.New(DbType.String, "String", "Nullable(String)", false, true, null) },
|
||||
{ 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, "Decimal(38, 19)", "Decimal(38, 19)", false, false, 0) //Nullable(Decimal(38, 19))
|
||||
},
|
||||
{
|
||||
typeof(decimal?).FullName,
|
||||
CsToDb.New(DbType.Decimal, "Nullable(Decimal(38, 19))", "Nullable(Decimal(38, 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)
|
||||
},
|
||||
|
||||
{ typeof(string).FullName, CsToDb.New(DbType.String, "String", "String", false, null, "") },
|
||||
{ typeof(char).FullName, CsToDb.New(DbType.String, "String", "String", false, false, "") },
|
||||
{ typeof(char?).FullName, CsToDb.New(DbType.Single, "String", "Nullable(String)", false, true, null) },
|
||||
{ typeof(Guid).FullName, CsToDb.New(DbType.String, "String", "String", false, false, Guid.Empty) },
|
||||
{ typeof(Guid?).FullName, CsToDb.New(DbType.String, "String", "Nullable(String)", false, true, null) },
|
||||
};
|
||||
|
||||
public override DbInfoResult GetDbInfo(Type type)
|
||||
{
|
||||
if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new DbInfoResult((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue);
|
||||
if (type.IsArray) return null;
|
||||
if (_dicCsToDb.TryGetValue(type.FullName, out var trydc))
|
||||
return new DbInfoResult((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable,
|
||||
trydc.defaultValue);
|
||||
if (type.IsArray)
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -56,7 +89,7 @@ namespace FreeSql.ClickHouse
|
||||
{
|
||||
Object<DbConnection> conn = null;
|
||||
string database = null;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5));
|
||||
@ -65,19 +98,25 @@ namespace FreeSql.ClickHouse
|
||||
var sb = new StringBuilder();
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
if (sb.Length > 0) sb.Append("\r\n");
|
||||
if (sb.Length > 0)
|
||||
sb.Append("\r\n");
|
||||
var tb = _commonUtils.GetTableByEntity(obj.entityType);
|
||||
if (tb == null) throw new Exception(CoreStrings.S_Type_IsNot_Migrable(obj.entityType.FullName));
|
||||
if (tb.Columns.Any() == false) throw new Exception(CoreStrings.S_Type_IsNot_Migrable_0Attributes(obj.entityType.FullName));
|
||||
if (tb == null)
|
||||
throw new Exception(CoreStrings.S_Type_IsNot_Migrable(obj.entityType.FullName));
|
||||
if (tb.Columns.Any() == false)
|
||||
throw new Exception(CoreStrings.S_Type_IsNot_Migrable_0Attributes(obj.entityType.FullName));
|
||||
var tbname = _commonUtils.SplitTableName(tb.DbName);
|
||||
if (tbname?.Length == 1) tbname = new[] { database, tbname[0] };
|
||||
if (tbname?.Length == 1)
|
||||
tbname = new[] { database, tbname[0] };
|
||||
|
||||
var tboldname = _commonUtils.SplitTableName(tb.DbOldName); //旧表名
|
||||
if (tboldname?.Length == 1) tboldname = new[] { database, tboldname[0] };
|
||||
if (tboldname?.Length == 1)
|
||||
tboldname = new[] { database, tboldname[0] };
|
||||
if (string.IsNullOrEmpty(obj.tableName) == false)
|
||||
{
|
||||
var tbtmpname = _commonUtils.SplitTableName(obj.tableName);
|
||||
if (tbtmpname?.Length == 1) tbtmpname = new[] { database, tbtmpname[0] };
|
||||
if (tbtmpname?.Length == 1)
|
||||
tbtmpname = new[] { database, tbtmpname[0] };
|
||||
if (tbname[0] != tbtmpname[0] || tbname[1] != tbtmpname[1])
|
||||
{
|
||||
tbname = tbtmpname;
|
||||
@ -85,20 +124,32 @@ namespace FreeSql.ClickHouse
|
||||
}
|
||||
}
|
||||
|
||||
if (string.Compare(tbname[0], database, true) != 0 && LocalExecuteScalar(database, _commonUtils.FormatSql(" select 1 from system.databases d where name={0}", tbname[0])) == null) //创建数据库
|
||||
sb.Append($"CREATE DATABASE IF NOT EXISTS ").Append(_commonUtils.QuoteSqlName(tbname[0])).Append(" ENGINE=Ordinary;\r\n");
|
||||
if (string.Compare(tbname[0], database, true) != 0 && LocalExecuteScalar(database,
|
||||
_commonUtils.FormatSql(" select 1 from system.databases d where name={0}", tbname[0])) ==
|
||||
null) //创建数据库
|
||||
sb.Append($"CREATE DATABASE IF NOT EXISTS ").Append(_commonUtils.QuoteSqlName(tbname[0]))
|
||||
.Append(" ENGINE=Ordinary;\r\n");
|
||||
|
||||
var sbalter = new StringBuilder();
|
||||
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
|
||||
if (LocalExecuteScalar(tbname[0], _commonUtils.FormatSql(" SELECT 1 FROM system.tables t WHERE database ={0} and name ={1}", tbname)) == null)
|
||||
{ //表不存在
|
||||
if (LocalExecuteScalar(tbname[0],
|
||||
_commonUtils.FormatSql(" SELECT 1 FROM system.tables t WHERE database ={0} and name ={1}",
|
||||
tbname)) == null)
|
||||
{
|
||||
//表不存在
|
||||
if (tboldname != null)
|
||||
{
|
||||
if (string.Compare(tboldname[0], tbname[0], true) != 0 && LocalExecuteScalar(database, _commonUtils.FormatSql(" select 1 from system.databases where name={0}", tboldname[0])) == null ||
|
||||
LocalExecuteScalar(tboldname[0], _commonUtils.FormatSql(" SELECT 1 FROM system.tables WHERE database={0} and name={1}", tboldname)) == null)
|
||||
if (string.Compare(tboldname[0], tbname[0], true) != 0 && LocalExecuteScalar(database,
|
||||
_commonUtils.FormatSql(" select 1 from system.databases where name={0}",
|
||||
tboldname[0])) == null ||
|
||||
LocalExecuteScalar(tboldname[0],
|
||||
_commonUtils.FormatSql(
|
||||
" SELECT 1 FROM system.tables WHERE database={0} and name={1}", tboldname)) ==
|
||||
null)
|
||||
//数据库或表不存在
|
||||
tboldname = null;
|
||||
}
|
||||
|
||||
if (tboldname == null)
|
||||
{
|
||||
//创建表
|
||||
@ -106,33 +157,44 @@ namespace FreeSql.ClickHouse
|
||||
sb.Append("CREATE TABLE IF NOT EXISTS ").Append(createTableName).Append(" ( ");
|
||||
foreach (var tbcol in tb.ColumnsByPosition)
|
||||
{
|
||||
tbcol.Attribute.DbType = tbcol.Attribute.DbType.Replace(" NOT NULL", "");
|
||||
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType);
|
||||
if (string.IsNullOrEmpty(tbcol.Comment) == false) sb.Append(" COMMENT ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment));
|
||||
//如果这里是主键就是不为Nullable
|
||||
tbcol.Attribute.DbType =
|
||||
CkNullableAdapter(tbcol.Attribute.DbType, tbcol.Attribute.IsPrimary);
|
||||
tbcol.Attribute.DbType = CkIntAdapter(tbcol.Attribute.DbType);
|
||||
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ")
|
||||
.Append(tbcol.Attribute.DbType);
|
||||
if (string.IsNullOrEmpty(tbcol.Comment) == false)
|
||||
sb.Append(" COMMENT ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment));
|
||||
sb.Append(",");
|
||||
}
|
||||
|
||||
foreach (var uk in tb.Indexes)
|
||||
{
|
||||
sb.Append(" \r\n ");
|
||||
sb.Append("INDEX ").Append(_commonUtils.QuoteSqlName(ReplaceIndexName(uk.Name, tbname[1])));
|
||||
sb.Append("INDEX ")
|
||||
.Append(_commonUtils.QuoteSqlName(ReplaceIndexName(uk.Name, tbname[1])));
|
||||
|
||||
sb.Append(" (");
|
||||
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(", ");
|
||||
}
|
||||
sb.Remove(sb.Length - 2, 2);
|
||||
|
||||
sb.Remove(sb.Length - 2, 2).Append(") ");
|
||||
sb.Append("TYPE set(8192) GRANULARITY 5,");
|
||||
}
|
||||
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
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(", ");
|
||||
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(" )");
|
||||
@ -140,15 +202,20 @@ namespace FreeSql.ClickHouse
|
||||
sb.Append(ls);
|
||||
sb.Remove(sb.Length - 2, 2).Append(",");
|
||||
}
|
||||
|
||||
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");
|
||||
continue;
|
||||
}
|
||||
|
||||
//如果新表,旧表在一个数据库下,直接修改表名
|
||||
if (string.Compare(tbname[0], tboldname[0], true) == 0)
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName(tboldname[0], tboldname[1])).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName(tbname[0], tbname[1])).Append(";\r\n");
|
||||
sbalter.Append("RENAME TABLE ")
|
||||
.Append(_commonUtils.QuoteSqlName(tboldname[0], tboldname[1]))
|
||||
.Append(" TO ").Append(_commonUtils.QuoteSqlName(tbname[0], tbname[1]))
|
||||
.Append(";\r\n");
|
||||
else
|
||||
{
|
||||
//如果新表,旧表不在一起,创建新表,导入数据,删除旧表
|
||||
@ -178,64 +245,162 @@ where a.database in ({0}) and a.table in ({1})", tboldname ?? tbname);
|
||||
{
|
||||
column = string.Concat(a[0]),
|
||||
sqlType = (string)a[1],
|
||||
is_nullable = string.Concat(a[2]) == "1",
|
||||
is_nullable = a[1]?.ToString().Contains("Nullable"),
|
||||
is_identity = false,
|
||||
comment = string.Concat(a[3]),
|
||||
is_primary= string.Concat(a[6]) == "1",
|
||||
is_primary = string.Concat(a[6]) == "1",
|
||||
};
|
||||
}, StringComparer.CurrentCultureIgnoreCase);
|
||||
|
||||
|
||||
if (istmpatler == false)
|
||||
{
|
||||
var existsPrimary = tbstruct.Any(o => o.Value.is_primary);
|
||||
//对比列
|
||||
foreach (var tbcol in tb.ColumnsByPosition)
|
||||
{
|
||||
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
|
||||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol))
|
||||
//表中有这个字段
|
||||
var condition1 = tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol);
|
||||
var condition2 = string.IsNullOrEmpty(tbcol.Attribute.OldName) == false;
|
||||
if (condition1 ||
|
||||
condition2 && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol))
|
||||
{
|
||||
var isCommentChanged = tbstructcol.comment != (tbcol.Comment ?? "");
|
||||
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false ||
|
||||
tbcol.Attribute.IsNullable != tbstructcol.is_nullable || isCommentChanged)
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(tbcol.Attribute.IsNullable ? $"Nullable({tbcol.Attribute.DbType.Split(' ').First()})":tbcol.Attribute.DbType.Split(' ').First()).Append(";\r\n");
|
||||
if(isCommentChanged) sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" COMMENT COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(_commonUtils.FormatSql("{0}", tbcol.Comment ?? "")).Append(";\r\n");
|
||||
var ckDbType = CkNullableAdapter(tbcol.Attribute.DbType, tbcol.Attribute.IsPrimary);
|
||||
ckDbType = CkIntAdapter(ckDbType);
|
||||
var typeCondition1 = RemoveSpaceComparison(tbstructcol.sqlType, ckDbType) == false;
|
||||
var typeCondition2 = tbcol.Attribute.IsNullable != tbstructcol.is_nullable;
|
||||
if (typeCondition1 || typeCondition1 || isCommentChanged)
|
||||
{
|
||||
sbalter.Append("ALTER TABLE ")
|
||||
.Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}"))
|
||||
.Append(" MODIFY COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column))
|
||||
.Append(tbcol.Attribute.IsNullable &&
|
||||
tbcol.Attribute.DbType.Contains("Nullable") == false
|
||||
? $"Nullable({tbcol.Attribute.DbType.Split(' ').First()})"
|
||||
: tbcol.Attribute.DbType.Split(' ').First())
|
||||
.Append(";\r\n");
|
||||
}
|
||||
|
||||
if (isCommentChanged)
|
||||
sbalter.Append("ALTER TABLE ")
|
||||
.Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}"))
|
||||
.Append(" COMMENT COLUMN ")
|
||||
.Append(_commonUtils.QuoteSqlName(tbstructcol.column))
|
||||
.Append(_commonUtils.FormatSql("{0}", tbcol.Comment ?? "")).Append(";\r\n");
|
||||
if (string.Compare(tbstructcol.column, tbcol.Attribute.OldName, true) == 0)
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(";\r\n");
|
||||
sbalter.Append("ALTER TABLE ")
|
||||
.Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}"))
|
||||
.Append(" RENAME COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column))
|
||||
.Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name))
|
||||
.Append(";\r\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
//添加列
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName(tbname[0], tbname[1])).Append(" ADD ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType);
|
||||
if (tbcol.Attribute.IsNullable == false && tbcol.DbDefaultValue != "NULL" && tbcol.Attribute.IsIdentity == false) sbalter.Append(" DEFAULT ").Append(tbcol.DbDefaultValue);
|
||||
if (string.IsNullOrEmpty(tbcol.Comment) == false) sbalter.Append(" COMMENT ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment ?? ""));
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName(tbname[0], tbname[1]))
|
||||
.Append(" ADD Column ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ")
|
||||
.Append(tbcol.Attribute.DbType);
|
||||
if (tbcol.Attribute.IsNullable == false && tbcol.DbDefaultValue != "NULL" &&
|
||||
tbcol.Attribute.IsIdentity == false)
|
||||
sbalter.Append(" DEFAULT ").Append(tbcol.DbDefaultValue);
|
||||
if (string.IsNullOrEmpty(tbcol.Comment) == false)
|
||||
sbalter.Append(" COMMENT ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment ?? ""));
|
||||
sbalter.Append(";\r\n");
|
||||
}
|
||||
|
||||
var indexSelectSql = _commonUtils.FormatSql(
|
||||
@"SELECT name,expr FROM system.data_skipping_indices WHERE database={0}",
|
||||
tboldname ?? tbname);
|
||||
var indexCollect = _orm.Ado.Query<ClickHouseTableIndex>(CommandType.Text, indexSelectSql);
|
||||
//对比索引
|
||||
foreach (var uk in tb.Indexes)
|
||||
{
|
||||
if (string.IsNullOrEmpty(uk.Name) || uk.Columns.Any() == false)
|
||||
continue;
|
||||
var ukname = ReplaceIndexName(uk.Name, tbname[1]);
|
||||
//先判断表中有没此字段的索引
|
||||
if (indexCollect.Any(c =>
|
||||
RemoveSpaceComparison(c.expr,
|
||||
string.Join(',', uk.Columns.Select(i => i.Column.CsName)))))
|
||||
{
|
||||
//有这个字段的索引,但是名称不一样 修改名 , ClickHouse不支持修改列
|
||||
//if (!indexCollect.Where(c => c.name == uk.Name).Any())
|
||||
//{
|
||||
//
|
||||
// sbalter.Append("ALTER TABLE ")
|
||||
// .Append(_commonUtils.QuoteSqlName(tbname[0], tbname[1]))
|
||||
// .Append(" DROP INDEX ").Append(ukname).Append(" ").Append(";\r\n");
|
||||
|
||||
// //添加
|
||||
// sbalter.Append("ALTER TABLE ")
|
||||
// .Append(_commonUtils.QuoteSqlName(tbname[0], tbname[1]))
|
||||
// .Append(" ADD INDEX ").Append(ukname).Append(" (");
|
||||
// foreach (var tbcol in uk.Columns)
|
||||
// {
|
||||
// sbalter.Append(_commonUtils.QuoteSqlName(tbcol.Column.Attribute.Name));
|
||||
// sbalter.Append(", ");
|
||||
// }
|
||||
|
||||
// sbalter.Remove(sbalter.Length - 2, 2).Append(") TYPE set(8192) GRANULARITY 5")
|
||||
// .Append(";\r\n");
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
//创建索引
|
||||
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName(tbname[0], tbname[1]))
|
||||
.Append(" ADD INDEX ").Append(ukname).Append(" (");
|
||||
foreach (var tbcol in uk.Columns)
|
||||
{
|
||||
sbalter.Append(_commonUtils.QuoteSqlName(tbcol.Column.Attribute.Name));
|
||||
sbalter.Append(", ");
|
||||
}
|
||||
|
||||
sbalter.Remove(sbalter.Length - 2, 2).Append(") TYPE set(8192) GRANULARITY 5")
|
||||
.Append(";\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (istmpatler == false)
|
||||
{
|
||||
sb.Append(sbalter);
|
||||
Console.WriteLine(sb.ToString());
|
||||
continue;
|
||||
}
|
||||
|
||||
//创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名
|
||||
var tablename = tboldname == null ? _commonUtils.QuoteSqlName(tbname[0], tbname[1]) : _commonUtils.QuoteSqlName(tboldname[0], tboldname[1]);
|
||||
var tablename = tboldname == null
|
||||
? _commonUtils.QuoteSqlName(tbname[0], tbname[1])
|
||||
: _commonUtils.QuoteSqlName(tboldname[0], tboldname[1]);
|
||||
var tmptablename = _commonUtils.QuoteSqlName(tbname[0], $"FreeSqlTmp_{tbname[1]}");
|
||||
//创建临时表
|
||||
sb.Append("CREATE TABLE IF NOT EXISTS ").Append(tmptablename).Append(" ( ");
|
||||
foreach (var tbcol in tb.ColumnsByPosition)
|
||||
{
|
||||
tbcol.Attribute.DbType = tbcol.Attribute.DbType.Replace(" NOT NULL", "");
|
||||
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType);
|
||||
if (string.IsNullOrEmpty(tbcol.Comment) == false) sb.Append(" COMMENT ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment));
|
||||
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ")
|
||||
.Append(tbcol.Attribute.DbType);
|
||||
if (string.IsNullOrEmpty(tbcol.Comment) == false)
|
||||
sb.Append(" COMMENT ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment));
|
||||
sb.Append(",");
|
||||
}
|
||||
|
||||
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])))
|
||||
.Append("(");
|
||||
foreach (var tbcol in uk.Columns)
|
||||
{
|
||||
sb.Append(_commonUtils.QuoteSqlName(tbcol.Column.Attribute.Name));
|
||||
sb.Append("TYPE set(8192) GRANULARITY 5, ");
|
||||
}
|
||||
|
||||
sb.Remove(sb.Length - 2, 2).Append("),");
|
||||
}
|
||||
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
sb.Append("\r\n) ");
|
||||
sb.Append("\r\nENGINE = MergeTree()");
|
||||
@ -244,7 +409,8 @@ where a.database in ({0}) and a.table in ({1})", tboldname ?? tbname);
|
||||
{
|
||||
sb.Append(" \r\nORDER BY ( ");
|
||||
var ls = new StringBuilder();
|
||||
foreach (var tbcol in tb.Primarys) ls.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
|
||||
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(" )");
|
||||
@ -252,6 +418,7 @@ where a.database in ({0}) and a.table in ({1})", tboldname ?? tbname);
|
||||
sb.Append(ls);
|
||||
sb.Remove(sb.Length - 2, 2).Append(",");
|
||||
}
|
||||
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
//if (string.IsNullOrEmpty(tb.Comment) == false)
|
||||
// sb.Append(" Comment=").Append(_commonUtils.FormatSql("{0}", tb.Comment));
|
||||
@ -262,25 +429,32 @@ where a.database in ({0}) and a.table in ({1})", tboldname ?? tbname);
|
||||
{
|
||||
var insertvalue = "NULL";
|
||||
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
|
||||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol))
|
||||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false &&
|
||||
tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol))
|
||||
{
|
||||
insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column);
|
||||
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false)
|
||||
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType,
|
||||
StringComparison.CurrentCultureIgnoreCase) == false)
|
||||
{
|
||||
//insertvalue = $"cast({insertvalue} as {tbcol.Attribute.DbType.Split(' ').First()})";
|
||||
}
|
||||
|
||||
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable)
|
||||
insertvalue = $"ifnull({insertvalue},{tbcol.DbDefaultValue})";
|
||||
}
|
||||
else if (tbcol.Attribute.IsNullable == false)
|
||||
if (tbcol.DbDefaultValue != "NULL")
|
||||
insertvalue = tbcol.DbDefaultValue;
|
||||
|
||||
sb.Append(insertvalue).Append(", ");
|
||||
}
|
||||
|
||||
sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append(";\r\n");
|
||||
sb.Append("DROP TABLE ").Append(tablename).Append(";\r\n");
|
||||
sb.Append("RENAME TABLE ").Append(tmptablename).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbname[0], tbname[1])).Append(";\r\n");
|
||||
sb.Append("RENAME TABLE ").Append(tmptablename).Append(" TO ")
|
||||
.Append(_commonUtils.QuoteSqlName(tbname[0], tbname[1])).Append(";\r\n");
|
||||
}
|
||||
|
||||
return sb.Length == 0 ? null : sb.ToString();
|
||||
}
|
||||
finally
|
||||
@ -299,7 +473,8 @@ where a.database in ({0}) and a.table in ({1})", tboldname ?? tbname);
|
||||
|
||||
object LocalExecuteScalar(string db, string sql)
|
||||
{
|
||||
if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db);
|
||||
if (string.Compare(database, db) != 0)
|
||||
conn.Value.ChangeDatabase(db);
|
||||
try
|
||||
{
|
||||
using (var cmd = conn.Value.CreateCommand())
|
||||
@ -311,17 +486,72 @@ where a.database in ({0}) and a.table in ({1})", tboldname ?? tbname);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database);
|
||||
if (string.Compare(database, db) != 0)
|
||||
conn.Value.ChangeDatabase(database);
|
||||
}
|
||||
}
|
||||
|
||||
string CkNullablePrimaryAdapter(string dbType, bool isPrimary)
|
||||
{
|
||||
return isPrimary
|
||||
? dbType.Replace("Nullable(", "").Replace(")", "")
|
||||
: dbType.Replace(" NOT NULL", "");
|
||||
}
|
||||
string CkNullableAdapter(string dbType, bool isPrimary)
|
||||
{
|
||||
return isPrimary
|
||||
? dbType.Replace("Nullable(", "").Replace(")","").Replace(" NOT NULL", "")
|
||||
: dbType.Replace(" NOT NULL", "");
|
||||
}
|
||||
|
||||
|
||||
string CkIntAdapter(string dbType)
|
||||
{
|
||||
var result = dbType;
|
||||
if (dbType.ToLower().Contains("int64"))
|
||||
{
|
||||
if (dbType.Contains("Nullable"))
|
||||
{
|
||||
result = "Nullable(Int64)";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = "Int64";
|
||||
}
|
||||
}
|
||||
else if (dbType.ToLower().Contains("int"))
|
||||
{
|
||||
if (dbType.Contains("Nullable"))
|
||||
{
|
||||
result = "Nullable(Int32)";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = "Int32";
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//去除空格后比较
|
||||
bool RemoveSpaceComparison(string a, string b)
|
||||
{
|
||||
a = Regex.Replace(a, @"\s", "").ToLower();
|
||||
b = Regex.Replace(b, @"\s", "").ToLower();
|
||||
return a == b;
|
||||
}
|
||||
}
|
||||
|
||||
public override int ExecuteDDLStatements(string ddl)
|
||||
{
|
||||
if (string.IsNullOrEmpty(ddl)) return 0;
|
||||
var scripts = ddl.Split(new string[] { ";\r\n" }, StringSplitOptions.None).Where(a => string.IsNullOrEmpty(a.Trim()) == false).ToArray();
|
||||
if (string.IsNullOrEmpty(ddl))
|
||||
return 0;
|
||||
var scripts = ddl.Split(new string[] { ";\r\n" }, StringSplitOptions.None)
|
||||
.Where(a => string.IsNullOrEmpty(a.Trim()) == false).ToArray();
|
||||
|
||||
if (scripts.Any() == false) return 0;
|
||||
if (scripts.Any() == false)
|
||||
return 0;
|
||||
|
||||
var affrows = 0;
|
||||
foreach (var script in scripts)
|
||||
@ -329,4 +559,16 @@ where a.database in ({0}) and a.table in ({1})", tboldname ?? tbname);
|
||||
return affrows;
|
||||
}
|
||||
}
|
||||
|
||||
internal class ClickHouseTableIndex
|
||||
{
|
||||
public string name
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string expr
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
}
|
@ -79,7 +79,7 @@ namespace FreeSql.ClickHouse
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatClickHouse(args);
|
||||
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -46,7 +46,7 @@ namespace FreeSql.ClickHouse.Curd
|
||||
//如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1
|
||||
for (var b = 1; b < tbsfrom.Length; b++)
|
||||
{
|
||||
sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[b].Table.Type, tbsfrom[b].Alias) ?? tbsfrom[b].Alias);
|
||||
sb.Append(" \r\nGLOBAL LEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[b].Table.Type, tbsfrom[b].Alias) ?? tbsfrom[b].Alias);
|
||||
|
||||
if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1");
|
||||
else
|
||||
@ -80,13 +80,13 @@ namespace FreeSql.ClickHouse.Curd
|
||||
case SelectTableInfoType.RawJoin:
|
||||
continue;
|
||||
case SelectTableInfoType.LeftJoin:
|
||||
sb.Append(" \r\nLEFT JOIN ");
|
||||
sb.Append(" \r\nGLOBAL LEFT JOIN ");
|
||||
break;
|
||||
case SelectTableInfoType.InnerJoin:
|
||||
sb.Append(" \r\nINNER JOIN ");
|
||||
sb.Append(" \r\nGLOBAL INNER JOIN ");
|
||||
break;
|
||||
case SelectTableInfoType.RightJoin:
|
||||
sb.Append(" \r\nRIGHT JOIN ");
|
||||
sb.Append(" \r\nGLOBAL RIGHT JOIN ");
|
||||
break;
|
||||
}
|
||||
sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tb.Table.Type, tb.Alias) ?? tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition);
|
||||
|
@ -19,7 +19,7 @@
|
||||
<SignAssembly>False</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -41,7 +41,7 @@ namespace FreeSql.Custom
|
||||
|
||||
static FreeSql.Custom.CustomAdo _customAdo = new FreeSql.Custom.CustomAdo();
|
||||
public override string FormatSql(string sql, params object[] args) => (_orm?.Ado as CustomAdo)?.Addslashes(sql, args) ?? _customAdo.Addslashes(sql, args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -41,7 +41,7 @@ namespace FreeSql.Custom.MySql
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatCustomMySql(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -71,7 +71,7 @@ namespace FreeSql.Custom.Oracle
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatCustomOracle(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -97,7 +97,7 @@ namespace FreeSql.Custom.PostgreSQL
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatCustomPostgreSQL(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -49,7 +49,7 @@ namespace FreeSql.Custom.SqlServer
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatCustomSqlServer(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -82,7 +82,7 @@ namespace FreeSql.Dameng
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatDameng(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -15,7 +15,7 @@
|
||||
<Title>$(AssemblyName)</Title>
|
||||
<IsPackable>true</IsPackable>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -52,7 +52,7 @@ namespace FreeSql.Firebird
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatFirebird(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -56,7 +56,7 @@ namespace FreeSql.GBase
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatGBase(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -15,7 +15,7 @@
|
||||
<Title>$(AssemblyName)</Title>
|
||||
<IsPackable>true</IsPackable>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -92,7 +92,7 @@ namespace FreeSql.KingbaseES
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatKingbaseES(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -38,7 +38,7 @@ namespace FreeSql.MsAccess
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatAccess(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -36,6 +36,7 @@ namespace FreeSql.MySql
|
||||
});
|
||||
|
||||
Select0Provider._dicMethodDataReaderGetValue[typeof(Guid)] = typeof(DbDataReader).GetMethod("GetGuid", new Type[] { typeof(int) });
|
||||
Select0Provider._dicMethodDataReaderGetValue[typeof(DateTimeOffset)] = typeof(DbDataReader).GetMethod("GetDateTime", new Type[] { typeof(int) });
|
||||
}
|
||||
|
||||
public override ISelect<T1> CreateSelectProvider<T1>(object dywhere) => new MySqlSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
||||
|
@ -73,7 +73,7 @@ namespace FreeSql.MySql
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatMySql(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -4,6 +4,11 @@ using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using FreeSql.Internal.Model;
|
||||
using FreeSql.Internal.CommonProvider;
|
||||
using FreeSql.Internal.ObjectPool;
|
||||
using System.Linq;
|
||||
using System.Data.Common;
|
||||
#if MySqlConnector
|
||||
using MySqlConnector;
|
||||
#else
|
||||
@ -13,6 +18,55 @@ using MySql.Data.MySqlClient;
|
||||
public static class FreeSqlMySqlConnectorGlobalExtensions
|
||||
{
|
||||
#region ExecuteMySqlBulkCopy
|
||||
|
||||
/// <summary>
|
||||
/// 批量更新(更新字段数量超过 2000 时收益大)<para></para>
|
||||
/// 实现原理:使用 MySqlBulkCopy 插入临时表,再使用 UPDATE INNER JOIN 联表更新
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="that"></param>
|
||||
/// <param name="bulkCopyTimeout"></param>
|
||||
/// <returns></returns>
|
||||
public static int ExecuteMySqlBulkCopy<T>(this IUpdate<T> that, int? bulkCopyTimeout = null) where T : class
|
||||
{
|
||||
var update = that as UpdateProvider<T>;
|
||||
if (update._source.Any() != true || update._tempPrimarys.Any() == false) return 0;
|
||||
var state = ExecuteMySqlBulkCopyState(update);
|
||||
return UpdateProvider.ExecuteBulkUpdate(update, state, insert => insert.ExecuteMySqlBulkCopy(bulkCopyTimeout));
|
||||
}
|
||||
static NativeTuple<string, string, string, string, string[]> ExecuteMySqlBulkCopyState<T>(UpdateProvider<T> update) where T : class
|
||||
{
|
||||
if (update._source.Any() != true) return null;
|
||||
var _table = update._table;
|
||||
var _commonUtils = update._commonUtils;
|
||||
var updateTableName = update._tableRule?.Invoke(_table.DbName) ?? _table.DbName;
|
||||
var tempTableName = $"Temp_{Guid.NewGuid().ToString("N")}";
|
||||
if (update._orm.CodeFirst.IsSyncStructureToLower) tempTableName = tempTableName.ToLower();
|
||||
if (update._orm.CodeFirst.IsSyncStructureToUpper) tempTableName = tempTableName.ToUpper();
|
||||
if (update._connection == null && update._orm.Ado.TransactionCurrentThread != null)
|
||||
update.WithTransaction(update._orm.Ado.TransactionCurrentThread);
|
||||
var sb = new StringBuilder().Append("CREATE TEMPORARY TABLE ").Append(_commonUtils.QuoteSqlName(tempTableName)).Append(" ( ");
|
||||
var setColumns = new List<string>();
|
||||
var pkColumns = new List<string>();
|
||||
foreach (var col in _table.Columns.Values)
|
||||
{
|
||||
if (update._tempPrimarys.Any(a => a.CsName == col.CsName)) pkColumns.Add(col.Attribute.Name);
|
||||
else if (col.Attribute.IsIdentity == false && col.Attribute.IsVersion == false && update._ignore.ContainsKey(col.Attribute.Name) == false) setColumns.Add(col.Attribute.Name);
|
||||
else continue;
|
||||
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" ").Append(col.Attribute.DbType.Replace("NOT NULL", ""));
|
||||
sb.Append(",");
|
||||
}
|
||||
var sql1 = sb.Remove(sb.Length - 1, 1).Append(" \r\n) Engine=InnoDB;").ToString();
|
||||
|
||||
sb.Clear().Append("UPDATE ").Append(_commonUtils.QuoteSqlName(updateTableName)).Append(" a ")
|
||||
.Append(" \r\nINNER JOIN ").Append(_commonUtils.QuoteSqlName(tempTableName)).Append(" b ON ").Append(string.Join(" AND ", pkColumns.Select(col => $"a.{_commonUtils.QuoteSqlName(col)} = b.{_commonUtils.QuoteSqlName(col)}")))
|
||||
.Append(" \r\nSET \r\n ").Append(string.Join(", \r\n ", setColumns.Select(col => $"a.{_commonUtils.QuoteSqlName(col)} = b.{_commonUtils.QuoteSqlName(col)}")));
|
||||
var sql2 = sb.ToString();
|
||||
sb.Clear();
|
||||
var sql3 = $"DROP TABLE {_commonUtils.QuoteSqlName(tempTableName)}";
|
||||
return NativeTuple.Create(sql1, sql2, sql3, tempTableName, pkColumns.Concat(setColumns).ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MySql MySqlCopyBulk 批量插入功能<para></para>
|
||||
/// 使用 IgnoreColumns/InsertColumns 设置忽略/指定导入的列<para></para>
|
||||
@ -93,6 +147,13 @@ public static class FreeSqlMySqlConnectorGlobalExtensions
|
||||
}
|
||||
#if net40
|
||||
#else
|
||||
public static Task<int> ExecuteMySqlBulkCopyAsync<T>(this IUpdate<T> that, int? bulkCopyTimeout = null, CancellationToken cancellationToken = default) where T : class
|
||||
{
|
||||
var update = that as UpdateProvider<T>;
|
||||
if (update._source.Any() != true || update._tempPrimarys.Any() == false) return Task.FromResult(0);
|
||||
var state = ExecuteMySqlBulkCopyState(update);
|
||||
return UpdateProvider.ExecuteBulkUpdateAsync(update, state, insert => insert.ExecuteMySqlBulkCopyAsync(bulkCopyTimeout, cancellationToken));
|
||||
}
|
||||
async public static Task ExecuteMySqlBulkCopyAsync<T>(this IInsert<T> that, int? bulkCopyTimeout = null, CancellationToken cancellationToken = default) where T : class
|
||||
{
|
||||
var insert = that as FreeSql.MySql.Curd.MySqlInsert<T>;
|
||||
|
@ -91,7 +91,7 @@ namespace FreeSql.MySql
|
||||
}
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatMySql(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -71,7 +71,7 @@ namespace FreeSql.Odbc.Dameng
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatOdbcDameng(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ namespace FreeSql.Odbc.Default
|
||||
|
||||
static FreeSql.Odbc.Default.OdbcAdo _customAdo = new FreeSql.Odbc.Default.OdbcAdo();
|
||||
public override string FormatSql(string sql, params object[] args) => (_orm?.Ado as OdbcAdo)?.Addslashes(sql, args) ?? _customAdo.Addslashes(sql, args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -91,7 +91,7 @@ namespace FreeSql.Odbc.KingbaseES
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatOdbcKingbaseES(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -37,7 +37,7 @@ namespace FreeSql.Odbc.MySql
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatOdbcMySql(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -71,7 +71,7 @@ namespace FreeSql.Odbc.Oracle
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatOdbcOracle(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -91,7 +91,7 @@ namespace FreeSql.Odbc.PostgreSQL
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatOdbcPostgreSQL(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -43,7 +43,7 @@ namespace FreeSql.Odbc.SqlServer
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatOdbcSqlServer(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -100,7 +100,7 @@ namespace FreeSql.Oracle
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatOracle(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -104,7 +104,7 @@ namespace FreeSql.Oracle
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatOracle(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1,9 +1,13 @@
|
||||
using FreeSql;
|
||||
using FreeSql.Internal.CommonProvider;
|
||||
using FreeSql.Internal.Model;
|
||||
using FreeSql.PostgreSQL.Curd;
|
||||
using Npgsql;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
@ -32,6 +36,54 @@ public static partial class FreeSqlPostgreSQLGlobalExtensions
|
||||
public static OnConflictDoUpdate<T1> OnConflictDoUpdate<T1>(this IInsert<T1> that, Expression<Func<T1, object>> columns = null) where T1 : class => new FreeSql.PostgreSQL.Curd.OnConflictDoUpdate<T1>(that.InsertIdentity(), columns);
|
||||
|
||||
#region ExecutePgCopy
|
||||
/// <summary>
|
||||
/// 批量更新(更新字段数量超过 2000 时收益大)<para></para>
|
||||
/// 实现原理:使用 PgCopy 插入临时表,再使用 UPDATE INNER JOIN 联表更新
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="that"></param>
|
||||
/// <returns></returns>
|
||||
public static int ExecutePgCopy<T>(this IUpdate<T> that) where T : class
|
||||
{
|
||||
var update = that as UpdateProvider<T>;
|
||||
if (update._source.Any() != true || update._tempPrimarys.Any() == false) return 0;
|
||||
var state = ExecutePgCopyState(update);
|
||||
return UpdateProvider.ExecuteBulkUpdate(update, state, insert => insert.ExecutePgCopy());
|
||||
}
|
||||
static NativeTuple<string, string, string, string, string[]> ExecutePgCopyState<T>(UpdateProvider<T> update) where T : class
|
||||
{
|
||||
if (update._source.Any() != true) return null;
|
||||
var _table = update._table;
|
||||
var _commonUtils = update._commonUtils;
|
||||
var updateTableName = update._tableRule?.Invoke(_table.DbName) ?? _table.DbName;
|
||||
var tempTableName = $"Temp_{Guid.NewGuid().ToString("N")}";
|
||||
if (update._orm.CodeFirst.IsSyncStructureToLower) tempTableName = tempTableName.ToLower();
|
||||
if (update._orm.CodeFirst.IsSyncStructureToUpper) tempTableName = tempTableName.ToUpper();
|
||||
if (update._connection == null && update._orm.Ado.TransactionCurrentThread != null)
|
||||
update.WithTransaction(update._orm.Ado.TransactionCurrentThread);
|
||||
var sb = new StringBuilder().Append("CREATE TEMP TABLE ").Append(_commonUtils.QuoteSqlName(tempTableName)).Append(" ( ");
|
||||
var setColumns = new List<string>();
|
||||
var pkColumns = new List<string>();
|
||||
foreach (var col in _table.Columns.Values)
|
||||
{
|
||||
if (update._tempPrimarys.Any(a => a.CsName == col.CsName)) pkColumns.Add(col.Attribute.Name);
|
||||
else if (col.Attribute.IsIdentity == false && col.Attribute.IsVersion == false && update._ignore.ContainsKey(col.Attribute.Name) == false) setColumns.Add(col.Attribute.Name);
|
||||
else continue;
|
||||
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(col.Attribute.Name)).Append(" ").Append(col.Attribute.DbType.Replace("NOT NULL", ""));
|
||||
sb.Append(",");
|
||||
}
|
||||
var sql1 = sb.Remove(sb.Length - 1, 1).Append("\r\n) WITH (OIDS=FALSE);").ToString();
|
||||
|
||||
sb.Clear().Append("UPDATE ").Append(_commonUtils.QuoteSqlName(updateTableName)).Append(" a ")
|
||||
.Append("\r\nSET \r\n ").Append(string.Join(", \r\n ", setColumns.Select(col => $"{_commonUtils.QuoteSqlName(col)} = b.{_commonUtils.QuoteSqlName(col)}")))
|
||||
.Append("\r\nFROM ").Append(_commonUtils.QuoteSqlName(tempTableName)).Append(" b ")
|
||||
.Append("\r\nWHERE ").Append(string.Join(" AND ", pkColumns.Select(col => $"a.{_commonUtils.QuoteSqlName(col)} = b.{_commonUtils.QuoteSqlName(col)}")));
|
||||
var sql2 = sb.ToString();
|
||||
sb.Clear();
|
||||
var sql3 = $"DROP TABLE {_commonUtils.QuoteSqlName(tempTableName)}";
|
||||
return NativeTuple.Create(sql1, sql2, sql3, tempTableName, pkColumns.Concat(setColumns).ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PostgreSQL COPY 批量导入功能,封装了 NpgsqlConnection.BeginBinaryImport 方法<para></para>
|
||||
/// 使用 IgnoreColumns/InsertColumns 设置忽略/指定导入的列<para></para>
|
||||
@ -121,6 +173,13 @@ public static partial class FreeSqlPostgreSQLGlobalExtensions
|
||||
|
||||
#if net45
|
||||
#else
|
||||
public static Task<int> ExecutePgCopyAsync<T>(this IUpdate<T> that, CancellationToken cancellationToken = default) where T : class
|
||||
{
|
||||
var update = that as UpdateProvider<T>;
|
||||
if (update._source.Any() != true || update._tempPrimarys.Any() == false) return Task.FromResult(0);
|
||||
var state = ExecutePgCopyState(update);
|
||||
return UpdateProvider.ExecuteBulkUpdateAsync(update, state, insert => insert.ExecutePgCopyAsync(cancellationToken));
|
||||
}
|
||||
async public static Task ExecutePgCopyAsync<T>(this IInsert<T> that, CancellationToken cancellationToken = default) where T : class
|
||||
{
|
||||
var insert = that as FreeSql.PostgreSQL.Curd.PostgreSQLInsert<T>;
|
||||
|
@ -132,7 +132,7 @@ namespace FreeSql.PostgreSQL
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatPostgreSQL(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -15,7 +15,7 @@
|
||||
<Title>$(AssemblyName)</Title>
|
||||
<IsPackable>true</IsPackable>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -105,7 +105,7 @@ namespace FreeSql.ShenTong
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatShenTong(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<DelaySign>false</DelaySign>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -5,6 +5,10 @@ using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using FreeSql.Internal.CommonProvider;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Data.Common;
|
||||
using FreeSql.Internal.ObjectPool;
|
||||
#if microsoft
|
||||
using Microsoft.Data.SqlClient;
|
||||
#else
|
||||
@ -115,6 +119,51 @@ public static partial class FreeSqlSqlServerGlobalExtensions
|
||||
internal static ConcurrentDictionary<Guid, NativeTuple<SqlServerLock, Dictionary<Type, bool>>> _dicSetGlobalSelectWithLock = new ConcurrentDictionary<Guid, NativeTuple<SqlServerLock, Dictionary<Type, bool>>>();
|
||||
|
||||
#region ExecuteSqlBulkCopy
|
||||
/// <summary>
|
||||
/// 批量更新(更新字段数量超过 2000 时收益大)<para></para>
|
||||
/// 实现原理:使用 SqlBulkCopy 插入临时表,再使用 UPDATE INNER JOIN 联表更新
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="that"></param>
|
||||
/// <param name="copyOptions"></param>
|
||||
/// <param name="batchSize"></param>
|
||||
/// <param name="bulkCopyTimeout"></param>
|
||||
/// <returns></returns>
|
||||
public static int ExecuteSqlBulkCopy<T>(this IUpdate<T> that, SqlBulkCopyOptions copyOptions = SqlBulkCopyOptions.Default, int? batchSize = null, int? bulkCopyTimeout = null) where T : class
|
||||
{
|
||||
var update = that as UpdateProvider<T>;
|
||||
if (update._source.Any() != true || update._tempPrimarys.Any() == false) return 0;
|
||||
var state = ExecuteSqlBulkCopyState(update);
|
||||
return UpdateProvider.ExecuteBulkUpdate(update, state, insert => insert.ExecuteSqlBulkCopy(copyOptions, batchSize, bulkCopyTimeout));
|
||||
}
|
||||
static NativeTuple<string, string, string, string, string[]> ExecuteSqlBulkCopyState<T>(UpdateProvider<T> update) where T : class
|
||||
{
|
||||
if (update._source.Any() != true) return null;
|
||||
var _table = update._table;
|
||||
var _commonUtils = update._commonUtils;
|
||||
var updateTableName = update._tableRule?.Invoke(_table.DbName) ?? _table.DbName;
|
||||
var tempTableName = $"#Temp_{updateTableName}";
|
||||
if (update._orm.CodeFirst.IsSyncStructureToLower) tempTableName = tempTableName.ToLower();
|
||||
if (update._orm.CodeFirst.IsSyncStructureToUpper) tempTableName = tempTableName.ToUpper();
|
||||
if (update._connection == null && update._orm.Ado.TransactionCurrentThread != null)
|
||||
update.WithTransaction(update._orm.Ado.TransactionCurrentThread);
|
||||
var setColumns = new List<string>();
|
||||
var pkColumns = new List<string>();
|
||||
foreach (var col in _table.Columns.Values)
|
||||
{
|
||||
if (update._tempPrimarys.Any(a => a.CsName == col.CsName)) pkColumns.Add(col.Attribute.Name);
|
||||
else if (col.Attribute.IsIdentity == false && col.Attribute.IsVersion == false && update._ignore.ContainsKey(col.Attribute.Name) == false) setColumns.Add(col.Attribute.Name);
|
||||
}
|
||||
var sql1 = $"SELECT {string.Join(", ", pkColumns)}, {string.Join(", ", setColumns)} INTO {tempTableName} FROM {_commonUtils.QuoteSqlName(updateTableName)} WHERE 1=2";
|
||||
var sb = new StringBuilder().Append("UPDATE ").Append(" a SET \r\n ").Append(string.Join(", \r\n ", setColumns.Select(col => $"a.{_commonUtils.QuoteSqlName(col)} = b.{_commonUtils.QuoteSqlName(col)}")));
|
||||
sb.Append(" \r\nFROM ").Append(_commonUtils.QuoteSqlName(updateTableName)).Append(" a ")
|
||||
.Append(" \r\nINNER JOIN ").Append(tempTableName).Append(" b ON ").Append(string.Join(" AND ", pkColumns.Select(col => $"a.{_commonUtils.QuoteSqlName(col)} = b.{_commonUtils.QuoteSqlName(col)}")));
|
||||
var sql2 = sb.ToString();
|
||||
sb.Clear();
|
||||
var sql3 = $"DROP TABLE {tempTableName}";
|
||||
return NativeTuple.Create(sql1, sql2, sql3, tempTableName, pkColumns.Concat(setColumns).ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SqlServer SqlCopyBulk 批量插入功能<para></para>
|
||||
/// 使用 IgnoreColumns/InsertColumns 设置忽略/指定导入的列<para></para>
|
||||
@ -214,6 +263,13 @@ public static partial class FreeSqlSqlServerGlobalExtensions
|
||||
}
|
||||
#if net40
|
||||
#else
|
||||
public static Task<int> ExecuteSqlBulkCopyAsync<T>(this IUpdate<T> that, SqlBulkCopyOptions copyOptions = SqlBulkCopyOptions.Default, int? batchSize = null, int? bulkCopyTimeout = null, CancellationToken cancellationToken = default) where T : class
|
||||
{
|
||||
var update = that as UpdateProvider<T>;
|
||||
if (update._source.Any() != true || update._tempPrimarys.Any() == false) return Task.FromResult(0);
|
||||
var state = ExecuteSqlBulkCopyState(update);
|
||||
return UpdateProvider.ExecuteBulkUpdateAsync(update, state, insert => insert.ExecuteSqlBulkCopyAsync(copyOptions, batchSize, bulkCopyTimeout, cancellationToken));
|
||||
}
|
||||
async public static Task ExecuteSqlBulkCopyAsync<T>(this IInsert<T> that, SqlBulkCopyOptions copyOptions = SqlBulkCopyOptions.Default, int? batchSize = null, int? bulkCopyTimeout = null, CancellationToken cancellationToken = default) where T : class
|
||||
{
|
||||
var insert = that as FreeSql.SqlServer.Curd.SqlServerInsert<T>;
|
||||
|
@ -59,7 +59,7 @@ namespace FreeSql.SqlServer
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatSqlServer(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -82,7 +82,7 @@ namespace FreeSql.Sqlite
|
||||
});
|
||||
|
||||
public override string FormatSql(string sql, params object[] args) => sql?.FormatSqlite(args);
|
||||
public override string QuoteSqlName(params string[] name)
|
||||
public override string QuoteSqlNameAdapter(params string[] name)
|
||||
{
|
||||
if (name.Length == 1)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Version>3.2.684-preview20221124</Version>
|
||||
<Version>3.2.686-preview20221226</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -210,13 +210,15 @@ constantine,
|
||||
[mafeng8](https://github.com/mafeng8),
|
||||
[VicBilibily](https://github.com/VicBilibily),
|
||||
[Soar](https://github.com/sgf),
|
||||
[quzhen91](https://github.com/quzhen91) etc.
|
||||
[quzhen91](https://github.com/quzhen91),
|
||||
homejun,
|
||||
[d4ilys](https://github.com/d4ilys) etc.
|
||||
|
||||
## 💕 Donation
|
||||
|
||||
L*y 58元、花花 88元、麦兜很乖 50元、网络来者 2000元、John 99.99元、alex 666元、bacongao 36元、无名 100元、Eternity 188元、无名 10元、⌒.Helper~..oO 66元、习惯与被习惯 100元、无名 100元、蔡易喋 88.88元、中讯科技 1000元、Good Good Work 24元、炽焰 6.6元、Nothing 100元、兰州天擎赵 500元、哈利路亚 300元、
|
||||
无名 100元、蛰伏 99.99元、TCYM 66.66元、MOTA 5元、LDZXG 30元、Near 30元、建爽 66元、无名 200元、LambertWu 100元、无名 18.88元、乌龙 50元、无名 100元、陳怼怼 66.66元、陳怼怼 66.66元、丁淮 100元、李伟坚-Excel催化剂 100元、白狐 6.66元、她微笑的脸y 30元、Eternity²º²¹ 588元、夜归柴门 88元、蔡易喋 666.66元、
|
||||
*礼 10元、litrpa 88元、Alax CHOW 200元、Daily 66元、k\*t 66元、蓝 100元、*菜 10元、生命如歌 1000元、山鸡 88元、平凡 100元、大树 1000元、软软的毛毛虫 66.66
|
||||
*礼 10元、litrpa 88元、Alax CHOW 200元、Daily 66元、k\*t 66元、蓝 100元、*菜 10元、生命如歌 1000元、山鸡 88元、平凡 100元、大树 1000元、软软的毛毛虫 66.66元、问卷星 2000元
|
||||
|
||||
> Thank you for your donation
|
||||
|
||||
|
@ -211,13 +211,15 @@ constantine,
|
||||
[mafeng8](https://github.com/mafeng8),
|
||||
[VicBilibily](https://github.com/VicBilibily),
|
||||
[Soar](https://github.com/sgf),
|
||||
[quzhen91](https://github.com/quzhen91) 等。
|
||||
[quzhen91](https://github.com/quzhen91),
|
||||
homejun,
|
||||
[d4ilys](https://github.com/d4ilys) 等。
|
||||
|
||||
## 💕 Donation (捐赠)
|
||||
|
||||
L\*y 58元、花花 88元、麦兜很乖 50元、网络来者 2000元、John 99.99元、alex 666元、bacongao 36元、无名 100元、Eternity 188元、无名 10元、⌒.Helper~..oO 66元、习惯与被习惯 100元、无名 100元、蔡易喋 88.88元、中讯科技 1000元、Good Good Work 24元、炽焰 6.6元、Nothing 100元、兰州天擎赵 500元、哈利路亚 300元、
|
||||
无名 100元、蛰伏 99.99元、TCYM 66.66元、MOTA 5元、LDZXG 30元、Near 30元、建爽 66元、无名 200元、LambertWu 100元、无名 18.88元、乌龙 50元、无名 100元、陳怼怼 66.66元、陳怼怼 66.66元、丁淮 100元、李伟坚-Excel催化剂 100元、白狐 6.66元、她微笑的脸y 30元、Eternity²º²¹ 588元、夜归柴门 88元、蔡易喋 666.66元、
|
||||
*礼 10元、litrpa 88元、Alax CHOW 200元、Daily 66元、k*t 66元、蓝 100元、\*菜 10元、生命如歌 1000元、山鸡 88元、平凡 100元、大树 1000元、软软的毛毛虫 66.66
|
||||
*礼 10元、litrpa 88元、Alax CHOW 200元、Daily 66元、k*t 66元、蓝 100元、\*菜 10元、生命如歌 1000元、山鸡 88元、平凡 100元、大树 1000元、软软的毛毛虫 66.66元、问卷星 2000元
|
||||
|
||||
> 超级感谢你的打赏。
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user