This commit is contained in:
jinghognbo 2022-12-28 13:59:39 +08:00
commit 5210723caa
99 changed files with 1545 additions and 507 deletions

View File

@ -11,7 +11,7 @@
<!--
经常出于版本交叉问题,暂时关闭,在每个项目上设置版本号
<PropertyGroup>
<Version>3.2.684-preview20221124</Version>
<Version>3.2.686-preview20221226</Version>
</PropertyGroup>
-->

View File

@ -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; }
}

View File

@ -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();

View File

@ -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; }

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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 NTJSTJNONE
Newtonsoft.JsonSystem.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++;

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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>

View File

@ -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&lt;T&gt;的配置类
</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>

View File

@ -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>

View File

@ -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()
{

View File

@ -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"));

View File

@ -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)

View 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));
}
}
}

View 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;
}
}
}
}

View File

@ -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>
编号

View File

@ -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();

View File

@ -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()
{

View File

@ -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]

View File

@ -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];

View File

@ -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>

View File

@ -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&lt;&gt;)</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&lt;&gt;)</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>

View File

@ -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&lt;&gt;)</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&lt;&gt;)</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;

View File

@ -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;
}
}
}
}
}

View File

@ -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

View File

@ -277,6 +277,8 @@ namespace FreeSql.Internal
return false;
}
if (parent.CsType == null) parent.CsType = exp.Type;
try
{
var pdbfield = parent.DbField = ExpressionLambdaToSql(exp, getTSC());
if (parent.MapType == null || _tables?.Any(a => a.Table?.IsRereadSql == true) == true)
{
@ -285,7 +287,13 @@ namespace FreeSql.Internal
if (findcol != null) pdbfield = _common.RereadColumn(findcol, pdbfield);
}
field.Append(", ").Append(pdbfield);
LocalSetFieldAlias(ref index, true);
LocalSetFieldAlias(ref index, _tables != null ||
SelectGroupingProvider._ParseExpOnlyDbField.Value != pdbfield);
}
finally
{
SelectGroupingProvider._ParseExpOnlyDbField.Value = null;
}
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:

View File

@ -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");
@ -784,10 +806,13 @@ namespace FreeSql.Internal.CommonProvider
int val = 0;
Exception ex = null;
try
{
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)
{
ex = ex2;
@ -820,10 +845,13 @@ namespace FreeSql.Internal.CommonProvider
object val = null;
Exception ex = null;
try
{
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)
{
ex = ex2;

View File

@ -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");
@ -689,10 +725,13 @@ namespace FreeSql.Internal.CommonProvider
int val = 0;
Exception ex = null;
try
{
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)
{
ex = ex2;
@ -725,10 +764,13 @@ namespace FreeSql.Internal.CommonProvider
object val = null;
Exception ex = null;
try
{
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)
{
ex = ex2;

View File

@ -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
{

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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:

View File

@ -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;

View File

@ -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;
}

View File

@ -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)

View File

@ -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
}
}

View File

@ -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>

View File

@ -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);
}

View File

@ -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) },
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(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) },
{ 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(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(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(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) },
{ 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;
}
@ -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,24 +157,34 @@ 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()");
@ -132,7 +193,8 @@ namespace FreeSql.ClickHouse
{
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;
}
}
}

View File

@ -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)
{

View File

@ -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);

View File

@ -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>

View File

@ -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)
{

View File

@ -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>

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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>

View File

@ -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)
{

View File

@ -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>

View File

@ -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>

View File

@ -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)
{

View File

@ -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>

View File

@ -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)
{

View File

@ -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>

View File

@ -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)
{

View File

@ -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>

View File

@ -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);

View File

@ -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)
{

View File

@ -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>

View File

@ -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>;

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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>

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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>

View File

@ -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)
{

View File

@ -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>

View File

@ -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)
{

View File

@ -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>

View File

@ -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>;

View File

@ -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)
{

View File

@ -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>

View File

@ -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)
{

View File

@ -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>

View File

@ -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>;

View File

@ -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)
{

View File

@ -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>

View File

@ -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>

View File

@ -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)
{

View File

@ -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>

View File

@ -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

View File

@ -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元
> 超级感谢你的打赏。