拆分 FreeSql 按需引用

This commit is contained in:
28810
2019-05-28 21:32:54 +08:00
parent 37ed28f7a0
commit f8e897e201
149 changed files with 945 additions and 4082 deletions

View File

@ -66,7 +66,7 @@ namespace FreeSql.DataAnnotations {
/// <summary>
/// 数据库默认值
/// </summary>
internal object DbDefautValue { get; set; }
public object DbDefautValue { get; set; }
/// <summary>
/// 类型映射,比如:可将 enum 属性映射成 typeof(string)

View File

@ -5,46 +5,46 @@ namespace FreeSql.DatabaseModel {
/// <summary>
/// 所属表
/// </summary>
public DbTableInfo Table { get; internal set; }
public DbTableInfo Table { get; set; }
/// <summary>
/// 列名
/// </summary>
public string Name { get; internal set; }
public string Name { get; set; }
/// <summary>
/// 映射到 C# 类型
/// </summary>
public Type CsType { get; internal set; }
public Type CsType { get; set; }
/// <summary>
/// 数据库枚举类型int值
/// </summary>
public int DbType { get; internal set; }
public int DbType { get; set; }
/// <summary>
/// 数据库类型字符串varchar
/// </summary>
public string DbTypeText { get; internal set; }
public string DbTypeText { get; set; }
/// <summary>
/// 数据库类型字符串varchar(255)
/// </summary>
public string DbTypeTextFull { get; internal set; }
public string DbTypeTextFull { get; set; }
/// <summary>
/// 最大长度
/// </summary>
public int MaxLength { get; internal set; }
public int MaxLength { get; set; }
/// <summary>
/// 主键
/// </summary>
public bool IsPrimary { get; internal set; }
public bool IsPrimary { get; set; }
/// <summary>
/// 自增标识
/// </summary>
public bool IsIdentity { get; internal set; }
public bool IsIdentity { get; set; }
/// <summary>
/// 是否可DBNull
/// </summary>
public bool IsNullable { get; internal set; }
public bool IsNullable { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Coment { get; internal set; }
public string Coment { get; set; }
}
}

View File

@ -6,19 +6,19 @@ namespace FreeSql.DatabaseModel {
/// <summary>
/// 唯一标识
/// </summary>
public string Id { get; internal set; }
public string Id { get; set; }
/// <summary>
/// SqlServer下是Owner、PostgreSQL下是Schema、MySql下是数据库名
/// </summary>
public string Schema { get; internal set; }
public string Schema { get; set; }
/// <summary>
/// 表名
/// </summary>
public string Name { get; internal set; }
public string Name { get; set; }
/// <summary>
/// 表备注SqlServer下是扩展属性 MS_Description
/// </summary>
public string Comment { get; internal set; }
public string Comment { get; set; }
/// <summary>
/// 表/视图
/// </summary>
@ -26,27 +26,27 @@ namespace FreeSql.DatabaseModel {
/// <summary>
/// 列
/// </summary>
public List<DbColumnInfo> Columns { get; internal set; } = new List<DbColumnInfo>();
public List<DbColumnInfo> Columns { get; set; } = new List<DbColumnInfo>();
/// <summary>
/// 自增列
/// </summary>
public List<DbColumnInfo> Identitys { get; internal set; } = new List<DbColumnInfo>();
public List<DbColumnInfo> Identitys { get; set; } = new List<DbColumnInfo>();
/// <summary>
/// 主键/组合
/// </summary>
public List<DbColumnInfo> Primarys { get; internal set; } = new List<DbColumnInfo>();
public List<DbColumnInfo> Primarys { get; set; } = new List<DbColumnInfo>();
/// <summary>
/// 唯一键/组合
/// </summary>
public Dictionary<string, List<DbColumnInfo>> UniquesDict { get; internal set; } = new Dictionary<string, List<DbColumnInfo>>();
public Dictionary<string, List<DbColumnInfo>> UniquesDict { get; set; } = new Dictionary<string, List<DbColumnInfo>>();
/// <summary>
/// 索引/组合
/// </summary>
public Dictionary<string, List<DbColumnInfo>> IndexesDict { get; internal set; } = new Dictionary<string, List<DbColumnInfo>>();
public Dictionary<string, List<DbColumnInfo>> IndexesDict { get; set; } = new Dictionary<string, List<DbColumnInfo>>();
/// <summary>
/// 外键
/// </summary>
public Dictionary<string, DbForeignInfo> ForeignsDict { get; internal set; } = new Dictionary<string, DbForeignInfo>();
public Dictionary<string, DbForeignInfo> ForeignsDict { get; set; } = new Dictionary<string, DbForeignInfo>();
public List<List<DbColumnInfo>> Uniques => UniquesDict.Values.ToList();
public List<List<DbColumnInfo>> Indexes => IndexesDict.Values.ToList();

View File

@ -2,10 +2,10 @@
namespace FreeSql.DatabaseModel {
public class DbForeignInfo {
public DbTableInfo Table { get; internal set; }
public List<DbColumnInfo> Columns { get; internal set; } = new List<DbColumnInfo>();
public DbTableInfo ReferencedTable { get; internal set; }
public List<DbColumnInfo> ReferencedColumns { get; internal set; } = new List<DbColumnInfo>();
public DbTableInfo Table { get; set; }
public List<DbColumnInfo> Columns { get; set; } = new List<DbColumnInfo>();
public DbTableInfo ReferencedTable { get; set; }
public List<DbColumnInfo> ReferencedColumns { get; set; } = new List<DbColumnInfo>();
}
}

View File

@ -28,7 +28,7 @@ public static partial class FreeSqlGlobalExtensions {
public static bool IsNumberType(this Type that) => that == null ? false : dicIsNumberType.Value.ContainsKey(that);
public static bool IsNullableType(this Type that) => that?.FullName.StartsWith("System.Nullable`1[") == true;
public static bool IsAnonymousType(this Type that) => that?.FullName.StartsWith("<>f__AnonymousType") == true;
internal static Type NullableTypeOrThis(this Type that) => that?.IsNullableType() == true ? that.GenericTypeArguments.First() : that;
public static Type NullableTypeOrThis(this Type that) => that?.IsNullableType() == true ? that.GenericTypeArguments.First() : that;
/// <summary>
/// 测量两个经纬度的距离,返回单位:米

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Version>0.5.23</Version>
<Version>0.6.1</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>YeXiangQin</Authors>
<Description>FreeSql is the most convenient ORM in dotnet. It supports Mysql, Postgresql, SqlServer, Oracle and Sqlite.</Description>
@ -23,18 +23,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CS-Script.Core" Version="1.0.6" />
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.1.0" />
<PackageReference Include="MySql.Data" Version="8.0.15" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="Npgsql.LegacyPostgis" Version="4.0.5" />
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="2.18.5" />
<PackageReference Include="SafeObjectPool" Version="2.0.1" />
<PackageReference Include="System.Data.SqlClient" Version="4.6.0" />
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.110" />
</ItemGroup>
</Project>

View File

@ -409,20 +409,6 @@
<param name="columnType"></param>
<param name="setExp"></param>
</member>
<member name="M:FreeSql.FreeSqlBuilder.UseCache(Microsoft.Extensions.Caching.Distributed.IDistributedCache)">
<summary>
使用缓存,不指定默认使用内存
</summary>
<param name="cache">缓存实现</param>
<returns></returns>
</member>
<member name="M:FreeSql.FreeSqlBuilder.UseLogger(Microsoft.Extensions.Logging.ILogger)">
<summary>
使用日志,不指定默认输出控制台
</summary>
<param name="logger"></param>
<returns></returns>
</member>
<member name="M:FreeSql.FreeSqlBuilder.UseConnectionString(FreeSql.DataType,System.String)">
<summary>
使用连接串
@ -488,16 +474,6 @@
<param name="executed">执行后,可监视执行性能</param>
<returns></returns>
</member>
<member name="M:FreeSql.Generator.TemplateEngin.ITemplateOutput.OuTpUt(System.Text.StringBuilder,System.Collections.IDictionary,System.String,FreeSql.Generator.TemplateEngin)">
<summary>
</summary>
<param name="tOuTpUt">返回内容</param>
<param name="oPtIoNs">渲染对象</param>
<param name="rEfErErFiLeNaMe">当前文件路径</param>
<param name="tEmPlAtEsEnDeR"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IDelete`1.WithTransaction(System.Data.Common.DbTransaction)">
<summary>
指定事务对象
@ -807,14 +783,6 @@
</summary>
<returns></returns>
</member>
<member name="M:FreeSql.ISelect0`2.Caching(System.Int32,System.String)">
<summary>
缓存查询结果
</summary>
<param name="seconds">缓存秒数</param>
<param name="key">缓存key</param>
<returns></returns>
</member>
<member name="M:FreeSql.ISelect0`2.LeftJoin(System.Linq.Expressions.Expression{System.Func{`1,System.Boolean}})">
<summary>
左联查询使用导航属性自动生成SQL
@ -1643,12 +1611,6 @@
当前线程的事务
</summary>
</member>
<member name="M:FreeSql.IAdo.TransactionPreRemoveCache(System.String[])">
<summary>
事务完成前预删除缓存
</summary>
<param name="keys"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteReader(System.Action{System.Data.Common.DbDataReader},System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
查询若使用读写分离查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】
@ -2081,118 +2043,6 @@
耗时(单位:毫秒)
</summary>
</member>
<member name="P:FreeSql.ICache.Serialize">
<summary>
缓存数据时序列化方法,若无设置则默认使用 Json.net
</summary>
</member>
<member name="P:FreeSql.ICache.Deserialize">
<summary>
获取缓存数据时反序列化方法,若无设置则默认使用 Json.net
</summary>
</member>
<member name="M:FreeSql.ICache.Set``1(System.String,``0,System.Int32)">
<summary>
缓存可序列化数据
</summary>
<typeparam name="T"></typeparam>
<param name="key">缓存键</param>
<param name="data">可序列化数据</param>
<param name="timeoutSeconds">缓存秒数,&lt;=0时永久缓存</param>
</member>
<member name="M:FreeSql.ICache.Get``1(System.String)">
<summary>
循环或批量获取缓存数据
</summary>
<typeparam name="T"></typeparam>
<param name="key"></param>
<returns></returns>
</member>
<member name="M:FreeSql.ICache.Get(System.String)">
<summary>
循环或批量获取缓存数据
</summary>
<param name="key"></param>
<returns></returns>
</member>
<member name="M:FreeSql.ICache.Remove(System.String[])">
<summary>
循环或批量删除缓存键
</summary>
<param name="keys">缓存键[数组]</param>
</member>
<member name="M:FreeSql.ICache.Shell``1(System.String,System.Int32,System.Func{``0})">
<summary>
缓存壳
</summary>
<typeparam name="T">缓存类型</typeparam>
<param name="key">缓存键</param>
<param name="timeoutSeconds">缓存秒数</param>
<param name="getData">获取源数据的函数</param>
<returns></returns>
</member>
<member name="M:FreeSql.ICache.Shell``1(System.String,System.String,System.Int32,System.Func{``0})">
<summary>
缓存壳(哈希表)
</summary>
<typeparam name="T">缓存类型</typeparam>
<param name="key">缓存键</param>
<param name="field">字段</param>
<param name="timeoutSeconds">缓存秒数</param>
<param name="getData">获取源数据的函数</param>
<returns></returns>
</member>
<member name="M:FreeSql.ICache.SetAsync``1(System.String,``0,System.Int32)">
<summary>
缓存可序列化数据
</summary>
<typeparam name="T"></typeparam>
<param name="key">缓存键</param>
<param name="data">可序列化数据</param>
<param name="timeoutSeconds">缓存秒数,&lt;=0时永久缓存</param>
</member>
<member name="M:FreeSql.ICache.GetAsync``1(System.String)">
<summary>
循环或批量获取缓存数据
</summary>
<typeparam name="T"></typeparam>
<param name="key"></param>
<returns></returns>
</member>
<member name="M:FreeSql.ICache.GetAsync(System.String)">
<summary>
循环或批量获取缓存数据
</summary>
<param name="key"></param>
<returns></returns>
</member>
<member name="M:FreeSql.ICache.RemoveAsync(System.String[])">
<summary>
循环或批量删除缓存键
</summary>
<param name="keys">缓存键[数组]</param>
</member>
<member name="M:FreeSql.ICache.ShellAsync``1(System.String,System.Int32,System.Func{System.Threading.Tasks.Task{``0}})">
<summary>
缓存壳
</summary>
<typeparam name="T">缓存类型</typeparam>
<param name="key">缓存键</param>
<param name="timeoutSeconds">缓存秒数</param>
<param name="getDataAsync">获取源数据的函数</param>
<returns></returns>
</member>
<member name="M:FreeSql.ICache.ShellAsync``1(System.String,System.String,System.Int32,System.Func{System.Threading.Tasks.Task{``0}})">
<summary>
缓存壳(哈希表)
</summary>
<typeparam name="T">缓存类型</typeparam>
<param name="key">缓存键</param>
<param name="field">字段</param>
<param name="timeoutSeconds">缓存秒数</param>
<param name="getDataAsync">获取源数据的函数</param>
<returns></returns>
</member>
<member name="P:FreeSql.ICodeFirst.IsAutoSyncStructure">
<summary>
【开发环境必备】自动同步实体结构到数据库,程序运行中检查实体表是否存在,然后创建或修改
@ -2385,46 +2235,6 @@
<param name="that"></param>
<returns></returns>
</member>
<member name="M:FreeSqlGlobalExtensions.FormatMySql(System.String,System.Object[])">
<summary>
特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换
</summary>
<param name="that"></param>
<param name="args"></param>
<returns></returns>
</member>
<member name="M:FreeSqlGlobalExtensions.FormatOracleSQL(System.String,System.Object[])">
<summary>
特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换
</summary>
<param name="that"></param>
<param name="args"></param>
<returns></returns>
</member>
<member name="M:FreeSqlGlobalExtensions.FormatPostgreSQL(System.String,System.Object[])">
<summary>
特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换
</summary>
<param name="that"></param>
<param name="args"></param>
<returns></returns>
</member>
<member name="M:FreeSqlGlobalExtensions.FormatSqlite(System.String,System.Object[])">
<summary>
特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换
</summary>
<param name="that"></param>
<param name="args"></param>
<returns></returns>
</member>
<member name="M:FreeSqlGlobalExtensions.FormatSqlServer(System.String,System.Object[])">
<summary>
特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换
</summary>
<param name="that"></param>
<param name="args"></param>
<returns></returns>
</member>
<member name="M:FreeUtil.NewMongodbId">
<summary>
生成类似Mongodb的ObjectId有序、不重复Guid
@ -2520,11 +2330,6 @@
<param name="handler">事务体 () => {}</param>
<param name="timeout">超时,未执行完将自动提交</param>
</member>
<member name="P:IFreeSql.Cache">
<summary>
缓存
</summary>
</member>
<member name="P:IFreeSql.Ado">
<summary>
数据库访问对象
@ -2545,36 +2350,5 @@
DbFirst 模式开发相关方法
</summary>
</member>
<member name="M:MygisTypesExtensions.Distance(MygisPoint,MygisPoint)">
<summary>
测量两个经纬度的距离,返回单位:米
</summary>
<param name="that">经纬坐标1</param>
<param name="point">经纬坐标2</param>
<returns>返回距离(单位:米)</returns>
</member>
<member name="M:PostgreSQLTypesExtensions.Distance(NpgsqlTypes.NpgsqlPoint,NpgsqlTypes.NpgsqlPoint)">
<summary>
测量两个经纬度的距离,返回单位:米
</summary>
<param name="that">经纬坐标1</param>
<param name="point">经纬坐标2</param>
<returns>返回距离(单位:米)</returns>
</member>
<member name="M:PostgreSQLTypesExtensions.Distance(Npgsql.LegacyPostgis.PostgisPoint,Npgsql.LegacyPostgis.PostgisPoint)">
<summary>
测量两个经纬度的距离,返回单位:米
</summary>
<param name="that">经纬坐标1</param>
<param name="point">经纬坐标2</param>
<returns>返回距离(单位:米)</returns>
</member>
<member name="M:PostgreSQLTypesExtensions.ToBitArray(System.String)">
<summary>
将 1010101010 这样的二进制字符串转换成 BitArray
</summary>
<param name="_1010Str">1010101010</param>
<returns></returns>
</member>
</members>
</doc>

View File

@ -1,12 +1,8 @@
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using System;
using System;
using System.Data.Common;
namespace FreeSql {
public class FreeSqlBuilder {
IDistributedCache _cache;
ILogger _logger;
DataType _dataType;
string _masterConnectionString;
string[] _slaveConnectionString;
@ -19,25 +15,6 @@ namespace FreeSql {
Action<DbCommand> _aopCommandExecuting = null;
Action<DbCommand, string> _aopCommandExecuted = null;
/// <summary>
/// 使用缓存,不指定默认使用内存
/// </summary>
/// <param name="cache">缓存实现</param>
/// <returns></returns>
public FreeSqlBuilder UseCache(IDistributedCache cache) {
_cache = cache;
return this;
}
/// <summary>
/// 使用日志,不指定默认输出控制台
/// </summary>
/// <param name="logger"></param>
/// <returns></returns>
public FreeSqlBuilder UseLogger(ILogger logger) {
_logger = logger;
return this;
}
/// <summary>
/// 使用连接串
/// </summary>
@ -127,14 +104,27 @@ namespace FreeSql {
public IFreeSql Build() => Build<IFreeSql>();
public IFreeSql<TMark> Build<TMark>() {
IFreeSql<TMark> ret = null;
Type type = null;
switch(_dataType) {
case DataType.MySql: ret = new MySql.MySqlProvider<TMark>(_cache, _logger, _masterConnectionString, _slaveConnectionString); break;
case DataType.SqlServer: ret = new SqlServer.SqlServerProvider<TMark>(_cache, _logger, _masterConnectionString, _slaveConnectionString); break;
case DataType.PostgreSQL: ret = new PostgreSQL.PostgreSQLProvider<TMark>(_cache, _logger, _masterConnectionString, _slaveConnectionString); break;
case DataType.Oracle: ret = new Oracle.OracleProvider<TMark>(_cache, _logger, _masterConnectionString, _slaveConnectionString); break;
case DataType.Sqlite: ret = new Sqlite.SqliteProvider<TMark>(_cache, _logger, _masterConnectionString, _slaveConnectionString); break;
case DataType.MySql:
type = Type.GetType("FreeSql.MySql.MySqlProvider`1,FreeSql.Provider.MySql")?.MakeGenericType(typeof(TMark));
if (type == null) throw new Exception("缺少 FreeSql 数据库实现包FreeSql.Provider.MySql.dll可前往 nuget 下载");
break;
case DataType.SqlServer: type = Type.GetType("FreeSql.SqlServer.SqlServerProvider`1,FreeSql.Provider.SqlServer")?.MakeGenericType(typeof(TMark));
if (type == null) throw new Exception("缺少 FreeSql 数据库实现包FreeSql.Provider.SqlServer.dll可前往 nuget 下载");
break;
case DataType.PostgreSQL: type = Type.GetType("FreeSql.PostgreSQL.PostgreSQLProvider`1,FreeSql.Provider.PostgreSQL")?.MakeGenericType(typeof(TMark));
if (type == null) throw new Exception("缺少 FreeSql 数据库实现包FreeSql.Provider.PostgreSQL.dll可前往 nuget 下载");
break;
case DataType.Oracle: type = Type.GetType("FreeSql.Oracle.OracleProvider`1,FreeSql.Provider.Oracle")?.MakeGenericType(typeof(TMark));
if (type == null) throw new Exception("缺少 FreeSql 数据库实现包FreeSql.Provider.Oracle.dll可前往 nuget 下载");
break;
case DataType.Sqlite: type = Type.GetType("FreeSql.Sqlite.SqliteProvider`1,FreeSql.Provider.Sqlite")?.MakeGenericType(typeof(TMark));
if (type == null) throw new Exception("缺少 FreeSql 数据库实现包FreeSql.Provider.Sqlite.dll可前往 nuget 下载");
break;
default: throw new Exception("未指定 UseConnectionString");
}
ret = Activator.CreateInstance(type, new object[] { _masterConnectionString, _slaveConnectionString }) as IFreeSql<TMark>;
if (ret != null) {
ret.CodeFirst.IsAutoSyncStructure = _isAutoSyncStructure;

View File

@ -31,38 +31,4 @@ public static class FreeUtil {
var guid = $"{uninxtime.ToString("x8").PadLeft(8, '0')}{__staticMachine.ToString("x8").PadLeft(8, '0').Substring(2, 6)}{__staticPid.ToString("x8").PadLeft(8, '0').Substring(6, 2)}{increment.ToString("x8").PadLeft(8, '0')}{rand.ToString("x8").PadLeft(8, '0')}";
return Guid.Parse(guid);
}
internal static void PrevReheatConnectionPool(ObjectPool<DbConnection> pool, int minPoolSize) {
if (minPoolSize <= 0) minPoolSize = Math.Min(5, pool.Policy.PoolSize);
if (minPoolSize > pool.Policy.PoolSize) minPoolSize = pool.Policy.PoolSize;
var initTestOk = true;
var initStartTime = DateTime.Now;
var initConns = new ConcurrentBag<Object<DbConnection>>();
try {
var conn = pool.Get();
initConns.Add(conn);
pool.Policy.OnCheckAvailable(conn);
} catch {
initTestOk = false; //预热一次失败,后面将不进行
}
for (var a = 1; initTestOk && a < minPoolSize; a += 10) {
if (initStartTime.Subtract(DateTime.Now).TotalSeconds > 3) break; //预热耗时超过3秒退出
var b = Math.Min(minPoolSize - a, 10); //每10个预热
var initTasks = new Task[b];
for (var c = 0; c < b; c++) {
initTasks[c] = Task.Run(() => {
try {
var conn = pool.Get();
initConns.Add(conn);
pool.Policy.OnCheckAvailable(conn);
} catch {
initTestOk = false; //有失败,下一组退出预热
}
});
}
Task.WaitAll(initTasks);
}
while (initConns.TryTake(out var conn)) pool.Return(conn);
}
}

View File

@ -1,644 +0,0 @@
using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
namespace FreeSql.Generator {
public class TemplateEngin : IDisposable {
public interface ITemplateOutput {
/// <summary>
///
/// </summary>
/// <param name="tOuTpUt">返回内容</param>
/// <param name="oPtIoNs">渲染对象</param>
/// <param name="rEfErErFiLeNaMe">当前文件路径</param>
/// <param name="tEmPlAtEsEnDeR"></param>
/// <returns></returns>
TemplateReturnInfo OuTpUt(StringBuilder tOuTpUt, IDictionary oPtIoNs, string rEfErErFiLeNaMe, TemplateEngin tEmPlAtEsEnDeR);
}
public class TemplateReturnInfo {
public Dictionary<string, int[]> Blocks;
public StringBuilder Sb;
}
public delegate bool TemplateIf(object exp);
public delegate void TemplatePrint(params object[] parms);
private static int _view = 0;
private static Regex _reg = new Regex(@"\{(\$TEMPLATE__CODE|\/\$TEMPLATE__CODE|import\s+|module\s+|extends\s+|block\s+|include\s+|for\s+|if\s+|#|\/for|elseif|else|\/if|\/block|\/module)([^\}]*)\}", RegexOptions.Compiled);
private static Regex _reg_forin = new Regex(@"^([\w_]+)\s*,?\s*([\w_]+)?\s+in\s+(.+)", RegexOptions.Compiled);
private static Regex _reg_foron = new Regex(@"^([\w_]+)\s*,?\s*([\w_]+)?,?\s*([\w_]+)?\s+on\s+(.+)", RegexOptions.Compiled);
private static Regex _reg_forab = new Regex(@"^([\w_]+)\s+([^,]+)\s*,\s*(.+)", RegexOptions.Compiled);
private static Regex _reg_miss = new Regex(@"\{\/?miss\}", RegexOptions.Compiled);
private static Regex _reg_code = new Regex(@"(\{%|%\})", RegexOptions.Compiled);
private static Regex _reg_syntax = new Regex(@"<(\w+)\s+@(if|for|else)\s*=""([^""]*)""", RegexOptions.Compiled);
private static Regex _reg_htmltag = new Regex(@"<\/?\w+[^>]*>", RegexOptions.Compiled);
private static Regex _reg_blank = new Regex(@"\s+", RegexOptions.Compiled);
private static Regex _reg_complie_undefined = new Regex(@"(当前上下文中不存在名称)?“(\w+)”", RegexOptions.Compiled);
private Dictionary<string, ITemplateOutput> _cache = new Dictionary<string, ITemplateOutput>();
private object _cache_lock = new object();
private string _viewDir;
private string[] _usings;
private FileSystemWatcher _fsw = new FileSystemWatcher();
public TemplateEngin(string viewDir, params string[] usings) {
_viewDir = Utils.TranslateUrl(viewDir);
_usings = usings;
_fsw = new FileSystemWatcher(_viewDir);
_fsw.IncludeSubdirectories = true;
_fsw.Changed += ViewDirChange;
_fsw.Renamed += ViewDirChange;
_fsw.EnableRaisingEvents = true;
}
public void Dispose() {
_fsw.Dispose();
}
void ViewDirChange(object sender, FileSystemEventArgs e) {
string filename = e.FullPath.ToLower();
lock (_cache_lock) {
_cache.Remove(filename);
}
}
public TemplateReturnInfo RenderFile2(StringBuilder sb, IDictionary options, string filename, string refererFilename) {
if (filename[0] == '/' || string.IsNullOrEmpty(refererFilename)) refererFilename = _viewDir;
//else refererFilename = Path.GetDirectoryName(refererFilename);
string filename2 = Utils.TranslateUrl(filename, refererFilename);
ITemplateOutput tpl;
if (_cache.TryGetValue(filename2, out tpl) == false) {
string tplcode = File.Exists(filename2) == false ? string.Concat("文件不存在 ", filename) : Utils.ReadTextFile(filename2);
tpl = Parser(tplcode, _usings, options);
lock (_cache_lock) {
if (_cache.ContainsKey(filename2) == false) {
_cache.Add(filename2, tpl);
}
}
}
try {
return tpl.OuTpUt(sb, options, filename2, this);
} catch (Exception ex) {
TemplateReturnInfo ret = sb == null ?
new TemplateReturnInfo { Sb = new StringBuilder(), Blocks = new Dictionary<string, int[]>() } :
new TemplateReturnInfo { Sb = sb, Blocks = new Dictionary<string, int[]>() };
ret.Sb.Append(refererFilename);
ret.Sb.Append(" -> ");
ret.Sb.Append(filename);
ret.Sb.Append("\r\n");
ret.Sb.Append(ex.Message);
ret.Sb.Append("\r\n");
ret.Sb.Append(ex.StackTrace);
return ret;
}
}
public string RenderFile(string filename, IDictionary options) {
TemplateReturnInfo ret = this.RenderFile2(null, options, filename, null);
return ret.Sb.ToString();
}
private static ITemplateOutput Parser(string tplcode, string[] usings, IDictionary options) {
int view = Interlocked.Increment(ref _view);
StringBuilder sb = new StringBuilder();
IDictionary options_copy = new Hashtable();
foreach (DictionaryEntry options_de in options) options_copy[options_de.Key] = options_de.Value;
sb.AppendFormat(@"
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;{1}
//namespace TplDynamicCodeGenerate {{
public class TplDynamicCodeGenerate_view{0} : FreeSql.Generator.TemplateEngin.ITemplateOutput {{
public FreeSql.Generator.TemplateEngin.TemplateReturnInfo OuTpUt(StringBuilder tOuTpUt, IDictionary oPtIoNs, string rEfErErFiLeNaMe, FreeSql.Generator.TemplateEngin tEmPlAtEsEnDeR) {{
FreeSql.Generator.TemplateEngin.TemplateReturnInfo rTn = tOuTpUt == null ?
new FreeSql.Generator.TemplateEngin.TemplateReturnInfo {{ Sb = (tOuTpUt = new StringBuilder()), Blocks = new Dictionary<string, int[]>() }} :
new FreeSql.Generator.TemplateEngin.TemplateReturnInfo {{ Sb = tOuTpUt, Blocks = new Dictionary<string, int[]>() }};
Dictionary<string, int[]> TPL__blocks = rTn.Blocks;
Stack<int[]> TPL__blocks_stack = new Stack<int[]>();
int[] TPL__blocks_stack_peek;
List<IDictionary> TPL__forc = new List<IDictionary>();
Func<IDictionary> pRoCeSsOpTiOnS = new Func<IDictionary>(delegate () {{
IDictionary nEwoPtIoNs = new Hashtable();
foreach (DictionaryEntry oPtIoNs_dE in oPtIoNs)
nEwoPtIoNs[oPtIoNs_dE.Key] = oPtIoNs_dE.Value;
foreach (IDictionary TPL__forc_dIc in TPL__forc)
foreach (DictionaryEntry TPL__forc_dIc_dE in TPL__forc_dIc)
nEwoPtIoNs[TPL__forc_dIc_dE.Key] = TPL__forc_dIc_dE.Value;
return nEwoPtIoNs;
}});
FreeSql.Generator.TemplateEngin.TemplateIf tPlIf = delegate(object exp) {{
if (exp is bool) return (bool)exp;
if (exp == null) return false;
if (exp is int && (int)exp == 0) return false;
if (exp is string && (string)exp == string.Empty) return false;
if (exp is long && (long)exp == 0) return false;
if (exp is short && (short)exp == 0) return false;
if (exp is byte && (byte)exp == 0) return false;
if (exp is double && (double)exp == 0) return false;
if (exp is float && (float)exp == 0) return false;
if (exp is decimal && (decimal)exp == 0) return false;
return true;
}};
FreeSql.Generator.TemplateEngin.TemplatePrint print = delegate(object[] pArMs) {{
if (pArMs == null || pArMs.Length == 0) return;
foreach (object pArMs_A in pArMs) if (pArMs_A != null) tOuTpUt.Append(pArMs_A);
}};
FreeSql.Generator.TemplateEngin.TemplatePrint Print = print;", view, usings?.Any() == true ? $"\r\nusing {string.Join(";\r\nusing ", usings)};" : "");
#region {miss}...{/miss}
string[] tmp_content_arr = _reg_miss.Split(tplcode);
if (tmp_content_arr.Length > 1) {
sb.AppendFormat(@"
string[] TPL__MISS = new string[{0}];", Math.Ceiling(1.0 * (tmp_content_arr.Length - 1) / 2));
int miss_len = -1;
for (int a = 1; a < tmp_content_arr.Length; a += 2) {
sb.Append(string.Concat(@"
TPL__MISS[", ++miss_len, @"] = """, Utils.GetConstString(tmp_content_arr[a]), @""";"));
tmp_content_arr[a] = string.Concat("{#TPL__MISS[", miss_len, "]}");
}
tplcode = string.Join("", tmp_content_arr);
}
#endregion
#region <div @if="表达式"></div>
tplcode = htmlSyntax(tplcode, 3); //<div @if="c#表达式" @for="index 1,100"></div>
//处理 {% %} 块 c#代码
tmp_content_arr = _reg_code.Split(tplcode);
if (tmp_content_arr.Length == 1) {
tplcode = Utils.GetConstString(tplcode)
.Replace("{%", "{$TEMPLATE__CODE}")
.Replace("%}", "{/$TEMPLATE__CODE}");
} else {
tmp_content_arr[0] = Utils.GetConstString(tmp_content_arr[0]);
for (int a = 1; a < tmp_content_arr.Length; a += 4) {
tmp_content_arr[a] = "{$TEMPLATE__CODE}";
tmp_content_arr[a + 2] = "{/$TEMPLATE__CODE}";
tmp_content_arr[a + 3] = Utils.GetConstString(tmp_content_arr[a + 3]);
}
tplcode = string.Join("", tmp_content_arr);
}
#endregion
sb.Append(@"
tOuTpUt.Append(""");
string error = null;
int tpl_tmpid = 0;
int forc_i = 0;
string extends = null;
Stack<string> codeTree = new Stack<string>();
Stack<string> forEndRepl = new Stack<string>();
sb.Append(_reg.Replace(tplcode, delegate (Match m) {
string _0 = m.Groups[0].Value;
if (!string.IsNullOrEmpty(error)) return _0;
string _1 = m.Groups[1].Value.Trim(' ', '\t');
string _2 = m.Groups[2].Value
.Replace("\\\\", "\\")
.Replace("\\\"", "\"");
_2 = Utils.ReplaceSingleQuote(_2);
switch (_1) {
#region $TEMPLATE__CODE--------------------------------------------------
case "$TEMPLATE__CODE":
codeTree.Push(_1);
return @""");
";
case "/$TEMPLATE__CODE":
string pop = codeTree.Pop();
if (pop != "$TEMPLATE__CODE") {
codeTree.Push(pop);
error = "编译出错,{% 与 %} 并没有配对";
return _0;
}
return @"
tOuTpUt.Append(""";
#endregion
case "include":
return string.Format(@""");
tEmPlAtEsEnDeR.RenderFile2(tOuTpUt, pRoCeSsOpTiOnS(), ""{0}"", rEfErErFiLeNaMe);
tOuTpUt.Append(""", _2);
case "import":
return _0;
case "module":
return _0;
case "/module":
return _0;
case "extends":
//{extends ../inc/layout.html}
if (string.IsNullOrEmpty(extends) == false) return _0;
extends = _2;
return string.Empty;
case "block":
codeTree.Push("block");
return string.Format(@""");
TPL__blocks_stack_peek = new int[] {{ tOuTpUt.Length, 0 }};
TPL__blocks_stack.Push(TPL__blocks_stack_peek);
TPL__blocks.Add(""{0}"", TPL__blocks_stack_peek);
tOuTpUt.Append(""", _2.Trim(' ', '\t'));
case "/block":
codeTreeEnd(codeTree, "block");
return @""");
TPL__blocks_stack_peek = TPL__blocks_stack.Pop();
TPL__blocks_stack_peek[1] = tOuTpUt.Length - TPL__blocks_stack_peek[0];
tOuTpUt.Append(""";
#region ##---------------------------------------------------------
case "#":
if (_2[0] == '#')
return string.Format(@""");
try {{ Print({0}); }} catch {{ }}
tOuTpUt.Append(""", _2.Substring(1));
return string.Format(@""");
Print({0});
tOuTpUt.Append(""", _2);
#endregion
#region for--------------------------------------------------------
case "for":
forc_i++;
int cur_tpl_tmpid = tpl_tmpid;
string sb_endRepl = string.Empty;
StringBuilder sbfor = new StringBuilder();
sbfor.Append(@""");");
Match mfor = _reg_forin.Match(_2);
if (mfor.Success) {
string mfor1 = mfor.Groups[1].Value.Trim(' ', '\t');
string mfor2 = mfor.Groups[2].Value.Trim(' ', '\t');
sbfor.AppendFormat(@"
//new Action(delegate () {{
IDictionary TPL__tmp{0} = new Hashtable();
TPL__forc.Add(TPL__tmp{0});
var TPL__tmp{1} = {3};
var TPL__tmp{2} = {4};", ++tpl_tmpid, ++tpl_tmpid, ++tpl_tmpid, mfor.Groups[3].Value, mfor1);
sb_endRepl = string.Concat(sb_endRepl, string.Format(@"
{0} = TPL__tmp{1};", mfor1, cur_tpl_tmpid + 3));
if (options_copy.Contains(mfor1) == false) options_copy[mfor1] = null;
if (!string.IsNullOrEmpty(mfor2)) {
sbfor.AppendFormat(@"
var TPL__tmp{1} = {0};
{0} = 0;", mfor2, ++tpl_tmpid);
sb_endRepl = string.Concat(sb_endRepl, string.Format(@"
{0} = TPL__tmp{1};", mfor2, tpl_tmpid));
if (options_copy.Contains(mfor2) == false) options_copy[mfor2] = null;
}
sbfor.AppendFormat(@"
if (TPL__tmp{1} != null)
foreach (var TPL__tmp{0} in TPL__tmp{1}) {{", ++tpl_tmpid, cur_tpl_tmpid + 2);
if (!string.IsNullOrEmpty(mfor2))
sbfor.AppendFormat(@"
TPL__tmp{1}[""{0}""] = ++ {0};", mfor2, cur_tpl_tmpid + 1);
sbfor.AppendFormat(@"
TPL__tmp{1}[""{0}""] = TPL__tmp{2};
{0} = TPL__tmp{2};
tOuTpUt.Append(""", mfor1, cur_tpl_tmpid + 1, tpl_tmpid);
codeTree.Push("for");
forEndRepl.Push(sb_endRepl);
return sbfor.ToString();
}
mfor = _reg_foron.Match(_2);
if (mfor.Success) {
string mfor1 = mfor.Groups[1].Value.Trim(' ', '\t');
string mfor2 = mfor.Groups[2].Value.Trim(' ', '\t');
string mfor3 = mfor.Groups[3].Value.Trim(' ', '\t');
sbfor.AppendFormat(@"
//new Action(delegate () {{
IDictionary TPL__tmp{0} = new Hashtable();
TPL__forc.Add(TPL__tmp{0});
var TPL__tmp{1} = {3};
var TPL__tmp{2} = {4};", ++tpl_tmpid, ++tpl_tmpid, ++tpl_tmpid, mfor.Groups[4].Value, mfor1);
sb_endRepl = string.Concat(sb_endRepl, string.Format(@"
{0} = TPL__tmp{1};", mfor1, cur_tpl_tmpid + 3));
if (options_copy.Contains(mfor1) == false) options_copy[mfor1] = null;
if (!string.IsNullOrEmpty(mfor2)) {
sbfor.AppendFormat(@"
var TPL__tmp{1} = {0};", mfor2, ++tpl_tmpid);
sb_endRepl = string.Concat(sb_endRepl, string.Format(@"
{0} = TPL__tmp{1};", mfor2, tpl_tmpid));
if (options_copy.Contains(mfor2) == false) options_copy[mfor2] = null;
}
if (!string.IsNullOrEmpty(mfor3)) {
sbfor.AppendFormat(@"
var TPL__tmp{1} = {0};
{0} = 0;", mfor3, ++tpl_tmpid);
sb_endRepl = string.Concat(sb_endRepl, string.Format(@"
{0} = TPL__tmp{1};", mfor3, tpl_tmpid));
if (options_copy.Contains(mfor3) == false) options_copy[mfor3] = null;
}
sbfor.AppendFormat(@"
if (TPL__tmp{2} != null)
foreach (DictionaryEntry TPL__tmp{1} in TPL__tmp{2}) {{
{0} = TPL__tmp{1}.Key;
TPL__tmp{3}[""{0}""] = {0};", mfor1, ++tpl_tmpid, cur_tpl_tmpid + 2, cur_tpl_tmpid + 1);
if (!string.IsNullOrEmpty(mfor2))
sbfor.AppendFormat(@"
{0} = TPL__tmp{1}.Value;
TPL__tmp{2}[""{0}""] = {0};", mfor2, tpl_tmpid, cur_tpl_tmpid + 1);
if (!string.IsNullOrEmpty(mfor3))
sbfor.AppendFormat(@"
TPL__tmp{1}[""{0}""] = ++ {0};", mfor3, cur_tpl_tmpid + 1);
sbfor.AppendFormat(@"
tOuTpUt.Append(""");
codeTree.Push("for");
forEndRepl.Push(sb_endRepl);
return sbfor.ToString();
}
mfor = _reg_forab.Match(_2);
if (mfor.Success) {
string mfor1 = mfor.Groups[1].Value.Trim(' ', '\t');
sbfor.AppendFormat(@"
//new Action(delegate () {{
IDictionary TPL__tmp{0} = new Hashtable();
TPL__forc.Add(TPL__tmp{0});
var TPL__tmp{1} = {5};
{5} = {3} - 1;
if ({5} == null) {5} = 0;
var TPL__tmp{2} = {4} + 1;
while (++{5} < TPL__tmp{2}) {{
TPL__tmp{0}[""{5}""] = {5};
tOuTpUt.Append(""", ++tpl_tmpid, ++tpl_tmpid, ++tpl_tmpid, mfor.Groups[2].Value, mfor.Groups[3].Value, mfor1);
sb_endRepl = string.Concat(sb_endRepl, string.Format(@"
{0} = TPL__tmp{1};", mfor1, cur_tpl_tmpid + 1));
if (options_copy.Contains(mfor1) == false) options_copy[mfor1] = null;
codeTree.Push("for");
forEndRepl.Push(sb_endRepl);
return sbfor.ToString();
}
return _0;
case "/for":
if (--forc_i < 0) return _0;
codeTreeEnd(codeTree, "for");
return string.Format(@""");
}}{0}
TPL__forc.RemoveAt(TPL__forc.Count - 1);
//}})();
tOuTpUt.Append(""", forEndRepl.Pop());
#endregion
#region if---------------------------------------------------------
case "if":
codeTree.Push("if");
return string.Format(@""");
if ({1}tPlIf({0})) {{
tOuTpUt.Append(""", _2[0] == '!' ? _2.Substring(1) : _2, _2[0] == '!' ? '!' : ' ');
case "elseif":
codeTreeEnd(codeTree, "if");
codeTree.Push("if");
return string.Format(@""");
}} else if ({1}tPlIf({0})) {{
tOuTpUt.Append(""", _2[0] == '!' ? _2.Substring(1) : _2, _2[0] == '!' ? '!' : ' ');
case "else":
codeTreeEnd(codeTree, "if");
codeTree.Push("if");
return @""");
} else {
tOuTpUt.Append(""";
case "/if":
codeTreeEnd(codeTree, "if");
return @""");
}
tOuTpUt.Append(""";
#endregion
}
return _0;
}));
sb.Append(@""");");
if (string.IsNullOrEmpty(extends) == false) {
sb.AppendFormat(@"
FreeSql.Generator.TemplateEngin.TemplateReturnInfo eXtEnDs_ReT = tEmPlAtEsEnDeR.RenderFile2(null, pRoCeSsOpTiOnS(), ""{0}"", rEfErErFiLeNaMe);
string rTn_Sb_string = rTn.Sb.ToString();
foreach(string eXtEnDs_ReT_blocks_key in eXtEnDs_ReT.Blocks.Keys) {{
if (rTn.Blocks.ContainsKey(eXtEnDs_ReT_blocks_key)) {{
int[] eXtEnDs_ReT_blocks_value = eXtEnDs_ReT.Blocks[eXtEnDs_ReT_blocks_key];
eXtEnDs_ReT.Sb.Remove(eXtEnDs_ReT_blocks_value[0], eXtEnDs_ReT_blocks_value[1]);
int[] rTn_blocks_value = rTn.Blocks[eXtEnDs_ReT_blocks_key];
eXtEnDs_ReT.Sb.Insert(eXtEnDs_ReT_blocks_value[0], rTn_Sb_string.Substring(rTn_blocks_value[0], rTn_blocks_value[1]));
foreach(string eXtEnDs_ReT_blocks_keyb in eXtEnDs_ReT.Blocks.Keys) {{
if (eXtEnDs_ReT_blocks_keyb == eXtEnDs_ReT_blocks_key) continue;
int[] eXtEnDs_ReT_blocks_valueb = eXtEnDs_ReT.Blocks[eXtEnDs_ReT_blocks_keyb];
if (eXtEnDs_ReT_blocks_valueb[0] >= eXtEnDs_ReT_blocks_value[0])
eXtEnDs_ReT_blocks_valueb[0] = eXtEnDs_ReT_blocks_valueb[0] - eXtEnDs_ReT_blocks_value[1] + rTn_blocks_value[1];
}}
eXtEnDs_ReT_blocks_value[1] = rTn_blocks_value[1];
}}
}}
return eXtEnDs_ReT;
", extends);
} else {
sb.Append(@"
return rTn;");
}
sb.Append(@"
}
}
//}
");
var str = "FreeSql.Generator.TemplateEngin.TemplatePrint Print = print;";
int dim_idx = sb.ToString().IndexOf(str) + str.Length;
foreach (string dic_name in options_copy.Keys) {
sb.Insert(dim_idx, string.Format(@"
dynamic {0} = oPtIoNs[""{0}""];", dic_name));
}
//Console.WriteLine(sb.ToString());
return Complie(sb.ToString(), @"TplDynamicCodeGenerate_view" + view);
}
private static string codeTreeEnd(Stack<string> codeTree, string tag) {
string ret = string.Empty;
Stack<int> pop = new Stack<int>();
foreach (string ct in codeTree) {
if (ct == "import" ||
ct == "include") {
pop.Push(1);
} else if (ct == tag) {
pop.Push(2);
break;
} else {
if (string.IsNullOrEmpty(tag) == false) pop.Clear();
break;
}
}
if (pop.Count == 0 && string.IsNullOrEmpty(tag) == false)
return string.Concat("语法错误,{", tag, "} {/", tag, "} 并没配对");
while (pop.Count > 0 && pop.Pop() > 0) codeTree.Pop();
return ret;
}
#region htmlSyntax
private static string htmlSyntax(string tplcode, int num) {
while (num-- > 0) {
string[] arr = _reg_syntax.Split(tplcode);
if (arr.Length == 1) break;
for (int a = 1; a < arr.Length; a += 4) {
string tag = string.Concat('<', arr[a]);
string end = string.Concat("</", arr[a], '>');
int fc = 1;
for (int b = a; fc > 0 && b < arr.Length; b += 4) {
if (b > a && arr[a].ToLower() == arr[b].ToLower()) fc++;
int bpos = 0;
while (true) {
int fa = arr[b + 3].IndexOf(tag, bpos);
int fb = arr[b + 3].IndexOf(end, bpos);
if (b == a) {
var z = arr[b + 3].IndexOf("/>");
if ((fb == -1 || z < fb) && z != -1) {
var y = arr[b + 3].Substring(0, z + 2);
if (_reg_htmltag.IsMatch(y) == false)
fb = z - end.Length + 2;
}
}
if (fa == -1 && fb == -1) break;
if (fa != -1 && (fa < fb || fb == -1)) {
fc++;
bpos = fa + tag.Length;
continue;
}
if (fb != -1) fc--;
if (fc <= 0) {
var a1 = arr[a + 1];
var end3 = string.Concat("{/", a1, "}");
if (a1.ToLower() == "else") {
if (_reg_blank.Replace(arr[a - 4 + 3], "").EndsWith("{/if}", StringComparison.CurrentCultureIgnoreCase) == true) {
var idx = arr[a - 4 + 3].IndexOf("{/if}");
arr[a - 4 + 3] = string.Concat(arr[a - 4 + 3].Substring(0, idx), arr[a - 4 + 3].Substring(idx + 5));
//如果 @else="有条件内容",则变换成 elseif 条件内容
if (_reg_blank.Replace(arr[a + 2], "").Length > 0) a1 = "elseif";
end3 = "{/if}";
} else {
arr[a] = string.Concat("指令 @", arr[a + 1], "='", arr[a + 2], "' 没紧接着 if/else 指令之后,无效. <", arr[a]);
arr[a + 1] = arr[a + 2] = string.Empty;
}
}
if (arr[a + 1].Length > 0) {
if (_reg_blank.Replace(arr[a + 2], "").Length > 0 || a1.ToLower() == "else") {
arr[b + 3] = string.Concat(arr[b + 3].Substring(0, fb + end.Length), end3, arr[b + 3].Substring(fb + end.Length));
arr[a] = string.Concat("{", a1, " ", arr[a + 2], "}<", arr[a]);
arr[a + 1] = arr[a + 2] = string.Empty;
} else {
arr[a] = string.Concat('<', arr[a]);
arr[a + 1] = arr[a + 2] = string.Empty;
}
}
break;
}
bpos = fb + end.Length;
}
}
if (fc > 0) {
arr[a] = string.Concat("不严谨的html格式请检查 ", arr[a], " 的结束标签, @", arr[a + 1], "='", arr[a + 2], "' 指令无效. <", arr[a]);
arr[a + 1] = arr[a + 2] = string.Empty;
}
}
if (arr.Length > 0) tplcode = string.Join(string.Empty, arr);
}
return tplcode;
}
#endregion
#region Complie
private static ITemplateOutput Complie(string cscode, string typename) {
var assemly = _compiler.Value.CompileCode(cscode);
var type = assemly.DefinedTypes.Where(a => a.FullName.EndsWith(typename)).FirstOrDefault();
return Activator.CreateInstance(type) as ITemplateOutput;
}
internal static Lazy<CSScriptLib.RoslynEvaluator> _compiler = new Lazy<CSScriptLib.RoslynEvaluator>(() => {
//var dlls = Directory.GetFiles(Directory.GetParent(Type.GetType("IFreeSql, FreeSql").Assembly.Location).FullName, "*.dll");
var compiler = new CSScriptLib.RoslynEvaluator();
compiler.DisableReferencingFromCode = false;
//compiler.DebugBuild = true;
//foreach (var dll in dlls) {
// Console.WriteLine(dll);
// var ass = Assembly.LoadFile(dll);
// compiler.ReferenceAssembly(ass);
//}
compiler
.ReferenceAssemblyOf<IFreeSql>()
.ReferenceDomainAssemblies();
return compiler;
});
#endregion
#region Utils
public class Utils {
public static string ReplaceSingleQuote(object exp) {
//将 ' 转换成 "
string exp2 = string.Concat(exp);
int quote_pos = -1;
while (true) {
int first_pos = quote_pos = exp2.IndexOf('\'', quote_pos + 1);
if (quote_pos == -1) break;
while (true) {
quote_pos = exp2.IndexOf('\'', quote_pos + 1);
if (quote_pos == -1) break;
int r_cout = 0;
for (int p = 1; true; p++) {
if (exp2[quote_pos - p] == '\\') r_cout++;
else break;
}
if (r_cout % 2 == 0/* && quote_pos - first_pos > 2*/) {
string str1 = exp2.Substring(0, first_pos);
string str2 = exp2.Substring(first_pos + 1, quote_pos - first_pos - 1);
string str3 = exp2.Substring(quote_pos + 1);
string str4 = str2.Replace("\"", "\\\"");
quote_pos += str4.Length - str2.Length;
exp2 = string.Concat(str1, "\"", str4, "\"", str3);
break;
}
}
if (quote_pos == -1) break;
}
return exp2;
}
public static string GetConstString(object obj) {
return string.Concat(obj)
.Replace("\\", "\\\\")
.Replace("\"", "\\\"")
.Replace("\r", "\\r")
.Replace("\n", "\\n");
}
public static string ReadTextFile(string path) {
byte[] bytes = ReadFile(path);
return Encoding.UTF8.GetString(bytes).TrimStart((char)65279);
}
public static byte[] ReadFile(string path) {
if (File.Exists(path)) {
string destFileName = Path.GetTempFileName();
File.Copy(path, destFileName, true);
int read = 0;
byte[] data = new byte[1024];
using (MemoryStream ms = new MemoryStream()) {
using (FileStream fs = new FileStream(destFileName, FileMode.OpenOrCreate, FileAccess.Read)) {
do {
read = fs.Read(data, 0, data.Length);
if (read <= 0) break;
ms.Write(data, 0, read);
} while (true);
}
File.Delete(destFileName);
data = ms.ToArray();
}
return data;
}
return new byte[] { };
}
public static string TranslateUrl(string url) {
return TranslateUrl(url, null);
}
public static string TranslateUrl(string url, string baseDir) {
if (string.IsNullOrEmpty(baseDir)) baseDir = AppContext.BaseDirectory + "/";
if (string.IsNullOrEmpty(url)) return Path.GetDirectoryName(baseDir);
if (url.StartsWith("~/")) url = url.Substring(1);
if (url.StartsWith("/")) return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(baseDir), url.TrimStart('/')));
if (url.StartsWith("\\")) return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(baseDir), url.TrimStart('\\')));
if (url.IndexOf(":\\") != -1) return url;
return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(baseDir), url));
}
}
#endregion
}
}

View File

@ -1,72 +0,0 @@
using FreeSql.DatabaseModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace FreeSql.Generator {
public class TemplateGenerator {
public void Build(IDbFirst dbfirst, string templateDirectory, string outputDirectory, params string[] database) {
if (dbfirst == null) throw new ArgumentException("dbfirst 参数不能为 null");
if (string.IsNullOrEmpty(templateDirectory) || Directory.Exists(templateDirectory) == false) throw new ArgumentException("templateDirectory 目录不存在");
if (string.IsNullOrEmpty(templateDirectory)) throw new ArgumentException("outputDirectory 不能为 null");
if (database == null || database.Any() == false) throw new ArgumentException("database 参数不能为空");
if (Directory.Exists(outputDirectory) == false) Directory.CreateDirectory(outputDirectory);
templateDirectory = new DirectoryInfo(templateDirectory).FullName;
outputDirectory = new DirectoryInfo(outputDirectory).FullName;
if (templateDirectory.IndexOf(outputDirectory, StringComparison.CurrentCultureIgnoreCase) != -1) throw new ArgumentException("outputDirectory 目录不能设置在 templateDirectory 目录内");
var tables = dbfirst.GetTablesByDatabase(database);
var tpl = new TemplateEngin(templateDirectory, "FreeSql", "FreeSql.DatabaseModel");
BuildEachDirectory(templateDirectory, outputDirectory, tpl, dbfirst, tables);
tpl.Dispose();
}
void BuildEachDirectory(string templateDirectory, string outputDirectory, TemplateEngin tpl, IDbFirst dbfirst, List<DbTableInfo> tables) {
if (Directory.Exists(outputDirectory) == false) Directory.CreateDirectory(outputDirectory);
var files = Directory.GetFiles(templateDirectory);
foreach (var file in files) {
var fi = new FileInfo(file);
if (string.Compare(fi.Extension, ".FreeSql", true) == 0) {
var outputExtension = "." + fi.Name.Split('.')[1];
if (fi.Name.StartsWith("for-table.")) {
foreach (var table in tables) {
var result = tpl.RenderFile(file, new Dictionary<string, object>() { { "table", table }, { "dbfirst", dbfirst } });
if (result.EndsWith("return;")) continue;
var outputName = table.Name + outputExtension;
var mcls = Regex.Match(result, @"\s+class\s+(\w+)");
if (mcls.Success) outputName = mcls.Groups[1].Value + outputExtension;
var outputStream = Encoding.UTF8.GetBytes(result);
var fullname = outputDirectory + "/" + outputName;
if (File.Exists(fullname)) File.Delete(fullname);
using (var outfs = File.Open(fullname, FileMode.OpenOrCreate, FileAccess.Write)) {
outfs.Write(outputStream, 0, outputStream.Length);
outfs.Close();
}
}
continue;
} else {
var result = tpl.RenderFile(file, new Dictionary<string, object>() { { "tables", tables }, { "dbfirst", dbfirst } });
var outputName = fi.Name;
var mcls = Regex.Match(result, @"\s+class\s+(\w+)");
if (mcls.Success) outputName = mcls.Groups[1].Value + outputExtension;
var outputStream = Encoding.UTF8.GetBytes(result);
var fullname = outputDirectory + "/" + outputName;
if (File.Exists(fullname)) File.Delete(fullname);
using (var outfs = File.Open(fullname, FileMode.OpenOrCreate, FileAccess.Write)) {
outfs.Write(outputStream, 0, outputStream.Length);
outfs.Close();
}
}
}
File.Copy(file, outputDirectory + file.Replace(templateDirectory, ""), true);
}
var dirs = Directory.GetDirectories(templateDirectory);
foreach(var dir in dirs) {
BuildEachDirectory(dir, outputDirectory + dir.Replace(templateDirectory, ""), tpl, dbfirst, tables);
}
}
}
}

View File

@ -108,13 +108,6 @@ namespace FreeSql {
/// </summary>
/// <returns></returns>
TSelect Master();
/// <summary>
/// 缓存查询结果
/// </summary>
/// <param name="seconds">缓存秒数</param>
/// <param name="key">缓存key</param>
/// <returns></returns>
TSelect Caching(int seconds, string key = null);
/// <summary>
/// 左联查询使用导航属性自动生成SQL

View File

@ -46,11 +46,6 @@ namespace FreeSql {
/// 当前线程的事务
/// </summary>
DbTransaction TransactionCurrentThread { get; }
/// <summary>
/// 事务完成前预删除缓存
/// </summary>
/// <param name="keys"></param>
void TransactionPreRemoveCache(params string[] keys);
#endregion
/// <summary>

View File

@ -1,108 +0,0 @@
using System;
using System.Threading.Tasks;
namespace FreeSql {
public interface ICache {
/// <summary>
/// 缓存数据时序列化方法,若无设置则默认使用 Json.net
/// </summary>
Func<object, string> Serialize { get; set; }
/// <summary>
/// 获取缓存数据时反序列化方法,若无设置则默认使用 Json.net
/// </summary>
Func<string, Type, object> Deserialize { get; set; }
/// <summary>
/// 缓存可序列化数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key">缓存键</param>
/// <param name="data">可序列化数据</param>
/// <param name="timeoutSeconds">缓存秒数,&lt;=0时永久缓存</param>
void Set<T>(string key, T data, int timeoutSeconds = 0);
/// <summary>
/// 循环或批量获取缓存数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
T Get<T>(string key);
/// <summary>
/// 循环或批量获取缓存数据
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
string Get(string key);
/// <summary>
/// 循环或批量删除缓存键
/// </summary>
/// <param name="keys">缓存键[数组]</param>
void Remove(params string[] keys);
/// <summary>
/// 缓存壳
/// </summary>
/// <typeparam name="T">缓存类型</typeparam>
/// <param name="key">缓存键</param>
/// <param name="timeoutSeconds">缓存秒数</param>
/// <param name="getData">获取源数据的函数</param>
/// <returns></returns>
T Shell<T>(string key, int timeoutSeconds, Func<T> getData);
/// <summary>
/// 缓存壳(哈希表)
/// </summary>
/// <typeparam name="T">缓存类型</typeparam>
/// <param name="key">缓存键</param>
/// <param name="field">字段</param>
/// <param name="timeoutSeconds">缓存秒数</param>
/// <param name="getData">获取源数据的函数</param>
/// <returns></returns>
T Shell<T>(string key, string field, int timeoutSeconds, Func<T> getData);
/// <summary>
/// 缓存可序列化数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key">缓存键</param>
/// <param name="data">可序列化数据</param>
/// <param name="timeoutSeconds">缓存秒数,&lt;=0时永久缓存</param>
Task SetAsync<T>(string key, T data, int timeoutSeconds = 0);
/// <summary>
/// 循环或批量获取缓存数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
Task<T> GetAsync<T>(string key);
/// <summary>
/// 循环或批量获取缓存数据
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
Task<string> GetAsync(string key);
/// <summary>
/// 循环或批量删除缓存键
/// </summary>
/// <param name="keys">缓存键[数组]</param>
Task RemoveAsync(params string[] keys);
/// <summary>
/// 缓存壳
/// </summary>
/// <typeparam name="T">缓存类型</typeparam>
/// <param name="key">缓存键</param>
/// <param name="timeoutSeconds">缓存秒数</param>
/// <param name="getDataAsync">获取源数据的函数</param>
/// <returns></returns>
Task<T> ShellAsync<T>(string key, int timeoutSeconds, Func<Task<T>> getDataAsync);
/// <summary>
/// 缓存壳(哈希表)
/// </summary>
/// <typeparam name="T">缓存类型</typeparam>
/// <param name="key">缓存键</param>
/// <param name="field">字段</param>
/// <param name="timeoutSeconds">缓存秒数</param>
/// <param name="getDataAsync">获取源数据的函数</param>
/// <returns></returns>
Task<T> ShellAsync<T>(string key, string field, int timeoutSeconds, Func<Task<T>> getDataAsync);
}
}

View File

@ -87,10 +87,6 @@ public interface IFreeSql : IDisposable {
/// <param name="timeout">超时,未执行完将自动提交</param>
void Transaction(Action handler, TimeSpan timeout);
/// <summary>
/// 缓存
/// </summary>
ICache Cache { get; }
/// <summary>
/// 数据库访问对象
/// </summary>

View File

@ -10,17 +10,17 @@ using System.Reflection;
using System.Text;
namespace FreeSql.Internal {
internal abstract class CommonExpression {
public abstract class CommonExpression {
internal CommonUtils _common;
internal CommonProvider.AdoProvider _ado => _adoPriv ?? (_adoPriv = _common._orm.Ado as CommonProvider.AdoProvider);
public CommonUtils _common;
public CommonProvider.AdoProvider _ado => _adoPriv ?? (_adoPriv = _common._orm.Ado as CommonProvider.AdoProvider);
CommonProvider.AdoProvider _adoPriv;
internal CommonExpression(CommonUtils common) {
public CommonExpression(CommonUtils common) {
_common = common;
}
static ConcurrentDictionary<Type, PropertyInfo[]> _dicReadAnonymousFieldDtoPropertys = new ConcurrentDictionary<Type, PropertyInfo[]>();
internal bool ReadAnonymousField(List<SelectTableInfo> _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
public bool ReadAnonymousField(List<SelectTableInfo> _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
Func<ExpTSC> getTSC = () => new ExpTSC { _tables = _tables, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where };
switch (exp.NodeType) {
case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, getSelectGroupingMapString);
@ -180,7 +180,7 @@ namespace FreeSql.Internal {
if (index >= 0) field.Append(" as").Append(++index);
return false;
}
internal object ReadAnonymous(ReadAnonymousTypeInfo parent, DbDataReader dr, ref int index, bool notRead) {
public object ReadAnonymous(ReadAnonymousTypeInfo parent, DbDataReader dr, ref int index, bool notRead) {
if (parent.Childs.Any() == false) {
if (notRead) {
++index;
@ -215,7 +215,7 @@ namespace FreeSql.Internal {
return null;
}
internal ColumnInfo SearchColumnByField(List<SelectTableInfo> _tables, TableInfo currentTable, string field) {
public ColumnInfo SearchColumnByField(List<SelectTableInfo> _tables, TableInfo currentTable, string field) {
if (_tables != null) {
var testCol = _common.TrimQuoteSqlName(field).Split(new[] { '.' }, 2);
if (testCol.Length == 2) {
@ -232,11 +232,11 @@ namespace FreeSql.Internal {
return null;
}
internal string ExpressionSelectColumn_MemberAccess(List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, Expression exp, bool isQuoteName, Func<Expression[], string> getSelectGroupingMapString) {
public string ExpressionSelectColumn_MemberAccess(List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, SelectTableInfoType tbtype, Expression exp, bool isQuoteName, Func<Expression[], string> getSelectGroupingMapString) {
return ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, _selectColumnMap = _selectColumnMap, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = tbtype, isQuoteName = isQuoteName, isDisableDiyParse = false, style = ExpressionStyle.SelectColumns });
}
internal string[] ExpressionSelectColumns_MemberAccess_New_NewArrayInit(List<SelectTableInfo> _tables, Expression exp, bool isQuoteName, Func<Expression[], string> getSelectGroupingMapString) {
public string[] ExpressionSelectColumns_MemberAccess_New_NewArrayInit(List<SelectTableInfo> _tables, Expression exp, bool isQuoteName, Func<Expression[], string> getSelectGroupingMapString) {
switch (exp?.NodeType) {
case ExpressionType.Quote: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as UnaryExpression)?.Operand, isQuoteName, getSelectGroupingMapString);
case ExpressionType.Lambda: return ExpressionSelectColumns_MemberAccess_New_NewArrayInit(_tables, (exp as LambdaExpression)?.Body, isQuoteName, getSelectGroupingMapString);
@ -276,7 +276,7 @@ namespace FreeSql.Internal {
{ ExpressionType.Modulo, "%" },
{ ExpressionType.Equal, "=" },
};
internal string ExpressionWhereLambdaNoneForeignObject(List<SelectTableInfo> _tables, TableInfo table, List<SelectColumnInfo> _selectColumnMap, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
public string ExpressionWhereLambdaNoneForeignObject(List<SelectTableInfo> _tables, TableInfo table, List<SelectColumnInfo> _selectColumnMap, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, _selectColumnMap = _selectColumnMap, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, currentTable = table });
if (exp.NodeType == ExpressionType.MemberAccess && exp.Type == typeof(bool))
return $"{sql} = {formatSql(true, null)}";
@ -289,7 +289,7 @@ namespace FreeSql.Internal {
}
}
internal string ExpressionWhereLambda(List<SelectTableInfo> _tables, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
public string ExpressionWhereLambda(List<SelectTableInfo> _tables, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
var sql = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where });
if (exp.NodeType == ExpressionType.MemberAccess && exp.Type == typeof(bool))
return $"{sql} = {formatSql(true, null)}";
@ -301,7 +301,7 @@ namespace FreeSql.Internal {
default: return sql;
}
}
internal void ExpressionJoinLambda(List<SelectTableInfo> _tables, SelectTableInfoType tbtype, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
public void ExpressionJoinLambda(List<SelectTableInfo> _tables, SelectTableInfoType tbtype, Expression exp, Func<Expression[], string> getSelectGroupingMapString) {
var tbidx = _tables.Count;
var filter = ExpressionLambdaToSql(exp, new ExpTSC { _tables = _tables, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = tbtype, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where });
if (exp.NodeType == ExpressionType.MemberAccess && exp.Type == typeof(bool))
@ -333,7 +333,7 @@ namespace FreeSql.Internal {
internal static ConcurrentDictionary<Type, PropertyInfo> _dicNullableValueProperty = new ConcurrentDictionary<Type, PropertyInfo>();
static ConcurrentDictionary<Type, Expression> _dicFreeSqlGlobalExtensionsAsSelectExpression = new ConcurrentDictionary<Type, Expression>();
internal string ExpressionBinary(string oper, Expression leftExp, Expression rightExp, ExpTSC tsc) {
public string ExpressionBinary(string oper, Expression leftExp, Expression rightExp, ExpTSC tsc) {
switch (oper) {
case "OR":
case "|":
@ -399,7 +399,7 @@ namespace FreeSql.Internal {
tsc.mapType = null;
return $"{left} {oper} {right}";
}
internal string ExpressionLambdaToSql(Expression exp, ExpTSC tsc) {
public string ExpressionLambdaToSql(Expression exp, ExpTSC tsc) {
if (exp == null) return "";
if (tsc.isDisableDiyParse == false && _common._orm.Aop.ParseExpression != null) {
var args = new Aop.ParseExpressionEventArgs(exp, ukexp => ExpressionLambdaToSql(exp, tsc.CloneDisableDiyParse()));
@ -882,20 +882,20 @@ namespace FreeSql.Internal {
return ExpressionBinary(tryoper, expBinary.Left, expBinary.Right, tsc);
}
internal abstract string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc);
internal abstract string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc);
internal abstract string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc);
internal abstract string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc);
internal abstract string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc);
internal abstract string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc);
internal abstract string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc);
internal abstract string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc);
internal abstract string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc);
public abstract string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc);
public abstract string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc);
public abstract string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc);
public abstract string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc);
public abstract string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc);
public abstract string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc);
public abstract string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc);
public abstract string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc);
public abstract string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc);
internal enum ExpressionStyle {
public enum ExpressionStyle {
Where, AsSelect, SelectColumns
}
internal class ExpTSC {
public class ExpTSC {
public List<SelectTableInfo> _tables { get; set; }
public List<SelectColumnInfo> _selectColumnMap { get; set; }
public Func<Expression[], string> getSelectGroupingMapString { get; set; }
@ -932,7 +932,7 @@ namespace FreeSql.Internal {
}
}
internal string formatSql(object obj, Type mapType) {
public string formatSql(object obj, Type mapType) {
return string.Concat(_ado.AddslashesProcessParam(obj, mapType));
}
}

View File

@ -1,5 +1,4 @@
using Microsoft.Extensions.Logging;
using SafeObjectPool;
using SafeObjectPool;
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
@ -11,7 +10,7 @@ using System.Text;
using System.Reflection;
namespace FreeSql.Internal.CommonProvider {
abstract partial class AdoProvider : IAdo, IDisposable {
public abstract partial class AdoProvider : IAdo, IDisposable {
protected abstract void ReturnConnection(ObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex);
protected abstract DbCommand CreateCommand();
@ -24,16 +23,12 @@ namespace FreeSql.Internal.CommonProvider {
public ObjectPool<DbConnection> MasterPool { get; protected set; }
public List<ObjectPool<DbConnection>> SlavePools { get; } = new List<ObjectPool<DbConnection>>();
public DataType DataType { get; }
protected ICache _cache { get; set; }
protected ILogger _log { get; set; }
protected CommonUtils _util { get; set; }
protected int slaveUnavailables = 0;
private object slaveLock = new object();
private Random slaveRandom = new Random();
public AdoProvider(ICache cache, ILogger log, DataType dataType) {
this._cache = cache;
this._log = log;
public AdoProvider(DataType dataType) {
this.DataType = dataType;
}
@ -43,7 +38,7 @@ namespace FreeSql.Internal.CommonProvider {
if (IsTracePerformance) {
TimeSpan ts = DateTime.Now.Subtract(dt);
if (e == null && ts.TotalMilliseconds > 100)
_log.LogWarning(logtxt.Insert(0, $"{pool?.Policy.Name}执行SQL语句耗时过长{ts.TotalMilliseconds}ms\r\n{cmd.CommandText}\r\n").ToString());
Trace.WriteLine(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();
}
@ -59,7 +54,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(e.Message);
_log.LogError(log.ToString());
Trace.WriteLine(log.ToString());
if (cmd.Transaction != null) {
var curTran = TransactionCurrentThread;

View File

@ -1,9 +1,8 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using SafeObjectPool;
using SafeObjectPool;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Diagnostics;
using System.Linq;
using System.Threading;
@ -29,24 +28,6 @@ namespace FreeSql.Internal.CommonProvider {
public DbTransaction TransactionCurrentThread => _trans.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var conn) && conn.Transaction?.Connection != null ? conn.Transaction : null;
private Dictionary<int, List<string>> _preRemoveKeys = new Dictionary<int, List<string>>();
private object _preRemoveKeys_lock = new object();
public string[] PreRemove(params string[] key) {
var tid = Thread.CurrentThread.ManagedThreadId;
List<string> keys = null;
if (key == null || key.Any() == false) return _preRemoveKeys.TryGetValue(tid, out keys) ? keys.ToArray() : new string[0];
_log.LogDebug($"线程{tid}事务预删除 {JsonConvert.SerializeObject(key)}");
if (_preRemoveKeys.TryGetValue(tid, out keys) == false)
lock (_preRemoveKeys_lock)
if (_preRemoveKeys.TryGetValue(tid, out keys) == false) {
_preRemoveKeys.Add(tid, keys = new List<string>(key));
return key;
}
keys.AddRange(key);
return keys.ToArray();
}
public void TransactionPreRemoveCache(params string[] key) => PreRemove(key);
public void BeginTransaction(TimeSpan timeout) {
if (TransactionCurrentThread != null) return;
@ -58,7 +39,7 @@ namespace FreeSql.Internal.CommonProvider {
conn = MasterPool.Get();
tran = new Transaction2(conn, conn.Value.BeginTransaction(), timeout);
} catch(Exception ex) {
_log.LogError($"数据库出错(开启事务){ex.Message} \r\n{ex.StackTrace}");
Trace.WriteLine($"数据库出错(开启事务){ex.Message} \r\n{ex.StackTrace}");
MasterPool.Return(conn);
throw ex;
}
@ -84,22 +65,15 @@ namespace FreeSql.Internal.CommonProvider {
if (_trans.ContainsKey(tran.Conn.LastGetThreadId))
_trans.Remove(tran.Conn.LastGetThreadId);
var removeKeys = PreRemove();
if (_preRemoveKeys.ContainsKey(tran.Conn.LastGetThreadId))
lock (_preRemoveKeys_lock)
if (_preRemoveKeys.ContainsKey(tran.Conn.LastGetThreadId))
_preRemoveKeys.Remove(tran.Conn.LastGetThreadId);
Exception ex = null;
var f001 = isCommit ? "提交" : "回滚";
try {
_log.LogDebug($"线程{tran.Conn.LastGetThreadId}事务{f001}批量删除缓存key {Newtonsoft.Json.JsonConvert.SerializeObject(removeKeys)}");
_cache.Remove(removeKeys);
Trace.WriteLine($"线程{tran.Conn.LastGetThreadId}事务{f001}");
if (isCommit) tran.Transaction.Commit();
else tran.Transaction.Rollback();
} catch (Exception ex2) {
ex = ex2;
_log.LogError($"数据库出错({f001}事务):{ex.Message} {ex.StackTrace}");
Trace.WriteLine($"数据库出错({f001}事务):{ex.Message} {ex.StackTrace}");
} finally {
ReturnConnection(MasterPool, tran.Conn, ex); //MasterPool.Return(tran.Conn, ex);
}

View File

@ -5,7 +5,7 @@ using System.Linq.Expressions;
using System.Text;
namespace FreeSql.Internal.CommonProvider {
class AopProvider : IAop {
public class AopProvider : IAop {
public EventHandler<Aop.ToListEventArgs> ToList { get; set; }
public EventHandler<Aop.WhereEventArgs> Where { get; set; }
public EventHandler<Aop.ParseExpressionEventArgs> ParseExpression { get; set; }

View File

@ -1,186 +0,0 @@
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
class CacheProvider : ICache, IDisposable {
public IDistributedCache Cache { get; private set; }
private bool CacheSupportMultiRemove = false;
private static DateTime dt1970 = new DateTime(1970, 1, 1);
public CacheProvider(IDistributedCache cache, ILogger log) {
if (cache == null) cache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions { }));
Cache = cache;
var key1 = $"testCacheSupportMultiRemoveFreeSql{Guid.NewGuid().ToString("N")}";
var key2 = $"testCacheSupportMultiRemoveFreeSql{Guid.NewGuid().ToString("N")}";
Cache.Set(key1, new byte[] { 65 });
Cache.Set(key2, new byte[] { 65 });
try { Cache.Remove($"{key1}|{key2}"); } catch { } // redis-cluster 不允许执行 multi keys 命令
CacheSupportMultiRemove = Cache.Get(key1) == null && cache.Get(key2) == null;
if (CacheSupportMultiRemove == false) {
//log.LogWarning("FreeSql Warning: 低性能, IDistributedCache 没实现批量删除缓存 Cache.Remove(\"key1|key2\").");
Remove(key1, key2);
}
}
~CacheProvider() {
this.Dispose();
}
bool _isdisposed = false;
public void Dispose() {
if (_isdisposed) return;
Cache = null;
}
public Func<object, string> Serialize { get; set; }
public Func<string, Type, object> Deserialize { get; set; }
Func<JsonSerializerSettings> JsonSerializerSettings = () => {
var st = new JsonSerializerSettings();
st.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
st.DateFormatHandling = DateFormatHandling.IsoDateFormat;
st.DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
return st;
};
string SerializeObject(object value) {
if (Serialize != null) return Serialize(value);
return JsonConvert.SerializeObject(value, this.JsonSerializerSettings());
}
T DeserializeObject<T>(string value) {
if (Deserialize != null) return (T) Deserialize(value, typeof(T));
return JsonConvert.DeserializeObject<T>(value, this.JsonSerializerSettings());
}
public void Set<T>(string key, T data, int timeoutSeconds = 0) {
if (string.IsNullOrEmpty(key)) return;
Cache.Set(key, Encoding.UTF8.GetBytes(this.SerializeObject(data)), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(timeoutSeconds) });
}
public T Get<T>(string key) {
if (string.IsNullOrEmpty(key)) return default(T);
var value = Cache.Get(key);
if (value == null) return default(T);
return this.DeserializeObject<T>(Encoding.UTF8.GetString(value));
}
public string Get(string key) {
if (string.IsNullOrEmpty(key)) return null;
var value = Cache.Get(key);
if (value == null) return null;
return Encoding.UTF8.GetString(value);
}
async public Task SetAsync<T>(string key, T data, int timeoutSeconds = 0) {
if (string.IsNullOrEmpty(key)) return;
await Cache.SetAsync(key, Encoding.UTF8.GetBytes(this.SerializeObject(data)), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(timeoutSeconds) });
}
async public Task<T> GetAsync<T>(string key) {
if (string.IsNullOrEmpty(key)) return default(T);
var value = await Cache.GetAsync(key);
if (value == null) return default(T);
return this.DeserializeObject<T>(Encoding.UTF8.GetString(value));
}
async public Task<string> GetAsync(string key) {
if (string.IsNullOrEmpty(key)) return null;
var value = await Cache.GetAsync(key);
if (value == null) return null;
return Encoding.UTF8.GetString(value);
}
public void Remove(params string[] keys) {
if (keys == null || keys.Length == 0) return;
var keysDistinct = keys.Distinct();
if (CacheSupportMultiRemove) Cache.Remove(string.Join("|", keysDistinct));
else foreach (var key in keysDistinct) Cache.Remove(key);
}
async public Task RemoveAsync(params string[] keys) {
if (keys == null || keys.Length == 0) return;
var keysDistinct = keys.Distinct();
if (CacheSupportMultiRemove) await Cache.RemoveAsync(string.Join("|", keysDistinct));
else foreach (var key in keysDistinct) await Cache.RemoveAsync(key);
}
public T Shell<T>(string key, int timeoutSeconds, Func<T> getData) {
if (timeoutSeconds <= 0) return getData();
if (Cache == null) throw new Exception("缓存实现 IDistributedCache 为 null");
var cacheValue = Cache.Get(key);
if (cacheValue != null) {
try {
var txt = Encoding.UTF8.GetString(cacheValue);
return DeserializeObject<T>(txt);
} catch {
Cache.Remove(key);
throw;
}
}
var ret = getData();
Cache.Set(key, Encoding.UTF8.GetBytes(SerializeObject(ret)), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(timeoutSeconds) });
return ret;
}
public T Shell<T>(string key, string field, int timeoutSeconds, Func<T> getData) {
if (timeoutSeconds <= 0) return getData();
if (Cache == null) throw new Exception("缓存实现 IDistributedCache 为 null");
var hashkey = $"{key}:{field}";
var cacheValue = Cache.Get(hashkey);
if (cacheValue != null) {
try {
var txt = Encoding.UTF8.GetString(cacheValue);
var value = DeserializeObject<(T, long)>(txt);
if (DateTime.Now.Subtract(dt1970.AddSeconds(value.Item2)).TotalSeconds <= timeoutSeconds) return value.Item1;
} catch {
Cache.Remove(hashkey);
throw;
}
}
var ret = (getData(), (long) DateTime.Now.Subtract(dt1970).TotalSeconds);
Cache.Set(hashkey, Encoding.UTF8.GetBytes(SerializeObject(ret)));
return ret.Item1;
}
async public Task<T> ShellAsync<T>(string key, int timeoutSeconds, Func<Task<T>> getDataAsync) {
if (timeoutSeconds <= 0) return await getDataAsync();
if (Cache == null) throw new Exception("缓存实现 IDistributedCache 为 null");
var cacheValue = await Cache.GetAsync(key);
if (cacheValue != null) {
try {
var txt = Encoding.UTF8.GetString(cacheValue);
return DeserializeObject<T>(txt);
} catch {
await Cache.RemoveAsync(key);
throw;
}
}
var ret = await getDataAsync();
await Cache.SetAsync(key, Encoding.UTF8.GetBytes(SerializeObject(ret)), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(timeoutSeconds) });
return ret;
}
async public Task<T> ShellAsync<T>(string key, string field, int timeoutSeconds, Func<Task<T>> getDataAsync) {
if (timeoutSeconds <= 0) return await getDataAsync();
if (Cache == null) throw new Exception("缓存实现 IDistributedCache 为 null");
var hashkey = $"{key}:{field}";
var cacheValue = await Cache.GetAsync(hashkey);
if (cacheValue != null) {
try {
var txt = Encoding.UTF8.GetString(cacheValue);
var value = DeserializeObject<(T, long)>(txt);
if (DateTime.Now.Subtract(dt1970.AddSeconds(value.Item2)).TotalSeconds <= timeoutSeconds) return value.Item1;
} catch {
await Cache.RemoveAsync(hashkey);
throw;
}
}
var ret = (await getDataAsync(), (long) DateTime.Now.Subtract(dt1970).TotalSeconds);
await Cache.SetAsync(hashkey, Encoding.UTF8.GetBytes(SerializeObject(ret)));
return ret.Item1;
}
}
}

View File

@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
abstract partial class DeleteProvider<T1> : IDelete<T1> where T1 : class {
public abstract partial class DeleteProvider<T1> : IDelete<T1> where T1 : class {
protected IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;

View File

@ -11,7 +11,7 @@ using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
abstract partial class InsertProvider<T1> : IInsert<T1> where T1 : class {
public abstract partial class InsertProvider<T1> : IInsert<T1> where T1 : class {
protected IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
@ -69,7 +69,7 @@ namespace FreeSql.Internal.CommonProvider {
}
#region values数量限制
internal List<T1>[] SplitSource(int valuesLimit, int parameterLimit) {
protected List<T1>[] SplitSource(int valuesLimit, int parameterLimit) {
valuesLimit = valuesLimit - 1;
parameterLimit = parameterLimit - 1;
if (_source == null || _source.Any() == false) return new List<T1>[0];
@ -101,7 +101,7 @@ namespace FreeSql.Internal.CommonProvider {
return ret;
}
}
internal int SplitExecuteAffrows(int valuesLimit, int parameterLimit) {
protected int SplitExecuteAffrows(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0;
if (ss.Any() == false) {
@ -137,7 +137,7 @@ namespace FreeSql.Internal.CommonProvider {
ClearData();
return ret;
}
async internal Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit) {
async protected Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0;
if (ss.Any() == false) {
@ -173,7 +173,7 @@ namespace FreeSql.Internal.CommonProvider {
ClearData();
return ret;
}
internal long SplitExecuteIdentity(int valuesLimit, int parameterLimit) {
protected long SplitExecuteIdentity(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
long ret = 0;
if (ss.Any() == false) {
@ -211,7 +211,7 @@ namespace FreeSql.Internal.CommonProvider {
ClearData();
return ret;
}
async internal Task<long> SplitExecuteIdentityAsync(int valuesLimit, int parameterLimit) {
async protected Task<long> SplitExecuteIdentityAsync(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
long ret = 0;
if (ss.Any() == false) {
@ -249,7 +249,7 @@ namespace FreeSql.Internal.CommonProvider {
ClearData();
return ret;
}
internal List<T1> SplitExecuteInserted(int valuesLimit, int parameterLimit) {
protected List<T1> SplitExecuteInserted(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = new List<T1>();
if (ss.Any() == false) {
@ -285,7 +285,7 @@ namespace FreeSql.Internal.CommonProvider {
ClearData();
return ret;
}
async internal Task<List<T1>> SplitExecuteInsertedAsync(int valuesLimit, int parameterLimit) {
async protected Task<List<T1>> SplitExecuteInsertedAsync(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = new List<T1>();
if (ss.Any() == false) {
@ -323,7 +323,7 @@ namespace FreeSql.Internal.CommonProvider {
}
#endregion
internal int RawExecuteAffrows() {
protected int RawExecuteAffrows() {
var sql = ToSql();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
@ -341,7 +341,7 @@ namespace FreeSql.Internal.CommonProvider {
this.ClearData();
return affrows;
}
async internal Task<int> RawExecuteAffrowsAsync() {
async protected Task<int> RawExecuteAffrowsAsync() {
var sql = ToSql();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
@ -359,10 +359,10 @@ namespace FreeSql.Internal.CommonProvider {
this.ClearData();
return affrows;
}
internal abstract long RawExecuteIdentity();
internal abstract Task<long> RawExecuteIdentityAsync();
internal abstract List<T1> RawExecuteInserted();
internal abstract Task<List<T1>> RawExecuteInsertedAsync();
protected abstract long RawExecuteIdentity();
protected abstract Task<long> RawExecuteIdentityAsync();
protected abstract List<T1> RawExecuteInserted();
protected abstract Task<List<T1>> RawExecuteInsertedAsync();
public abstract int ExecuteAffrows();
public abstract Task<int> ExecuteAffrowsAsync();

View File

@ -14,16 +14,15 @@ using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
abstract class Select0Provider<TSelect, T1> : ISelect0<TSelect, T1> where TSelect : class where T1 : class {
public abstract class Select0Provider<TSelect, T1> : ISelect0<TSelect, T1> where TSelect : class where T1 : class {
protected int _limit, _skip;
protected string _select = "SELECT ", _orderby, _groupby, _having;
protected StringBuilder _where = new StringBuilder();
protected List<DbParameter> _params = new List<DbParameter>();
internal List<SelectTableInfo> _tables = new List<SelectTableInfo>();
protected List<SelectTableInfo> _tables = new List<SelectTableInfo>();
protected List<Func<Type, string, string>> _tableRules = new List<Func<Type, string, string>>();
protected StringBuilder _join = new StringBuilder();
protected (int seconds, string key) _cache = (0, null);
protected IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
@ -34,7 +33,7 @@ namespace FreeSql.Internal.CommonProvider {
protected bool _distinct;
protected Expression _selectExpression;
internal static void CopyData(Select0Provider<TSelect, T1> from, object to, ReadOnlyCollection<ParameterExpression> lambParms) {
public static void CopyData(Select0Provider<TSelect, T1> from, object to, ReadOnlyCollection<ParameterExpression> lambParms) {
var toType = to?.GetType();
if (toType == null) return;
toType.GetField("_limit", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._limit);
@ -63,7 +62,6 @@ namespace FreeSql.Internal.CommonProvider {
}
toType.GetField("_tableRules", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._tableRules);
toType.GetField("_join", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new StringBuilder().Append(from._join.ToString()));
toType.GetField("_cache", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._cache);
//toType.GetField("_orm", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._orm);
//toType.GetField("_commonUtils", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._commonUtils);
//toType.GetField("_commonExpression", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._commonExpression);
@ -109,10 +107,6 @@ namespace FreeSql.Internal.CommonProvider {
return (await this.ToListAsync<int>("1")).FirstOrDefault() == 1;
}
public TSelect Caching(int seconds, string key = null) {
_cache = (seconds, key);
return this as TSelect;
}
public long Count() => this.ToList<int>("count(1)").FirstOrDefault();
async public Task<long> CountAsync() => (await this.ToListAsync<int>("count(1)")).FirstOrDefault();
@ -220,166 +214,142 @@ namespace FreeSql.Internal.CommonProvider {
public DataTable ToDataTable(string field = null) {
var sql = this.ToSql(field);
if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = sql;
return _orm.Cache.Shell(_cache.key, _cache.seconds, () => {
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
DataTable ret = null;
Exception exception = null;
try {
ret = _orm.Ado.ExecuteDataTable(_connection, _transaction, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
return ret;
});
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
DataTable ret = null;
Exception exception = null;
try {
ret = _orm.Ado.ExecuteDataTable(_connection, _transaction, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
return ret;
}
public Task<DataTable> ToDataTableAsync(string field = null) {
async public Task<DataTable> ToDataTableAsync(string field = null) {
var sql = this.ToSql(field);
if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = sql;
return _orm.Cache.ShellAsync(_cache.key, _cache.seconds, async () => {
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
DataTable ret = null;
Exception exception = null;
try {
ret = await _orm.Ado.ExecuteDataTableAsync(_connection, _transaction, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
return ret;
});
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
DataTable ret = null;
Exception exception = null;
try {
ret = await _orm.Ado.ExecuteDataTableAsync(_connection, _transaction, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
return ret;
}
public List<TTuple> ToList<TTuple>(string field) {
var sql = this.ToSql(field);
if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = sql;
return _orm.Cache.Shell(_cache.key, _cache.seconds, () => {
var type = typeof(TTuple);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<TTuple>();
var flagStr = $"ToListField:{field}";
Exception exception = null;
try {
_orm.Ado.ExecuteReader(_connection, _transaction, dr => {
var read = Utils.ExecuteArrayRowReadClassOrTuple(flagStr, type, null, dr, 0, _commonUtils);
ret.Add((TTuple)read.Value);
}, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
return ret;
});
var type = typeof(TTuple);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<TTuple>();
var flagStr = $"ToListField:{field}";
Exception exception = null;
try {
_orm.Ado.ExecuteReader(_connection, _transaction, dr => {
var read = Utils.ExecuteArrayRowReadClassOrTuple(flagStr, type, null, dr, 0, _commonUtils);
ret.Add((TTuple)read.Value);
}, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
return ret;
}
public Task<List<TTuple>> ToListAsync<TTuple>(string field) {
async public Task<List<TTuple>> ToListAsync<TTuple>(string field) {
var sql = this.ToSql(field);
if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = sql;
return _orm.Cache.ShellAsync(_cache.key, _cache.seconds, async () => {
var type = typeof(TTuple);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<TTuple>();
var flagStr = $"ToListField:{field}";
Exception exception = null;
try {
await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => {
var read = Utils.ExecuteArrayRowReadClassOrTuple(flagStr, type, null, dr, 0, _commonUtils);
ret.Add((TTuple)read.Value);
return Task.CompletedTask;
}, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
return ret;
});
var type = typeof(TTuple);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<TTuple>();
var flagStr = $"ToListField:{field}";
Exception exception = null;
try {
await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => {
var read = Utils.ExecuteArrayRowReadClassOrTuple(flagStr, type, null, dr, 0, _commonUtils);
ret.Add((TTuple)read.Value);
return Task.CompletedTask;
}, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
return ret;
}
internal List<T1> ToListAfPrivate(string sql, GetAllFieldExpressionTreeInfo af, (string field, ReadAnonymousTypeInfo read, List<object> retlist)[] otherData) {
if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}";
return _orm.Cache.Shell(_cache.key, _cache.seconds, () => {
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
_orm.Ado.ExecuteReader(_connection, _transaction, dr => {
ret.Add(af.Read(_orm, dr));
if (otherData != null) {
var idx = af.FieldCount - 1;
foreach (var other in otherData)
other.retlist.Add(_commonExpression.ReadAnonymous(other.read, dr, ref idx, false));
}
}, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
while (_includeToList.Any()) _includeToList.Dequeue()?.Invoke(ret);
_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret));
_trackToList?.Invoke(ret);
return ret;
});
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
_orm.Ado.ExecuteReader(_connection, _transaction, dr => {
ret.Add(af.Read(_orm, dr));
if (otherData != null) {
var idx = af.FieldCount - 1;
foreach (var other in otherData)
other.retlist.Add(_commonExpression.ReadAnonymous(other.read, dr, ref idx, false));
}
}, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
while (_includeToList.Any()) _includeToList.Dequeue()?.Invoke(ret);
_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret));
_trackToList?.Invoke(ret);
return ret;
}
async internal Task<List<T1>> ToListAfPrivateAsync(string sql, GetAllFieldExpressionTreeInfo af, (string field, ReadAnonymousTypeInfo read, List<object> retlist)[] otherData) {
if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}";
return await _orm.Cache.ShellAsync(_cache.key, _cache.seconds, async () => {
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => {
ret.Add(af.Read(_orm, dr));
if (otherData != null) {
var idx = af.FieldCount - 1;
foreach (var other in otherData)
other.retlist.Add(_commonExpression.ReadAnonymous(other.read, dr, ref idx, false));
}
return Task.CompletedTask;
}, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
while (_includeToList.Any()) _includeToList.Dequeue()?.Invoke(ret);
_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret));
_trackToList?.Invoke(ret);
return ret;
});
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => {
ret.Add(af.Read(_orm, dr));
if (otherData != null) {
var idx = af.FieldCount - 1;
foreach (var other in otherData)
other.retlist.Add(_commonExpression.ReadAnonymous(other.read, dr, ref idx, false));
}
return Task.CompletedTask;
}, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
while (_includeToList.Any()) _includeToList.Dequeue()?.Invoke(ret);
_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret));
_trackToList?.Invoke(ret);
return ret;
}
internal List<T1> ToListPrivate(GetAllFieldExpressionTreeInfo af, (string field, ReadAnonymousTypeInfo read, List<object> retlist)[] otherData) {
string sql = null;
@ -427,60 +397,52 @@ namespace FreeSql.Internal.CommonProvider {
protected List<TReturn> ToListMapReader<TReturn>((ReadAnonymousTypeInfo map, string field) af) {
var sql = this.ToSql(af.field);
if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}";
return _orm.Cache.Shell(_cache.key, _cache.seconds, () => {
var type = typeof(TReturn);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<TReturn>();
Exception exception = null;
try {
_orm.Ado.ExecuteReader(_connection, _transaction, dr => {
var index = -1;
ret.Add((TReturn)_commonExpression.ReadAnonymous(af.map, dr, ref index, false));
}, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret));
_trackToList?.Invoke(ret);
return ret;
});
var type = typeof(TReturn);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<TReturn>();
Exception exception = null;
try {
_orm.Ado.ExecuteReader(_connection, _transaction, dr => {
var index = -1;
ret.Add((TReturn)_commonExpression.ReadAnonymous(af.map, dr, ref index, false));
}, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret));
_trackToList?.Invoke(ret);
return ret;
}
async protected Task<List<TReturn>> ToListMapReaderAsync<TReturn>((ReadAnonymousTypeInfo map, string field) af) {
var sql = this.ToSql(af.field);
if (_cache.seconds > 0 && string.IsNullOrEmpty(_cache.key)) _cache.key = $"{sql}{string.Join("|", _params.Select(a => a.Value))}";
return await _orm.Cache.ShellAsync(_cache.key, _cache.seconds, async () => {
var type = typeof(TReturn);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<TReturn>();
Exception exception = null;
try {
await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => {
var index = -1;
ret.Add((TReturn)_commonExpression.ReadAnonymous(af.map, dr, ref index, false));
return Task.CompletedTask;
}, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret));
_trackToList?.Invoke(ret);
return ret;
});
var type = typeof(TReturn);
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, Aop.CurdType.Select, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<TReturn>();
Exception exception = null;
try {
await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => {
var index = -1;
ret.Add((TReturn)_commonExpression.ReadAnonymous(af.map, dr, ref index, false));
return Task.CompletedTask;
}, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
_orm.Aop.ToList?.Invoke(this, new Aop.ToListEventArgs(ret));
_trackToList?.Invoke(ret);
return ret;
}
protected (ReadAnonymousTypeInfo map, string field) GetExpressionField(Expression newexp) {
var map = new ReadAnonymousTypeInfo();

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
abstract class Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>
public abstract class Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>
where T1 : class
where T2 : class
where T3 : class

View File

@ -16,7 +16,7 @@ using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
abstract class Select1Provider<T1> : Select0Provider<ISelect<T1>, T1>, ISelect<T1>
public abstract class Select1Provider<T1> : Select0Provider<ISelect<T1>, T1>, ISelect<T1>
where T1 : class {
public Select1Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) {

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
abstract class Select2Provider<T1, T2> : Select0Provider<ISelect<T1, T2>, T1>, ISelect<T1, T2>
public abstract class Select2Provider<T1, T2> : Select0Provider<ISelect<T1, T2>, T1>, ISelect<T1, T2>
where T1 : class
where T2 : class {

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
abstract class Select3Provider<T1, T2, T3> : Select0Provider<ISelect<T1, T2, T3>, T1>, ISelect<T1, T2, T3>
public abstract class Select3Provider<T1, T2, T3> : Select0Provider<ISelect<T1, T2, T3>, T1>, ISelect<T1, T2, T3>
where T1 : class
where T2 : class
where T3 : class {

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
abstract class Select4Provider<T1, T2, T3, T4> : Select0Provider<ISelect<T1, T2, T3, T4>, T1>, ISelect<T1, T2, T3, T4>
public abstract class Select4Provider<T1, T2, T3, T4> : Select0Provider<ISelect<T1, T2, T3, T4>, T1>, ISelect<T1, T2, T3, T4>
where T1 : class
where T2 : class
where T3 : class

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
abstract class Select5Provider<T1, T2, T3, T4, T5> : Select0Provider<ISelect<T1, T2, T3, T4, T5>, T1>, ISelect<T1, T2, T3, T4, T5>
public abstract class Select5Provider<T1, T2, T3, T4, T5> : Select0Provider<ISelect<T1, T2, T3, T4, T5>, T1>, ISelect<T1, T2, T3, T4, T5>
where T1 : class
where T2 : class
where T3 : class

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
abstract class Select6Provider<T1, T2, T3, T4, T5, T6> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6>, T1>, ISelect<T1, T2, T3, T4, T5, T6>
public abstract class Select6Provider<T1, T2, T3, T4, T5, T6> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6>, T1>, ISelect<T1, T2, T3, T4, T5, T6>
where T1 : class
where T2 : class
where T3 : class

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
abstract class Select7Provider<T1, T2, T3, T4, T5, T6, T7> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7>
public abstract class Select7Provider<T1, T2, T3, T4, T5, T6, T7> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7>
where T1 : class
where T2 : class
where T3 : class

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
abstract class Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8>
public abstract class Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8>
where T1 : class
where T2 : class
where T3 : class

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
abstract class Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>
public abstract class Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9> : Select0Provider<ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>, T1>, ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>
where T1 : class
where T2 : class
where T3 : class

View File

@ -8,7 +8,7 @@ using System.Text;
using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
class SelectGroupingProvider<TKey, TValue> : ISelectGrouping<TKey, TValue> {
public class SelectGroupingProvider<TKey, TValue> : ISelectGrouping<TKey, TValue> {
internal object _select;
internal ReadAnonymousTypeInfo _map;

View File

@ -11,7 +11,7 @@ using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider {
abstract partial class UpdateProvider<T1> : IUpdate<T1> where T1 : class {
public abstract partial class UpdateProvider<T1> : IUpdate<T1> where T1 : class {
protected IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
@ -106,7 +106,7 @@ namespace FreeSql.Internal.CommonProvider {
return ret;
}
}
internal int SplitExecuteAffrows(int valuesLimit, int parameterLimit) {
protected int SplitExecuteAffrows(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0;
if (ss.Length <= 1) {
@ -138,7 +138,7 @@ namespace FreeSql.Internal.CommonProvider {
ClearData();
return ret;
}
async internal Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit) {
async protected Task<int> SplitExecuteAffrowsAsync(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = 0;
if (ss.Length <= 1) {
@ -170,7 +170,7 @@ namespace FreeSql.Internal.CommonProvider {
ClearData();
return ret;
}
internal List<T1> SplitExecuteUpdated(int valuesLimit, int parameterLimit) {
protected List<T1> SplitExecuteUpdated(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = new List<T1>();
if (ss.Length <= 1) {
@ -202,7 +202,7 @@ namespace FreeSql.Internal.CommonProvider {
ClearData();
return ret;
}
async internal Task<List<T1>> SplitExecuteUpdatedAsync(int valuesLimit, int parameterLimit) {
async protected Task<List<T1>> SplitExecuteUpdatedAsync(int valuesLimit, int parameterLimit) {
var ss = SplitSource(valuesLimit, parameterLimit);
var ret = new List<T1>();
if (ss.Length <= 1) {
@ -236,7 +236,7 @@ namespace FreeSql.Internal.CommonProvider {
}
#endregion
internal int RawExecuteAffrows() {
protected int RawExecuteAffrows() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
var dbParms = _params.Concat(_paramsSource).ToArray();
@ -257,7 +257,7 @@ namespace FreeSql.Internal.CommonProvider {
this.ClearData();
return affrows;
}
async internal Task<int> RawExecuteAffrowsAsync() {
async protected Task<int> RawExecuteAffrowsAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
var dbParms = _params.Concat(_paramsSource).ToArray();
@ -278,8 +278,8 @@ namespace FreeSql.Internal.CommonProvider {
this.ClearData();
return affrows;
}
internal abstract List<T1> RawExecuteUpdated();
internal abstract Task<List<T1>> RawExecuteUpdatedAsync();
protected abstract List<T1> RawExecuteUpdated();
protected abstract Task<List<T1>> RawExecuteUpdatedAsync();
public abstract int ExecuteAffrows();
public abstract Task<int> ExecuteAffrowsAsync();

View File

@ -2,43 +2,46 @@
using FreeSql.DatabaseModel;
using FreeSql.Extensions.EntityUtil;
using FreeSql.Internal.Model;
using SafeObjectPool;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.Internal {
internal abstract class CommonUtils {
public abstract class CommonUtils {
internal abstract string GetNoneParamaterSqlValue(List<DbParameter> specialParams, Type type, object value);
internal abstract DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value);
internal abstract DbParameter[] GetDbParamtersByObject(string sql, object obj);
internal abstract string FormatSql(string sql, params object[] args);
internal abstract string QuoteSqlName(string name);
internal abstract string TrimQuoteSqlName(string name);
internal abstract string QuoteParamterName(string name);
internal abstract string IsNull(string sql, object value);
internal abstract string StringConcat(string[] objs, Type[] types);
internal abstract string Mod(string left, string right, Type leftType, Type rightType);
internal abstract string QuoteWriteParamter(Type type, string paramterName);
internal abstract string QuoteReadColumn(Type type, string columnName);
public abstract string GetNoneParamaterSqlValue(List<DbParameter> specialParams, Type type, object value);
public abstract DbParameter AppendParamter(List<DbParameter> _params, string parameterName, 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(string name);
public abstract string TrimQuoteSqlName(string name);
public abstract string QuoteParamterName(string name);
public abstract string IsNull(string sql, object value);
public abstract string StringConcat(string[] objs, Type[] types);
public abstract string Mod(string left, string right, Type leftType, Type rightType);
public abstract string QuoteWriteParamter(Type type, string paramterName);
public abstract string QuoteReadColumn(Type type, string columnName);
internal IFreeSql _orm { get; set; }
internal ICodeFirst CodeFirst => _orm.CodeFirst;
internal TableInfo GetTableByEntity(Type entity) => Utils.GetTableByEntity(entity, this);
internal List<DbTableInfo> dbTables { get; set; }
internal object dbTablesLock = new object();
public IFreeSql _orm { get; set; }
public ICodeFirst CodeFirst => _orm.CodeFirst;
public TableInfo GetTableByEntity(Type entity) => Utils.GetTableByEntity(entity, this);
public List<DbTableInfo> dbTables { get; set; }
public object dbTablesLock = new object();
public CommonUtils(IFreeSql orm) {
_orm = orm;
}
ConcurrentDictionary<Type, TableAttribute> dicConfigEntity = new ConcurrentDictionary<Type, TableAttribute>();
internal ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) {
public ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) {
if (entity == null) return _orm.CodeFirst;
var type = typeof(T);
var table = dicConfigEntity.GetOrAdd(type, new TableAttribute());
@ -47,7 +50,7 @@ namespace FreeSql.Internal {
Utils.RemoveTableByEntity(type, this); //remove cache
return _orm.CodeFirst;
}
internal ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) {
public ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) {
if (entity == null) return _orm.CodeFirst;
var table = dicConfigEntity.GetOrAdd(type, new TableAttribute());
var fluent = new TableFluent(type, table);
@ -55,10 +58,10 @@ namespace FreeSql.Internal {
Utils.RemoveTableByEntity(type, this); //remove cache
return _orm.CodeFirst;
}
internal TableAttribute GetConfigEntity(Type type) {
public TableAttribute GetConfigEntity(Type type) {
return dicConfigEntity.TryGetValue(type, out var trytb) ? trytb : null;
}
internal TableAttribute GetEntityTableAttribute(Type type) {
public TableAttribute GetEntityTableAttribute(Type type) {
TableAttribute attr = null;
if (_orm.Aop.ConfigEntity != null) {
var aope = new Aop.ConfigEntityEventArgs(type);
@ -84,7 +87,7 @@ namespace FreeSql.Internal {
if (!string.IsNullOrEmpty(attr.SelectFilter)) return attr;
return null;
}
internal ColumnAttribute GetEntityColumnAttribute(Type type, PropertyInfo proto) {
public ColumnAttribute GetEntityColumnAttribute(Type type, PropertyInfo proto) {
ColumnAttribute attr = null;
if (_orm.Aop.ConfigEntityProperty != null) {
var aope = new Aop.ConfigEntityPropertyEventArgs(type, proto);
@ -137,7 +140,7 @@ namespace FreeSql.Internal {
return ret;
}
internal string WhereObject(TableInfo table, string aliasAndDot, object dywhere) {
public string WhereObject(TableInfo table, string aliasAndDot, object dywhere) {
if (dywhere == null) return "";
var type = dywhere.GetType();
var primarys = table.Primarys;
@ -182,7 +185,7 @@ namespace FreeSql.Internal {
}
}
internal string WhereItems<TEntity>(TableInfo table, string aliasAndDot, IEnumerable<TEntity> items) {
public string WhereItems<TEntity>(TableInfo table, string aliasAndDot, IEnumerable<TEntity> items) {
if (items == null || items.Any() == false) return null;
if (table.Primarys.Any() == false) return null;
var its = items.Where(a => a != null).ToArray();
@ -231,5 +234,39 @@ namespace FreeSql.Internal {
}
return iidx == 1 ? sb.Remove(0, 5).Remove(sb.Length - 1, 1).ToString() : sb.Remove(0, 4).ToString();
}
public static void PrevReheatConnectionPool(ObjectPool<DbConnection> pool, int minPoolSize) {
if (minPoolSize <= 0) minPoolSize = Math.Min(5, pool.Policy.PoolSize);
if (minPoolSize > pool.Policy.PoolSize) minPoolSize = pool.Policy.PoolSize;
var initTestOk = true;
var initStartTime = DateTime.Now;
var initConns = new ConcurrentBag<Object<DbConnection>>();
try {
var conn = pool.Get();
initConns.Add(conn);
pool.Policy.OnCheckAvailable(conn);
} catch {
initTestOk = false; //预热一次失败,后面将不进行
}
for (var a = 1; initTestOk && a < minPoolSize; a += 10) {
if (initStartTime.Subtract(DateTime.Now).TotalSeconds > 3) break; //预热耗时超过3秒退出
var b = Math.Min(minPoolSize - a, 10); //每10个预热
var initTasks = new Task[b];
for (var c = 0; c < b; c++) {
initTasks[c] = Task.Run(() => {
try {
var conn = pool.Get();
initConns.Add(conn);
pool.Policy.OnCheckAvailable(conn);
} catch {
initTestOk = false; //有失败,下一组退出预热
}
});
}
Task.WaitAll(initTasks);
}
while (initConns.TryTake(out var conn)) pool.Return(conn);
}
}
}

View File

@ -4,7 +4,7 @@ using System.Reflection;
using System.Text;
namespace FreeSql.Internal.Model {
class ReadAnonymousTypeInfo {
public class ReadAnonymousTypeInfo {
public PropertyInfo Property { get; set; }
public string CsName { get; set; }
public Type CsType { get; set; }
@ -15,5 +15,5 @@ namespace FreeSql.Internal.Model {
public List<ReadAnonymousTypeInfo> Childs = new List<ReadAnonymousTypeInfo>();
public TableInfo Table { get; set; }
}
enum ReadAnonymousTypeInfoConsturctorType { Arguments, Properties }
public enum ReadAnonymousTypeInfoConsturctorType { Arguments, Properties }
}

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Text;
namespace FreeSql.Internal.Model {
class SelectColumnInfo {
public class SelectColumnInfo {
public ColumnInfo Column { get; set; }
public SelectTableInfo Table { get; set; }
}

View File

@ -1,7 +1,7 @@
using System.Linq.Expressions;
namespace FreeSql.Internal.Model {
class SelectTableInfo {
public class SelectTableInfo {
public TableInfo Table { get; set; }
private string _alias;
@ -18,5 +18,5 @@ namespace FreeSql.Internal.Model {
public ParameterExpression Parameter { get; set; }
public SelectTableInfoType Type { get; set; }
}
enum SelectTableInfoType { From, LeftJoin, InnerJoin, RightJoin, Parent }
public enum SelectTableInfoType { From, LeftJoin, InnerJoin, RightJoin, Parent }
}

View File

@ -1,6 +1,5 @@
using FreeSql.DataAnnotations;
using FreeSql.Internal.Model;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Concurrent;
@ -637,8 +636,9 @@ namespace FreeSql.Internal {
if (overrieds > 0) {
cscode.AppendLine("}");
Assembly assembly = null;
if (MethodLazyLoadingComplier.Value == null) throw new Exception("【延时加载】功能需要安装 FreeSql.Extensions.LazyLoading.dll可前往 nuget 下载");
try {
assembly = Generator.TemplateEngin._compiler.Value.CompileCode(cscode.ToString());
assembly = MethodLazyLoadingComplier.Value.Invoke(null, new object[] { cscode.ToString() }) as Assembly;
} catch (Exception ex) {
throw new Exception($"【延时加载】{trytbTypeName} 编译错误:{ex.Message}\r\n\r\n{cscode}");
}
@ -651,8 +651,12 @@ namespace FreeSql.Internal {
return tbc.TryGetValue(entity, out var trytb2) ? trytb2 : trytb;
}
static Lazy<MethodInfo> MethodLazyLoadingComplier = new Lazy<MethodInfo>(() => {
var type = Type.GetType("FreeSql.Extensions.LazyLoading.LazyLoadingComplier,FreeSql.Extensions.LazyLoading");
return type.GetMethod("CompileCode");
});
internal static T[] GetDbParamtersByObject<T>(string sql, object obj, string paramPrefix, Func<string, Type, object, T> constructorParamter) {
public static T[] GetDbParamtersByObject<T>(string sql, object obj, string paramPrefix, Func<string, Type, object, T> constructorParamter) {
if (string.IsNullOrEmpty(sql) || obj == null) return new T[0];
var ttype = typeof(T);
var type = obj.GetType();
@ -668,7 +672,7 @@ namespace FreeSql.Internal {
return ret.ToArray();
}
internal static Dictionary<Type, bool> dicExecuteArrayRowReadClassOrTuple = new Dictionary<Type, bool> {
public static Dictionary<Type, bool> dicExecuteArrayRowReadClassOrTuple = new Dictionary<Type, bool> {
[typeof(bool)] = true,
[typeof(sbyte)] = true,
[typeof(short)] = true,
@ -837,12 +841,14 @@ namespace FreeSql.Internal {
if (type == typeof(object) && indexes != null) {
Func<Type, int[], DbDataReader, int, CommonUtils, RowInfo> dynamicFunc = (type2, indexes2, row2, dataindex2, commonUtils2) => {
dynamic expando = new System.Dynamic.ExpandoObject(); //动态类型字段 可读可写
var expandodic = (IDictionary<string, object>)expando;
//dynamic expando = new DynamicDictionary(); //动态类型字段 可读可写
var expandodic = new Dictionary<string, object>();// (IDictionary<string, object>)expando;
var fc = row2.FieldCount;
for (var a = 0; a < fc; a++)
//expando[row2.GetName(a)] = row2.GetValue(a);
expandodic.Add(row2.GetName(a), row2.GetValue(a));
return new RowInfo(expando, fc);
//expando = expandodic;
return new RowInfo(expandodic, fc);
};
return dynamicFunc;// Expression.Lambda<Func<Type, int[], DbDataReader, int, RowInfo>>(null);
}
@ -1092,14 +1098,10 @@ namespace FreeSql.Internal {
static ConcurrentDictionary<Type, ConcurrentDictionary<Type, Func<object, object>>> _dicGetDataReaderValue = new ConcurrentDictionary<Type, ConcurrentDictionary<Type, Func<object, object>>>();
static MethodInfo MethodArrayGetValue = typeof(Array).GetMethod("GetValue", new[] { typeof(int) });
static MethodInfo MethodArrayGetLength = typeof(Array).GetMethod("GetLength", new[] { typeof(int) });
static MethodInfo MethodMygisGeometryParse = typeof(MygisGeometry).GetMethod("Parse", new[] { typeof(string) });
static MethodInfo MethodGuidTryParse = typeof(Guid).GetMethod("TryParse", new[] { typeof(string), typeof(Guid).MakeByRefType() });
static MethodInfo MethodEnumParse = typeof(Enum).GetMethod("Parse", new[] { typeof(Type), typeof(string), typeof(bool) });
static MethodInfo MethodConvertChangeType = typeof(Convert).GetMethod("ChangeType", new[] { typeof(object), typeof(Type) });
static MethodInfo MethodTimeSpanFromSeconds = typeof(TimeSpan).GetMethod("FromSeconds");
static MethodInfo MethodJTokenParse = typeof(JToken).GetMethod("Parse", new[] { typeof(string) });
static MethodInfo MethodJObjectParse = typeof(JObject).GetMethod("Parse", new[] { typeof(string) });
static MethodInfo MethodJArrayParse = typeof(JArray).GetMethod("Parse", new[] { typeof(string) });
static MethodInfo MethodSByteTryParse = typeof(sbyte).GetMethod("TryParse", new[] { typeof(string), typeof(sbyte).MakeByRefType() });
static MethodInfo MethodShortTryParse = typeof(short).GetMethod("TryParse", new[] { typeof(string), typeof(short).MakeByRefType() });
static MethodInfo MethodIntTryParse = typeof(int).GetMethod("TryParse", new[] { typeof(string), typeof(int).MakeByRefType() });
@ -1116,6 +1118,8 @@ namespace FreeSql.Internal {
static MethodInfo MethodDateTimeOffsetTryParse = typeof(DateTimeOffset).GetMethod("TryParse", new[] { typeof(string), typeof(DateTimeOffset).MakeByRefType() });
static MethodInfo MethodToString = typeof(Utils).GetMethod("ToStringConcat", BindingFlags.NonPublic | BindingFlags.Static, null, new[] { typeof(object) }, null);
static MethodInfo MethodBigIntegerParse = typeof(Utils).GetMethod("ToBigInteger", BindingFlags.NonPublic | BindingFlags.Static, null, new[] { typeof(string) }, null);
public static ConcurrentBag<Func<LabelTarget, Expression, string, Expression>> GetDataReaderValueBlockExpressionSwitchTypeFullName = new ConcurrentBag<Func<LabelTarget, Expression, string, Expression>>();
public static Expression GetDataReaderValueBlockExpression(Type type, Expression value) {
var returnTarget = Expression.Label(typeof(object));
var valueExp = Expression.Variable(typeof(object), "locvalue");
@ -1177,16 +1181,6 @@ namespace FreeSql.Internal {
}
);
break;
case "MygisPoint": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisPoint)));
case "MygisLineString": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisLineString)));
case "MygisPolygon": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisPolygon)));
case "MygisMultiPoint": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisMultiPoint)));
case "MygisMultiLineString": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisMultiLineString)));
case "MygisMultiPolygon": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodMygisGeometryParse, Expression.Convert(valueExp, typeof(string))), typeof(MygisMultiPolygon)));
case "Newtonsoft.Json.Linq.JToken": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJTokenParse, Expression.Convert(valueExp, typeof(string))), typeof(JToken)));
case "Newtonsoft.Json.Linq.JObject": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJObjectParse, Expression.Convert(valueExp, typeof(string))), typeof(JObject)));
case "Newtonsoft.Json.Linq.JArray": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJArrayParse, Expression.Convert(valueExp, typeof(string))), typeof(JArray)));
case "Npgsql.LegacyPostgis.PostgisGeometry": return Expression.Return(returnTarget, valueExp);
case "System.Numerics.BigInteger": return Expression.Return(returnTarget, Expression.Convert(Expression.Call(MethodBigIntegerParse, Expression.Call(MethodToString, valueExp)), typeof(object)));
case "System.TimeSpan":
ParameterExpression tryparseVarTsExp, valueStrExp;
@ -1373,6 +1367,12 @@ namespace FreeSql.Internal {
typeof(object))
);
break;
default:
foreach (var switchFunc in GetDataReaderValueBlockExpressionSwitchTypeFullName) {
var switchFuncRet = switchFunc(returnTarget, valueExp, type.FullName);
if (switchFuncRet != null) return switchFuncRet;
}
break;
}
Expression switchExp = null;
if (tryparseExp != null)
@ -1437,45 +1437,7 @@ namespace FreeSql.Internal {
});
return func(value);
}
internal static object GetDataReaderValue22(Type type, object value) {
if (value == null || value == DBNull.Value) return Activator.CreateInstance(type);
if (type.FullName == "System.Byte[]") return value;
if (type.IsArray) {
var elementType = type.GetElementType();
var valueArr = value as Array;
if (elementType == valueArr.GetType().GetElementType()) return value;
var len = valueArr.GetLength(0);
var ret = Array.CreateInstance(elementType, len);
for (var a = 0; a < len; a++) {
var item = valueArr.GetValue(a);
ret.SetValue(GetDataReaderValue22(elementType, item), a);
}
return ret;
}
if (type.IsNullableType()) type = type.GenericTypeArguments.First();
if (type.IsEnum) return Enum.Parse(type, string.Concat(value), true);
switch (type.FullName) {
case "System.Guid":
if (value.GetType() != type) return Guid.TryParse(string.Concat(value), out var tryguid) ? tryguid : Guid.Empty;
return value;
case "MygisPoint": return MygisPoint.Parse(string.Concat(value)) as MygisPoint;
case "MygisLineString": return MygisLineString.Parse(string.Concat(value)) as MygisLineString;
case "MygisPolygon": return MygisPolygon.Parse(string.Concat(value)) as MygisPolygon;
case "MygisMultiPoint": return MygisMultiPoint.Parse(string.Concat(value)) as MygisMultiPoint;
case "MygisMultiLineString": return MygisMultiLineString.Parse(string.Concat(value)) as MygisMultiLineString;
case "MygisMultiPolygon": return MygisMultiPolygon.Parse(string.Concat(value)) as MygisMultiPolygon;
case "Newtonsoft.Json.Linq.JToken": return JToken.Parse(string.Concat(value));
case "Newtonsoft.Json.Linq.JObject": return JObject.Parse(string.Concat(value));
case "Newtonsoft.Json.Linq.JArray": return JArray.Parse(string.Concat(value));
case "Npgsql.LegacyPostgis.PostgisGeometry": return value;
}
if (type != value.GetType()) {
if (type.FullName == "System.TimeSpan") return TimeSpan.FromSeconds(double.Parse(value.ToString()));
return Convert.ChangeType(value, type);
}
return value;
}
internal static string GetCsName(string name) {
public static string GetCsName(string name) {
name = Regex.Replace(name.TrimStart('@'), @"[^\w]", "_");
return char.IsLetter(name, 0) ? name : string.Concat("_", name);
}

View File

@ -1,78 +0,0 @@
using FreeSql.Internal;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.MySql.Curd {
class MySqlDelete<T1> : Internal.CommonProvider.DeleteProvider<T1> where T1 : class {
public MySqlDelete(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
: base(orm, commonUtils, commonExpression, dywhere) {
}
public override List<T1> ExecuteDeleted() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(sql).Append(" RETURNING ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
sql = sb.ToString();
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Delete, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
async public override Task<List<T1>> ExecuteDeletedAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(sql).Append(" RETURNING ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
sql = sb.ToString();
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Delete, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
}
}

View File

@ -1,126 +0,0 @@
using FreeSql.Internal;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.MySql.Curd {
class MySqlInsert<T1> : Internal.CommonProvider.InsertProvider<T1> where T1 : class {
public MySqlInsert(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression) {
}
public override int ExecuteAffrows() => base.SplitExecuteAffrows(5000, 3000);
public override Task<int> ExecuteAffrowsAsync() => base.SplitExecuteAffrowsAsync(5000, 3000);
public override long ExecuteIdentity() => base.SplitExecuteIdentity(5000, 3000);
public override Task<long> ExecuteIdentityAsync() => base.SplitExecuteIdentityAsync(5000, 3000);
public override List<T1> ExecuteInserted() => base.SplitExecuteInserted(5000, 3000);
public override Task<List<T1>> ExecuteInsertedAsync() => base.SplitExecuteInsertedAsync(5000, 3000);
internal override long RawExecuteIdentity() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
sql = string.Concat(sql, "; SELECT LAST_INSERT_ID();");
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
long ret = 0;
Exception exception = null;
try {
ret = long.TryParse(string.Concat(_orm.Ado.ExecuteScalar(_connection, _transaction, CommandType.Text, sql, _params)), out var trylng) ? trylng : 0;
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
async internal override Task<long> RawExecuteIdentityAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
sql = string.Concat(sql, "; SELECT LAST_INSERT_ID();");
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
long ret = 0;
Exception exception = null;
try {
ret = long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync(_connection, _transaction, CommandType.Text, sql, _params)), out var trylng) ? trylng : 0;
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
internal override List<T1> RawExecuteInserted() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(sql).Append(" RETURNING ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
sql = sb.ToString();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sql, _params);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
async internal override Task<List<T1>> RawExecuteInsertedAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(sql).Append(" RETURNING ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
sql = sb.ToString();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sql, _params);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
}
}

View File

@ -1,128 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace FreeSql.MySql.Curd {
class MySqlSelect<T1> : FreeSql.Internal.CommonProvider.Select1Provider<T1> where T1 : class {
internal static string ToSqlStatic(CommonUtils _commonUtils, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables, Func<Type, string, string> tableRuleInvoke, IFreeSql _orm) {
if (_orm.CodeFirst.IsAutoSyncStructure)
_orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray());
var sb = new StringBuilder();
var sbnav = new StringBuilder();
sb.Append(_select);
if (_distinct) sb.Append("DISTINCT ");
sb.Append(field).Append(" \r\nFROM ");
var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray();
var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray();
for (var a = 0; a < tbsfrom.Length; a++) {
sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[a].Table.Type, tbsfrom[a].Table.DbName))).Append(" ").Append(tbsfrom[a].Alias);
if (tbsjoin.Length > 0) {
//如果存在 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(tableRuleInvoke(tbsfrom[b].Table.Type, tbsfrom[b].Table.DbName))).Append(" ").Append(tbsfrom[b].Alias);
if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On)) sb.Append(" ON 1 = 1");
else sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On);
}
break;
} else {
if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")");
if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")");
}
if (a < tbsfrom.Length - 1) sb.Append(", ");
}
foreach (var tb in tbsjoin) {
if (tb.Type == SelectTableInfoType.Parent) continue;
switch (tb.Type) {
case SelectTableInfoType.LeftJoin:
sb.Append(" \r\nLEFT JOIN ");
break;
case SelectTableInfoType.InnerJoin:
sb.Append(" \r\nINNER JOIN ");
break;
case SelectTableInfoType.RightJoin:
sb.Append(" \r\nRIGHT JOIN ");
break;
}
sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tb.Table.Type, tb.Table.DbName))).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition);
if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")");
}
if (_join.Length > 0) sb.Append(_join);
sbnav.Append(_where);
foreach (var tb in _tables) {
if (tb.Type == SelectTableInfoType.Parent) continue;
if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false)
sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")");
}
if (sbnav.Length > 0) {
sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5));
}
if (string.IsNullOrEmpty(_groupby) == false) {
sb.Append(_groupby);
if (string.IsNullOrEmpty(_having) == false)
sb.Append(" \r\nHAVING ").Append(_having.Substring(5));
}
sb.Append(_orderby);
if (_skip > 0 || _limit > 0)
sb.Append(" \r\nlimit ").Append(Math.Max(0, _skip)).Append(",").Append(_limit > 0 ? _limit : -1);
sbnav.Clear();
return sb.ToString();
}
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override ISelect<T1, T2> From<T2>(Expression<Func<ISelectFromExpression<T1>, T2, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new MySqlSelect<T1, T2>(_orm, _commonUtils, _commonExpression, null); MySqlSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3> From<T2, T3>(Expression<Func<ISelectFromExpression<T1>, T2, T3, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new MySqlSelect<T1, T2, T3>(_orm, _commonUtils, _commonExpression, null); MySqlSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4> From<T2, T3, T4>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new MySqlSelect<T1, T2, T3, T4>(_orm, _commonUtils, _commonExpression, null); MySqlSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5> From<T2, T3, T4, T5>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new MySqlSelect<T1, T2, T3, T4, T5>(_orm, _commonUtils, _commonExpression, null); MySqlSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6> From<T2, T3, T4, T5, T6>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new MySqlSelect<T1, T2, T3, T4, T5, T6>(_orm, _commonUtils, _commonExpression, null); MySqlSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7> From<T2, T3, T4, T5, T6, T7>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new MySqlSelect<T1, T2, T3, T4, T5, T6, T7>(_orm, _commonUtils, _commonExpression, null); MySqlSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8> From<T2, T3, T4, T5, T6, T7, T8>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new MySqlSelect<T1, T2, T3, T4, T5, T6, T7, T8>(_orm, _commonUtils, _commonExpression, null); MySqlSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> From<T2, T3, T4, T5, T6, T7, T8, T9>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new MySqlSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>(_orm, _commonUtils, _commonExpression, null); MySqlSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new MySqlSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); MySqlSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class MySqlSelect<T1, T2> : FreeSql.Internal.CommonProvider.Select2Provider<T1, T2> where T1 : class where T2 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class MySqlSelect<T1, T2, T3> : FreeSql.Internal.CommonProvider.Select3Provider<T1, T2, T3> where T1 : class where T2 : class where T3 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class MySqlSelect<T1, T2, T3, T4> : FreeSql.Internal.CommonProvider.Select4Provider<T1, T2, T3, T4> where T1 : class where T2 : class where T3 : class where T4 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class MySqlSelect<T1, T2, T3, T4, T5> : FreeSql.Internal.CommonProvider.Select5Provider<T1, T2, T3, T4, T5> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class MySqlSelect<T1, T2, T3, T4, T5, T6> : FreeSql.Internal.CommonProvider.Select6Provider<T1, T2, T3, T4, T5, T6> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class MySqlSelect<T1, T2, T3, T4, T5, T6, T7> : FreeSql.Internal.CommonProvider.Select7Provider<T1, T2, T3, T4, T5, T6, T7> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class MySqlSelect<T1, T2, T3, T4, T5, T6, T7, T8> : FreeSql.Internal.CommonProvider.Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class MySqlSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> : FreeSql.Internal.CommonProvider.Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class MySqlSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : FreeSql.Internal.CommonProvider.Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class {
public MySqlSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => MySqlSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
}

View File

@ -1,119 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.MySql.Curd {
class MySqlUpdate<T1> : Internal.CommonProvider.UpdateProvider<T1> where T1 : class {
public MySqlUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
: base(orm, commonUtils, commonExpression, dywhere) {
}
public override int ExecuteAffrows() => base.SplitExecuteAffrows(500, 3000);
public override Task<int> ExecuteAffrowsAsync() => base.SplitExecuteAffrowsAsync(500, 3000);
public override List<T1> ExecuteUpdated() => base.SplitExecuteUpdated(500, 3000);
public override Task<List<T1>> ExecuteUpdatedAsync() => base.SplitExecuteUpdatedAsync(500, 3000);
internal override List<T1> RawExecuteUpdated() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(sql).Append(" RETURNING ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
sql = sb.ToString();
var dbParms = _params.Concat(_paramsSource).ToArray();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Update, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sql, dbParms);
ValidateVersionAndThrow(ret.Count);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
async internal override Task<List<T1>> RawExecuteUpdatedAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(sql).Append(" RETURNING ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
sql = sb.ToString();
var dbParms = _params.Concat(_paramsSource).ToArray();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Update, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sql, dbParms);
ValidateVersionAndThrow(ret.Count);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
if (_table.Primarys.Length == 1) {
caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().Attribute.MapType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
return;
}
caseWhen.Append("CONCAT(");
var pkidx = 0;
foreach (var pk in _table.Primarys) {
if (pkidx > 0) caseWhen.Append(", ");
caseWhen.Append(_commonUtils.QuoteReadColumn(pk.Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name)));
++pkidx;
}
caseWhen.Append(")");
}
protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
if (_table.Primarys.Length == 1) {
sb.Append(_commonUtils.FormatSql("{0}", _table.Primarys.First().GetMapValue(d)));
return;
}
sb.Append("CONCAT(");
var pkidx = 0;
foreach (var pk in _table.Primarys) {
if (pkidx > 0) sb.Append(", ");
sb.Append(_commonUtils.FormatSql("{0}", pk.GetMapValue(d)));
++pkidx;
}
sb.Append(")");
}
}
}

View File

@ -1,64 +0,0 @@
using FreeSql.Internal;
using Microsoft.Extensions.Logging;
using MySql.Data.MySqlClient;
using SafeObjectPool;
using System;
using System.Collections;
using System.Data.Common;
using System.Text;
using System.Threading;
namespace FreeSql.MySql {
class MySqlAdo : FreeSql.Internal.CommonProvider.AdoProvider {
public MySqlAdo() : base(null, null, DataType.MySql) { }
public MySqlAdo(CommonUtils util, ICache cache, ILogger log, string masterConnectionString, string[] slaveConnectionStrings) : base(cache, log, DataType.MySql) {
base._util = util;
if (!string.IsNullOrEmpty(masterConnectionString))
MasterPool = new MySqlConnectionPool("主库", masterConnectionString, null, null);
if (slaveConnectionStrings != null) {
foreach (var slaveConnectionString in slaveConnectionStrings) {
var slavePool = new MySqlConnectionPool($"从库{SlavePools.Count + 1}", slaveConnectionString, () => Interlocked.Decrement(ref slaveUnavailables), () => Interlocked.Increment(ref slaveUnavailables));
SlavePools.Add(slavePool);
}
}
}
static DateTime dt1970 = new DateTime(1970, 1, 1);
public override object AddslashesProcessParam(object param, Type mapType) {
if (param == null) return "NULL";
if (mapType != null && mapType != param.GetType())
param = Utils.GetDataReaderValue(mapType, param);
if (param is bool || param is bool?)
return (bool)param ? 1 : 0;
else if (param is string || param is char)
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
else if (param is Enum)
return string.Concat("'", param.ToString().Replace("'", "''"), "'"); //((Enum)val).ToInt64();
else if (decimal.TryParse(string.Concat(param), out var trydec))
return param;
else if (param is DateTime || param is DateTime?)
return string.Concat("'", ((DateTime)param).ToString("yyyy-MM-dd HH:mm:ss.fff"), "'");
else if (param is TimeSpan || param is TimeSpan?)
return ((TimeSpan)param).Ticks / 10;
else if (param is MygisGeometry)
return string.Concat("ST_GeomFromText('", (param as MygisGeometry).AsText().Replace("'", "''"), "')");
else if (param is IEnumerable) {
var sb = new StringBuilder();
var ie = param as IEnumerable;
foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType));
return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
}
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
}
protected override DbCommand CreateCommand() {
return new MySqlCommand();
}
protected override void ReturnConnection(ObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex) {
(pool as MySqlConnectionPool).Return(conn, ex);
}
protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj);
}
}

View File

@ -1,177 +0,0 @@
using MySql.Data.MySqlClient;
using SafeObjectPool;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace FreeSql.MySql {
class MySqlConnectionPool : ObjectPool<DbConnection> {
internal Action availableHandler;
internal Action unavailableHandler;
public MySqlConnectionPool(string name, string connectionString, Action availableHandler, Action unavailableHandler) : base(null) {
var policy = new MySqlConnectionPoolPolicy {
_pool = this,
Name = name
};
this.Policy = policy;
policy.ConnectionString = connectionString;
this.availableHandler = availableHandler;
this.unavailableHandler = unavailableHandler;
}
public void Return(Object<DbConnection> obj, Exception exception, bool isRecreate = false) {
if (exception != null && exception is MySqlException) {
try { if (obj.Value.Ping() == false) obj.Value.Open(); } catch { base.SetUnavailable(exception); }
}
base.Return(obj, isRecreate);
}
}
class MySqlConnectionPoolPolicy : IPolicy<DbConnection> {
internal MySqlConnectionPool _pool;
public string Name { get; set; } = "MySql MySqlConnection 对象池";
public int PoolSize { get; set; } = 100;
public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
public TimeSpan IdleTimeout { get; set; } = TimeSpan.Zero;
public int AsyncGetCapacity { get; set; } = 10000;
public bool IsThrowGetTimeoutException { get; set; } = true;
public int CheckAvailableInterval { get; set; } = 5;
static ConcurrentDictionary<string, int> dicConnStrIncr = new ConcurrentDictionary<string, int>(StringComparer.CurrentCultureIgnoreCase);
private string _connectionString;
public string ConnectionString {
get => _connectionString;
set {
_connectionString = value ?? "";
var pattern = @"Max\s*pool\s*size\s*=\s*(\d+)";
var m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success == false || int.TryParse(m.Groups[1].Value, out var poolsize) == false || poolsize <= 0) poolsize = 100;
var connStrIncr = dicConnStrIncr.AddOrUpdate(_connectionString, 1, (oldkey, oldval) => oldval + 1);
PoolSize = poolsize + connStrIncr;
_connectionString = m.Success ?
Regex.Replace(_connectionString, pattern, $"Max pool size={PoolSize}", RegexOptions.IgnoreCase) :
$"{_connectionString};Max pool size={PoolSize}";
pattern = @"Connection\s*LifeTime\s*=\s*(\d+)";
m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success) {
IdleTimeout = TimeSpan.FromSeconds(int.Parse(m.Groups[1].Value));
_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase);
}
var minPoolSize = 0;
pattern = @"Min\s*pool\s*size\s*=\s*(\d+)";
m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success) {
minPoolSize = int.Parse(m.Groups[1].Value);
_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase);
}
FreeUtil.PrevReheatConnectionPool(_pool, minPoolSize);
}
}
public bool OnCheckAvailable(Object<DbConnection> obj) {
if (obj.Value.State == ConnectionState.Closed) obj.Value.Open();
return obj.Value.Ping(true);
}
public DbConnection OnCreate() {
var conn = new MySqlConnection(_connectionString);
return conn;
}
public void OnDestroy(DbConnection obj) {
if (obj.State != ConnectionState.Closed) obj.Close();
obj.Dispose();
}
public void OnGet(Object<DbConnection> obj) {
if (_pool.IsAvailable) {
if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && obj.Value.Ping() == false) {
try {
obj.Value.Open();
} catch (Exception ex) {
if (_pool.SetUnavailable(ex) == true)
throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}");
}
}
}
}
async public Task OnGetAsync(Object<DbConnection> obj) {
if (_pool.IsAvailable) {
if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && (await obj.Value.PingAsync()) == false) {
try {
await obj.Value.OpenAsync();
} catch (Exception ex) {
if (_pool.SetUnavailable(ex) == true)
throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}");
}
}
}
}
public void OnGetTimeout() {
}
public void OnReturn(Object<DbConnection> obj) {
}
public void OnAvailable() {
_pool.availableHandler?.Invoke();
}
public void OnUnavailable() {
_pool.unavailableHandler?.Invoke();
}
}
static class DbConnectionExtensions {
static DbCommand PingCommand(DbConnection conn) {
var cmd = conn.CreateCommand();
cmd.CommandTimeout = 5;
cmd.CommandText = "select 1";
return cmd;
}
public static bool Ping(this DbConnection that, bool isThrow = false) {
try {
PingCommand(that).ExecuteNonQuery();
return true;
} catch {
if (that.State != ConnectionState.Closed) try { that.Close(); } catch { }
if (isThrow) throw;
return false;
}
}
async public static Task<bool> PingAsync(this DbConnection that, bool isThrow = false) {
try {
await PingCommand(that).ExecuteNonQueryAsync();
return true;
} catch {
if (that.State != ConnectionState.Closed) try { that.Close(); } catch { }
if (isThrow) throw;
return false;
}
}
}
}

View File

@ -1,292 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
public struct MygisCoordinate2D : IEquatable<MygisCoordinate2D> {
public double X { get; }
public double Y { get; }
public MygisCoordinate2D(double x, double y) { X = x; Y = y; }
public bool Equals(MygisCoordinate2D c) => X == c.X && Y == c.Y;
public override int GetHashCode() => X.GetHashCode() ^ MygisGeometry.RotateShift(Y.GetHashCode(), sizeof(int) / 2);
public override bool Equals(object obj) => obj is MygisCoordinate2D && Equals((MygisCoordinate2D) obj);
public static bool operator ==(MygisCoordinate2D left, MygisCoordinate2D right) => Equals(left, right);
public static bool operator !=(MygisCoordinate2D left, MygisCoordinate2D right) => !Equals(left, right);
}
public abstract class MygisGeometry {
protected abstract int GetLenHelper();
internal int GetLen(bool includeSRID) => 5 + (SRID == 0 || !includeSRID ? 0 : 4) + GetLenHelper();
public uint SRID { get; set; } = 0;
internal static int RotateShift(int val, int shift) => (val << shift) | (val >> (sizeof(int) - shift));
public override string ToString() => this.AsText();
public string AsText() {
if (this is MygisPoint) {
var obj = this as MygisPoint;
return $"POINT({obj.X} {obj.Y})";
}
if (this is MygisLineString) {
var obj = this as MygisLineString;
return obj?.PointCount > 0 ? $"LINESTRING({string.Join(",", obj.Select(a => $"{a.X} {a.Y}"))})" : null;
}
if (this is MygisPolygon) {
var obj = (this as MygisPolygon).Where(z => z.Count() > 1 && z.First().Equals(z.Last()));
return obj.Any() ? $"POLYGON(({string.Join("),(", obj.Select(c => string.Join(",", c.Select(a => $"{a.X} {a.Y}"))))}))" : null;
}
if (this is MygisMultiPoint) {
var obj = this as MygisMultiPoint;
return obj?.PointCount > 0 ? $"MULTIPOINT({string.Join(",", obj.Select(a => $"{a.X} {a.Y}"))})" : null;
}
if (this is MygisMultiLineString) {
var obj = this as MygisMultiLineString;
return obj.LineCount > 0 ? $"MULTILINESTRING(({string.Join("),(", obj.Select(c => string.Join(",", c.Select(a => $"{a.X} {a.Y}"))))}))" : null;
}
if (this is MygisMultiPolygon) {
var obj = (this as MygisMultiPolygon)?.Where(z => z.Where(y => y.Count() > 1 && y.First().Equals(y.Last())).Any());
return obj.Any() ? $"MULTIPOLYGON((({string.Join(")),((", obj.Select(d => string.Join("),(", d.Select(c => string.Join(",", c.Select(a => $"{a.X} {a.Y}"))))))})))" : null;
}
return base.ToString();
}
static readonly Regex regexMygisPoint = new Regex(@"\s*(-?\d+\.?\d*)\s+(-?\d+\.?\d*)\s*");
static readonly Regex regexSplit1 = new Regex(@"\)\s*,\s*\(");
static readonly Regex regexSplit2 = new Regex(@"\)\s*\)\s*,\s*\(\s*\(");
public static MygisGeometry Parse(string wkt) {
if (string.IsNullOrEmpty(wkt)) return null;
wkt = wkt.Trim();
if (wkt.StartsWith("point", StringComparison.CurrentCultureIgnoreCase)) return ParsePoint(wkt.Substring(5).Trim('(', ')'));
else if (wkt.StartsWith("linestring", StringComparison.CurrentCultureIgnoreCase)) return new MygisLineString(ParseLineString(wkt.Substring(10).Trim('(', ')')));
else if (wkt.StartsWith("polygon", StringComparison.CurrentCultureIgnoreCase)) return new MygisPolygon(ParsePolygon(wkt.Substring(7).Trim('(', ')')));
else if (wkt.StartsWith("multipoint", StringComparison.CurrentCultureIgnoreCase)) return new MygisMultiPoint(ParseLineString(wkt.Substring(10).Trim('(', ')')));
else if (wkt.StartsWith("multilinestring", StringComparison.CurrentCultureIgnoreCase)) return new MygisMultiLineString(ParseMultiLineString(wkt.Substring(15).Trim('(', ')')));
else if (wkt.StartsWith("multipolygon", StringComparison.CurrentCultureIgnoreCase)) return new MygisMultiPolygon(ParseMultiPolygon(wkt.Substring(12).Trim('(', ')')));
throw new NotImplementedException($"MygisGeometry.Parse 未实现 \"{wkt}\"");
}
static MygisPoint ParsePoint(string str) {
var m = regexMygisPoint.Match(str);
if (m.Success == false) return null;
return new MygisPoint(double.TryParse(m.Groups[1].Value, out var tryd) ? tryd : 0, double.TryParse(m.Groups[2].Value, out tryd) ? tryd : 0);
}
static MygisCoordinate2D[] ParseLineString(string str) {
var ms = regexMygisPoint.Matches(str);
var points = new MygisCoordinate2D[ms.Count];
for (var a = 0; a < ms.Count; a++) points[a] = new MygisCoordinate2D(double.TryParse(ms[a].Groups[1].Value, out var tryd) ? tryd : 0, double.TryParse(ms[a].Groups[2].Value, out tryd) ? tryd : 0);
return points;
}
static MygisCoordinate2D[][] ParsePolygon(string str) {
return regexSplit1.Split(str).Select(s => ParseLineString(s)).Where(a => a.Length > 1 && a.First().Equals(a.Last())).ToArray();
}
static MygisLineString[] ParseMultiLineString(string str) {
return regexSplit1.Split(str).Select(s => new MygisLineString(ParseLineString(s))).ToArray();
}
static MygisPolygon[] ParseMultiPolygon(string str) {
return regexSplit2.Split(str).Select(s => new MygisPolygon(ParsePolygon(s))).ToArray();
}
}
public class MygisPoint : MygisGeometry, IEquatable<MygisPoint> {
MygisCoordinate2D _coord;
protected override int GetLenHelper() => 16;
public double X => _coord.X;
public double Y => _coord.Y;
public MygisPoint(double x, double y) {
_coord = new MygisCoordinate2D(x, y);
}
public bool Equals(MygisPoint other) => !ReferenceEquals(other, null) && _coord.Equals(other._coord);
public override bool Equals(object obj) => Equals(obj as MygisPoint);
public static bool operator ==(MygisPoint x, MygisPoint y) => ReferenceEquals(x, null) ? ReferenceEquals(y, null) : x.Equals(y);
public static bool operator !=(MygisPoint x, MygisPoint y) => !(x == y);
public override int GetHashCode() => X.GetHashCode() ^ RotateShift(Y.GetHashCode(), sizeof(int) / 2);
}
public class MygisLineString : MygisGeometry, IEquatable<MygisLineString>, IEnumerable<MygisCoordinate2D> {
readonly MygisCoordinate2D[] _points;
protected override int GetLenHelper() => 4 + _points.Length * 16;
public IEnumerator<MygisCoordinate2D> GetEnumerator() => ((IEnumerable<MygisCoordinate2D>) _points).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public MygisCoordinate2D this[int index] => _points[index];
public int PointCount => _points.Length;
public MygisLineString(IEnumerable<MygisCoordinate2D> points) {
_points = points.ToArray();
}
public MygisLineString(MygisCoordinate2D[] points) {
_points = points;
}
public bool Equals(MygisLineString other) {
if (ReferenceEquals(other, null)) return false;
if (_points.Length != other._points.Length) return false;
for (var i = 0; i < _points.Length; i++)
if (!_points[i].Equals(other._points[i])) return false;
return true;
}
public override bool Equals(object obj) => Equals(obj as MygisLineString);
public static bool operator ==(MygisLineString x, MygisLineString y) => ReferenceEquals(x, null) ? ReferenceEquals(y, null) : x.Equals(y);
public static bool operator !=(MygisLineString x, MygisLineString y) => !(x == y);
public override int GetHashCode() {
var ret = 266370105;//seed with something other than zero to make paths of all zeros hash differently.
foreach (var t in _points) ret ^= RotateShift(t.GetHashCode(), ret % sizeof(int));
return ret;
}
}
public class MygisPolygon : MygisGeometry, IEquatable<MygisPolygon>, IEnumerable<IEnumerable<MygisCoordinate2D>> {
readonly MygisCoordinate2D[][] _rings;
protected override int GetLenHelper() => 4 + _rings.Length * 4 + TotalPointCount * 16;
public MygisCoordinate2D this[int ringIndex, int pointIndex] => _rings[ringIndex][pointIndex];
public MygisCoordinate2D[] this[int ringIndex] => _rings[ringIndex];
public IEnumerator<IEnumerable<MygisCoordinate2D>> GetEnumerator() => ((IEnumerable<IEnumerable<MygisCoordinate2D>>) _rings).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public int RingCount => _rings.Length;
public int TotalPointCount => _rings.Sum(r => r.Length);
public MygisPolygon(MygisCoordinate2D[][] rings) {
_rings = rings;
}
public MygisPolygon(IEnumerable<IEnumerable<MygisCoordinate2D>> rings) {
_rings = rings.Select(x => x.ToArray()).ToArray();
}
public bool Equals(MygisPolygon other) {
if (ReferenceEquals(other, null)) return false;
if (_rings.Length != other._rings.Length) return false;
for (var i = 0; i < _rings.Length; i++) {
if (_rings[i].Length != other._rings[i].Length) return false;
for (var j = 0; j < _rings[i].Length; j++)
if (!_rings[i][j].Equals(other._rings[i][j])) return false;
}
return true;
}
public override bool Equals(object obj) => Equals(obj as MygisPolygon);
public static bool operator ==(MygisPolygon x, MygisPolygon y) => ReferenceEquals(x, null) ? ReferenceEquals(y, null) : x.Equals(y);
public static bool operator !=(MygisPolygon x, MygisPolygon y) => !(x == y);
public override int GetHashCode() {
var ret = 266370105;//seed with something other than zero to make paths of all zeros hash differently.
for (var i = 0; i < _rings.Length; i++)
for (var j = 0; j < _rings[i].Length; j++)
ret ^= RotateShift(_rings[i][j].GetHashCode(), ret % sizeof(int));
return ret;
}
}
public class MygisMultiPoint : MygisGeometry, IEquatable<MygisMultiPoint>, IEnumerable<MygisCoordinate2D> {
readonly MygisCoordinate2D[] _points;
protected override int GetLenHelper() => 4 + _points.Length * 21;
public IEnumerator<MygisCoordinate2D> GetEnumerator() => ((IEnumerable<MygisCoordinate2D>) _points).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public MygisCoordinate2D this[int indexer] => _points[indexer];
public int PointCount => _points.Length;
public MygisMultiPoint(MygisCoordinate2D[] points) {
_points = points;
}
public MygisMultiPoint(IEnumerable<MygisPoint> points) {
_points = points.Select(x => new MygisCoordinate2D(x.X, x.Y)).ToArray();
}
public MygisMultiPoint(IEnumerable<MygisCoordinate2D> points) {
_points = points.ToArray();
}
public bool Equals(MygisMultiPoint other) {
if (ReferenceEquals(other, null)) return false;
if (_points.Length != other._points.Length) return false;
for (var i = 0; i < _points.Length; i++)
if (!_points[i].Equals(other._points[i])) return false;
return true;
}
public override bool Equals(object obj) => Equals(obj as MygisMultiPoint);
public static bool operator ==(MygisMultiPoint x, MygisMultiPoint y) => ReferenceEquals(x, null) ? ReferenceEquals(y, null) : x.Equals(y);
public static bool operator !=(MygisMultiPoint x, MygisMultiPoint y) => !(x == y);
public override int GetHashCode() {
var ret = 266370105;//seed with something other than zero to make paths of all zeros hash differently.
for (var i = 0; i < _points.Length; i++) ret ^= RotateShift(_points[i].GetHashCode(), ret % sizeof(int));
return ret;
}
}
public sealed class MygisMultiLineString : MygisGeometry,
IEquatable<MygisMultiLineString>, IEnumerable<MygisLineString> {
readonly MygisLineString[] _lineStrings;
protected override int GetLenHelper() {
var n = 4;
for (var i = 0; i < _lineStrings.Length; i++) n += _lineStrings[i].GetLen(false);
return n;
}
public IEnumerator<MygisLineString> GetEnumerator() => ((IEnumerable<MygisLineString>) _lineStrings).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public MygisLineString this[int index] => _lineStrings[index];
public int LineCount => _lineStrings.Length;
internal MygisMultiLineString(MygisCoordinate2D[][] pointArray) {
_lineStrings = new MygisLineString[pointArray.Length];
for (var i = 0; i < pointArray.Length; i++)
_lineStrings[i] = new MygisLineString(pointArray[i]);
}
public MygisMultiLineString(MygisLineString[] linestrings) {
_lineStrings = linestrings;
}
public MygisMultiLineString(IEnumerable<MygisLineString> linestrings) {
_lineStrings = linestrings.ToArray();
}
public MygisMultiLineString(IEnumerable<IEnumerable<MygisCoordinate2D>> pointList) {
_lineStrings = pointList.Select(x => new MygisLineString(x)).ToArray();
}
public bool Equals(MygisMultiLineString other) {
if (ReferenceEquals(other, null)) return false;
if (_lineStrings.Length != other._lineStrings.Length) return false;
for (var i = 0; i < _lineStrings.Length; i++)
if (_lineStrings[i] != other._lineStrings[i]) return false;
return true;
}
public override bool Equals(object obj) => Equals(obj as MygisMultiLineString);
public static bool operator ==(MygisMultiLineString x, MygisMultiLineString y) => ReferenceEquals(x, null) ? ReferenceEquals(y, null) : x.Equals(y);
public static bool operator !=(MygisMultiLineString x, MygisMultiLineString y) => !(x == y);
public override int GetHashCode() {
var ret = 266370105;//seed with something other than zero to make paths of all zeros hash differently.
for (var i = 0; i < _lineStrings.Length; i++) ret ^= RotateShift(_lineStrings[i].GetHashCode(), ret % sizeof(int));
return ret;
}
}
public class MygisMultiPolygon : MygisGeometry, IEquatable<MygisMultiPolygon>, IEnumerable<MygisPolygon> {
readonly MygisPolygon[] _polygons;
protected override int GetLenHelper() {
var n = 4;
for (var i = 0; i < _polygons.Length; i++) n += _polygons[i].GetLen(false);
return n;
}
public IEnumerator<MygisPolygon> GetEnumerator() => ((IEnumerable<MygisPolygon>) _polygons).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public MygisPolygon this[int index] => _polygons[index];
public int PolygonCount => _polygons.Length;
public MygisMultiPolygon(MygisPolygon[] polygons) {
_polygons = polygons;
}
public MygisMultiPolygon(IEnumerable<MygisPolygon> polygons) {
_polygons = polygons.ToArray();
}
public MygisMultiPolygon(IEnumerable<IEnumerable<IEnumerable<MygisCoordinate2D>>> ringList) {
_polygons = ringList.Select(x => new MygisPolygon(x)).ToArray();
}
public bool Equals(MygisMultiPolygon other) {
if (ReferenceEquals(other, null)) return false;
if (_polygons.Length != other._polygons.Length) return false;
for (var i = 0; i < _polygons.Length; i++) if (_polygons[i] != other._polygons[i]) return false;
return true;
}
public override bool Equals(object obj) => obj is MygisMultiPolygon && Equals((MygisMultiPolygon) obj);
public static bool operator ==(MygisMultiPolygon x, MygisMultiPolygon y) => ReferenceEquals(x, null) ? ReferenceEquals(y, null) : x.Equals(y);
public static bool operator !=(MygisMultiPolygon x, MygisMultiPolygon y) => !(x == y);
public override int GetHashCode() {
var ret = 266370105;//seed with something other than zero to make paths of all zeros hash differently.
for (var i = 0; i < _polygons.Length; i++) ret ^= RotateShift(_polygons[i].GetHashCode(), ret % sizeof(int));
return ret;
}
}

View File

@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Reflection;
using System.Text;
public static partial class MygisTypesExtensions {
/// <summary>
/// 测量两个经纬度的距离,返回单位:米
/// </summary>
/// <param name="that">经纬坐标1</param>
/// <param name="point">经纬坐标2</param>
/// <returns>返回距离(单位:米)</returns>
public static double Distance(this MygisPoint that, MygisPoint point) {
double radLat1 = (double)(that.Y) * Math.PI / 180d;
double radLng1 = (double)(that.X) * Math.PI / 180d;
double radLat2 = (double)(point.Y) * Math.PI / 180d;
double radLng2 = (double)(point.X) * Math.PI / 180d;
return 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin((radLat1 - radLat2) / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin((radLng1 - radLng2) / 2), 2))) * 6378137;
}
}

View File

@ -1,325 +0,0 @@
using FreeSql.DataAnnotations;
using FreeSql.DatabaseModel;
using FreeSql.Internal;
using FreeSql.Internal.Model;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace FreeSql.MySql {
class MySqlCodeFirst : ICodeFirst {
IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
public MySqlCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) {
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
}
public bool IsAutoSyncStructure { get; set; } = false;
public bool IsSyncStructureToLower { get; set; } = false;
public bool IsSyncStructureToUpper { get; set; } = false;
public bool IsConfigEntityFromDbFirst { get; set; } = false;
public bool IsNoneCommandParameter { get; set; } = false;
public bool IsLazyLoading { get; set; } = false;
static object _dicCsToDbLock = new object();
static Dictionary<string, (MySqlDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)> _dicCsToDb = new Dictionary<string, (MySqlDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)>() {
{ typeof(bool).FullName, (MySqlDbType.Bit, "bit","bit(1) NOT NULL", null, false, false) },{ typeof(bool?).FullName, (MySqlDbType.Bit, "bit","bit(1)", null, true, null) },
{ typeof(sbyte).FullName, (MySqlDbType.Byte, "tinyint", "tinyint(3) NOT NULL", false, false, 0) },{ typeof(sbyte?).FullName, (MySqlDbType.Byte, "tinyint", "tinyint(3)", false, true, null) },
{ typeof(short).FullName, (MySqlDbType.Int16, "smallint","smallint(6) NOT NULL", false, false, 0) },{ typeof(short?).FullName, (MySqlDbType.Int16, "smallint", "smallint(6)", false, true, null) },
{ typeof(int).FullName, (MySqlDbType.Int32, "int", "int(11) NOT NULL", false, false, 0) },{ typeof(int?).FullName, (MySqlDbType.Int32, "int", "int(11)", false, true, null) },
{ typeof(long).FullName, (MySqlDbType.Int64, "bigint","bigint(20) NOT NULL", false, false, 0) },{ typeof(long?).FullName, (MySqlDbType.Int64, "bigint","bigint(20)", false, true, null) },
{ typeof(byte).FullName, (MySqlDbType.UByte, "tinyint","tinyint(3) unsigned NOT NULL", true, false, 0) },{ typeof(byte?).FullName, (MySqlDbType.UByte, "tinyint","tinyint(3) unsigned", true, true, null) },
{ typeof(ushort).FullName, (MySqlDbType.UInt16, "smallint","smallint(5) unsigned NOT NULL", true, false, 0) },{ typeof(ushort?).FullName, (MySqlDbType.UInt16, "smallint", "smallint(5) unsigned", true, true, null) },
{ typeof(uint).FullName, (MySqlDbType.UInt32, "int", "int(10) unsigned NOT NULL", true, false, 0) },{ typeof(uint?).FullName, (MySqlDbType.UInt32, "int", "int(10) unsigned", true, true, null) },
{ typeof(ulong).FullName, (MySqlDbType.UInt64, "bigint", "bigint(20) unsigned NOT NULL", true, false, 0) },{ typeof(ulong?).FullName, (MySqlDbType.UInt64, "bigint", "bigint(20) unsigned", true, true, null) },
{ typeof(double).FullName, (MySqlDbType.Double, "double", "double NOT NULL", false, false, 0) },{ typeof(double?).FullName, (MySqlDbType.Double, "double", "double", false, true, null) },
{ typeof(float).FullName, (MySqlDbType.Float, "float","float NOT NULL", false, false, 0) },{ typeof(float?).FullName, (MySqlDbType.Float, "float","float", false, true, null) },
{ typeof(decimal).FullName, (MySqlDbType.Decimal, "decimal", "decimal(10,2) NOT NULL", false, false, 0) },{ typeof(decimal?).FullName, (MySqlDbType.Decimal, "decimal", "decimal(10,2)", false, true, null) },
{ typeof(TimeSpan).FullName, (MySqlDbType.Time, "time","time NOT NULL", false, false, 0) },{ typeof(TimeSpan?).FullName, (MySqlDbType.Time, "time", "time",false, true, null) },
{ typeof(DateTime).FullName, (MySqlDbType.DateTime, "datetime(3)", "datetime(3) NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, (MySqlDbType.DateTime, "datetime(3)", "datetime(3)", false, true, null) },
{ typeof(byte[]).FullName, (MySqlDbType.VarBinary, "varbinary", "varbinary(255)", false, null, new byte[0]) },
{ typeof(string).FullName, (MySqlDbType.VarChar, "varchar", "varchar(255)", false, null, "") },
{ typeof(Guid).FullName, (MySqlDbType.VarChar, "char", "char(36) NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName, (MySqlDbType.VarChar, "char", "char(36)", false, true, null) },
{ typeof(MygisPoint).FullName, (MySqlDbType.Geometry, "point", "point", false, null, new MygisPoint(0, 0)) },
{ typeof(MygisLineString).FullName, (MySqlDbType.Geometry, "linestring", "linestring", false, null, new MygisLineString(new[]{new MygisCoordinate2D(),new MygisCoordinate2D()})) },
{ typeof(MygisPolygon).FullName, (MySqlDbType.Geometry, "polygon", "polygon", false, null, new MygisPolygon(new[]{new[]{new MygisCoordinate2D(),new MygisCoordinate2D()},new[]{new MygisCoordinate2D(),new MygisCoordinate2D()}})) },
{ typeof(MygisMultiPoint).FullName, (MySqlDbType.Geometry, "multipoint","multipoint", false, null, new MygisMultiPoint(new[]{new MygisCoordinate2D(),new MygisCoordinate2D()})) },
{ typeof(MygisMultiLineString).FullName, (MySqlDbType.Geometry, "multilinestring","multilinestring", false, null, new MygisMultiLineString(new[]{new[]{new MygisCoordinate2D(),new MygisCoordinate2D()},new[]{new MygisCoordinate2D(),new MygisCoordinate2D()}})) },
{ typeof(MygisMultiPolygon).FullName, (MySqlDbType.Geometry, "multipolygon", "multipolygon", false, null, new MygisMultiPolygon(new[]{new MygisPolygon(new[]{new[]{new MygisCoordinate2D(),new MygisCoordinate2D()},new[]{new MygisCoordinate2D(),new MygisCoordinate2D()}}),new MygisPolygon(new[]{new[]{new MygisCoordinate2D(),new MygisCoordinate2D()},new[]{new MygisCoordinate2D(),new MygisCoordinate2D()}})})) },
};
public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) {
if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (int, string, string, bool?, object)?(((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue));
if (type.IsArray) return null;
var enumType = type.IsEnum ? type : null;
if (enumType == null && type.IsNullableType() && type.GenericTypeArguments.Length == 1 && type.GenericTypeArguments.First().IsEnum) enumType = type.GenericTypeArguments.First();
if (enumType != null) {
var names = string.Join(",", Enum.GetNames(enumType).Select(a => _commonUtils.FormatSql("{0}", a)));
var newItem = enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Any() ?
(MySqlDbType.Set, "set", $"set({names}){(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0)) :
(MySqlDbType.Enum, "enum", $"enum({names}){(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0));
if (_dicCsToDb.ContainsKey(type.FullName) == false) {
lock (_dicCsToDbLock) {
if (_dicCsToDb.ContainsKey(type.FullName) == false)
_dicCsToDb.Add(type.FullName, newItem);
}
}
return ((int)newItem.Item1, newItem.Item2, newItem.Item3, newItem.Item5, newItem.Item6);
}
return null;
}
public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity));
public string GetComparisonDDLStatements(params Type[] entityTypes) {
var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5));
var database = conn.Value.Database;
Func<string, string, object> ExecuteScalar = (db, sql) => {
if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db);
try {
using (var cmd = conn.Value.CreateCommand()) {
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
return cmd.ExecuteScalar();
}
} finally {
if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database);
}
};
var sb = new StringBuilder();
try {
foreach (var entityType in entityTypes) {
if (sb.Length > 0) sb.Append("\r\n");
var tb = _commonUtils.GetTableByEntity(entityType);
if (tb == null) throw new Exception($"类型 {entityType.FullName} 不可迁移");
if (tb.Columns.Any() == false) throw new Exception($"类型 {entityType.FullName} 不可迁移可迁移属性0个");
var tbname = tb.DbName.Split(new[] { '.' }, 2);
if (tbname?.Length == 1) tbname = new[] { database, tbname[0] };
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //旧表名
if (tboldname?.Length == 1) tboldname = new[] { database, tboldname[0] };
if (string.Compare(tbname[0], database, true) != 0 && ExecuteScalar(database, _commonUtils.FormatSql(" select 1 from information_schema.schemata where schema_name={0}", tbname[0])) == null) //创建数据库
sb.Append($"CREATE DATABASE IF NOT EXISTS ").Append(_commonUtils.QuoteSqlName(tbname[0])).Append(" default charset utf8 COLLATE utf8_general_ci;\r\n");
var sbalter = new StringBuilder();
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
if (ExecuteScalar(tbname[0], _commonUtils.FormatSql(" SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}", tbname)) == null) { //表不存在
if (tboldname != null) {
if (string.Compare(tboldname[0], tbname[0], true) != 0 && ExecuteScalar(database, _commonUtils.FormatSql(" select 1 from information_schema.schemata where schema_name={0}", tboldname[0])) == null ||
ExecuteScalar(tboldname[0], _commonUtils.FormatSql(" SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}", tboldname)) == null)
//数据库或表不存在
tboldname = null;
}
if (tboldname == null) {
//创建表
sb.Append("CREATE TABLE IF NOT EXISTS ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ( ");
foreach (var tbcol in tb.Columns.Values) {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ");
sb.Append(tbcol.Attribute.DbType);
if (tbcol.Attribute.IsIdentity == true && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT");
sb.Append(",");
}
if (tb.Primarys.Any()) {
sb.Append(" \r\n PRIMARY KEY (");
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
foreach (var uk in tb.Uniques) {
sb.Append(" \r\n UNIQUE KEY ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append("(");
foreach (var tbcol in uk.Value) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
sb.Remove(sb.Length - 1, 1);
sb.Append("\r\n) Engine=InnoDB;\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");
else {
//如果新表,旧表不在一起,创建新表,导入数据,删除旧表
istmpatler = true;
}
} else
tboldname = null; //如果新表已经存在,不走改表名逻辑
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
var sql = _commonUtils.FormatSql(@"
select
a.column_name,
a.column_type,
case when a.is_nullable = 'YES' then 1 else 0 end 'is_nullable',
case when locate('auto_increment', a.extra) > 0 then 1 else 0 end 'is_identity'
from information_schema.columns a
where a.table_schema in ({0}) and a.table_name in ({1})", tboldname ?? tbname);
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => {
var a1 = string.Concat(a[1]);
if (a1 == "datetime") a1 = string.Concat(a1, "(0)");
return new {
column = string.Concat(a[0]),
sqlType = a1,
is_nullable = string.Concat(a[2]) == "1",
is_identity = string.Concat(a[3]) == "1",
is_unsigned = string.Concat(a[1]).EndsWith(" unsigned")
};
}, StringComparer.CurrentCultureIgnoreCase);
if (istmpatler == false) {
var existsPrimary = ExecuteScalar(tbname[0], _commonUtils.FormatSql("select 1 from information_schema.key_column_usage where table_schema={0} and table_name={1} and constraint_name = 'PRIMARY' limit 1", tbname));
foreach (var tbcol in tb.Columns.Values) {
var isIdentityChanged = tbcol.Attribute.IsIdentity == true && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1;
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
if ((tbcol.Attribute.DbType.IndexOf(" unsigned", StringComparison.CurrentCultureIgnoreCase) != -1) != tbstructcol.is_unsigned ||
tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false ||
tbcol.Attribute.IsNullable != tbstructcol.is_nullable ||
tbcol.Attribute.IsIdentity != tbstructcol.is_identity) {
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(tbcol.Attribute.DbType);
if (isIdentityChanged) sbalter.Append(" AUTO_INCREMENT").Append(existsPrimary == null ? "" : ", DROP PRIMARY KEY").Append(", ADD PRIMARY KEY(").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(")");
sbalter.Append(";\r\n");
}
if (tbstructcol.column == tbcol.Attribute.OldName) {
//修改列名
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" CHANGE COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.OldName)).Append(" ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType);
if (isIdentityChanged) sb.Append(" AUTO_INCREMENT").Append(existsPrimary == null ? "" : ", DROP PRIMARY KEY").Append(", ADD PRIMARY KEY(").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(")");
sbalter.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 (isIdentityChanged) sbalter.Append(" AUTO_INCREMENT").Append(existsPrimary == null ? "" : ", DROP PRIMARY KEY").Append(", ADD PRIMARY KEY(").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(")");
sbalter.Append(";\r\n");
}
var dsuksql = _commonUtils.FormatSql(@"
select
a.column_name,
a.constraint_name 'index_id'
from information_schema.key_column_usage a
where a.constraint_schema IN ({0}) and a.table_name IN ({1})", tboldname ?? tbname);
var dsuk = _orm.Ado.ExecuteArray(CommandType.Text, dsuksql).Select(a => new[] { string.Concat(a[0]), string.Concat(a[1]) });
foreach (var uk in tb.Uniques) {
if (uk.Key == "PRIMARY" || string.IsNullOrEmpty(uk.Key) || uk.Value.Any() == false) continue;
var dsukfind1 = dsuk.Where(a => string.Compare(a[1], uk.Key, true) == 0).ToArray();
if (dsukfind1.Any() == false || dsukfind1.Length != uk.Value.Count || dsukfind1.Where(a => uk.Value.Where(b => string.Compare(b.Attribute.Name, a[0], true) == 0).Any()).Count() != uk.Value.Count) {
if (dsukfind1.Any()) sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" DROP INDEX ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(";\r\n");
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(" UNIQUE(");
foreach (var tbcol in uk.Value) sbalter.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sbalter.Remove(sbalter.Length - 2, 2).Append(");\r\n");
}
}
}
if (istmpatler == false) {
sb.Append(sbalter);
continue;
}
//创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名
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.Columns.Values) {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ");
sb.Append(tbcol.Attribute.DbType);
if (tbcol.Attribute.IsIdentity == true && tbcol.Attribute.DbType.IndexOf("AUTO_INCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" AUTO_INCREMENT");
sb.Append(",");
}
if (tb.Primarys.Any()) {
sb.Append(" \r\n PRIMARY KEY (");
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
foreach (var uk in tb.Uniques) {
sb.Append(" \r\n UNIQUE KEY ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append("(");
foreach (var tbcol in uk.Value) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
sb.Remove(sb.Length - 1, 1);
sb.Append("\r\n) Engine=InnoDB;\r\n");
sb.Append("INSERT INTO ").Append(tmptablename).Append(" (");
foreach (var tbcol in tb.Columns.Values)
sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append(")\r\nSELECT ");
foreach (var tbcol in tb.Columns.Values) {
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)) {
insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column);
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},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue)})";
} else if (tbcol.Attribute.IsNullable == false)
insertvalue = _commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue);
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("ALTER TABLE ").Append(tmptablename).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(";\r\n");
}
return sb.Length == 0 ? null : sb.ToString();
} finally {
try {
conn.Value.ChangeDatabase(database);
_orm.Ado.MasterPool.Return(conn);
} catch {
_orm.Ado.MasterPool.Return(conn, true);
}
}
}
static object syncStructureLock = new object();
ConcurrentDictionary<string, bool> dicSyced = new ConcurrentDictionary<string, bool>();
public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity));
public bool SyncStructure(params Type[] entityTypes) {
if (entityTypes == null) return true;
var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray();
if (syncTypes.Any() == false) return true;
var before = new Aop.SyncStructureBeforeEventArgs(entityTypes);
_orm.Aop.SyncStructureBefore?.Invoke(this, before);
Exception exception = null;
string ddl = null;
try {
lock (syncStructureLock) {
ddl = this.GetComparisonDDLStatements(syncTypes);
if (string.IsNullOrEmpty(ddl)) {
foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true);
return true;
}
var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl);
foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true);
return affrows > 0;
}
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception);
_orm.Aop.SyncStructureAfter?.Invoke(this, after);
}
}
public ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) => _commonUtils.ConfigEntity(entity);
public ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) => _commonUtils.ConfigEntity(type, entity);
public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type);
public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type);
}
}

View File

@ -1,383 +0,0 @@
using FreeSql.DatabaseModel;
using FreeSql.Internal;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text.RegularExpressions;
namespace FreeSql.MySql {
class MySqlDbFirst : IDbFirst {
IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
public MySqlDbFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) {
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
}
public int GetDbType(DbColumnInfo column) => (int)GetMySqlDbType(column);
MySqlDbType GetMySqlDbType(DbColumnInfo column) {
var is_unsigned = column.DbTypeTextFull.ToLower().EndsWith(" unsigned");
switch (column.DbTypeText.ToLower()) {
case "bit": return MySqlDbType.Bit;
case "tinyint": return is_unsigned ? MySqlDbType.UByte : MySqlDbType.Byte;
case "smallint": return is_unsigned ? MySqlDbType.UInt16 : MySqlDbType.Int16;
case "mediumint": return is_unsigned ? MySqlDbType.UInt24 : MySqlDbType.Int24;
case "int": return is_unsigned ? MySqlDbType.UInt32 : MySqlDbType.Int32;
case "bigint": return is_unsigned ? MySqlDbType.UInt64 : MySqlDbType.Int64;
case "real":
case "double": return MySqlDbType.Double;
case "float": return MySqlDbType.Float;
case "numeric":
case "decimal": return MySqlDbType.Decimal;
case "year": return MySqlDbType.Year;
case "time": return MySqlDbType.Time;
case "date": return MySqlDbType.Date;
case "timestamp": return MySqlDbType.Timestamp;
case "datetime": return MySqlDbType.DateTime;
case "tinyblob": return MySqlDbType.TinyBlob;
case "blob": return MySqlDbType.Blob;
case "mediumblob": return MySqlDbType.MediumBlob;
case "longblob": return MySqlDbType.LongBlob;
case "binary": return MySqlDbType.Binary;
case "varbinary": return MySqlDbType.VarBinary;
case "tinytext": return MySqlDbType.TinyText;
case "text": return MySqlDbType.Text;
case "mediumtext": return MySqlDbType.MediumText;
case "longtext": return MySqlDbType.LongText;
case "char": return column.MaxLength == 36 ? MySqlDbType.Guid : MySqlDbType.String;
case "varchar": return MySqlDbType.VarChar;
case "set": return MySqlDbType.Set;
case "enum": return MySqlDbType.Enum;
case "point": return MySqlDbType.Geometry;
case "linestring": return MySqlDbType.Geometry;
case "polygon": return MySqlDbType.Geometry;
case "geometry": return MySqlDbType.Geometry;
case "multipoint": return MySqlDbType.Geometry;
case "multilinestring": return MySqlDbType.Geometry;
case "multipolygon": return MySqlDbType.Geometry;
case "geometrycollection": return MySqlDbType.Geometry;
default: return MySqlDbType.String;
}
}
static readonly Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)> _dicDbToCs = new Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)>() {
{ (int)MySqlDbType.Bit, ("(bool?)", "{0} == \"1\"", "{0} == true ? \"1\" : \"0\"", "bool?", typeof(bool), typeof(bool?), "{0}.Value", "GetBoolean") },
{ (int)MySqlDbType.Byte, ("(sbyte?)", "sbyte.Parse({0})", "{0}.ToString()", "sbyte?", typeof(sbyte), typeof(sbyte?), "{0}.Value", "GetByte") },
{ (int)MySqlDbType.Int16, ("(short?)", "short.Parse({0})", "{0}.ToString()", "short?", typeof(short), typeof(short?), "{0}.Value", "GetInt16") },
{ (int)MySqlDbType.Int24, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
{ (int)MySqlDbType.Int32, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
{ (int)MySqlDbType.Int64, ("(long?)", "long.Parse({0})", "{0}.ToString()", "long?", typeof(long), typeof(long?), "{0}.Value", "GetInt64") },
{ (int)MySqlDbType.UByte, ("(byte?)", "byte.Parse({0})", "{0}.ToString()", "byte?", typeof(byte), typeof(byte?), "{0}.Value", "GetByte") },
{ (int)MySqlDbType.UInt16, ("(ushort?)", "ushort.Parse({0})", "{0}.ToString()", "ushort?", typeof(ushort), typeof(ushort?), "{0}.Value", "GetInt16") },
{ (int)MySqlDbType.UInt24, ("(uint?)", "uint.Parse({0})", "{0}.ToString()", "uint?", typeof(uint), typeof(uint?), "{0}.Value", "GetInt32") },
{ (int)MySqlDbType.UInt32, ("(uint?)", "uint.Parse({0})", "{0}.ToString()", "uint?", typeof(uint), typeof(uint?), "{0}.Value", "GetInt32") },
{ (int)MySqlDbType.UInt64, ("(ulong?)", "ulong.Parse({0})", "{0}.ToString()", "ulong?", typeof(ulong), typeof(ulong?), "{0}.Value", "GetInt64") },
{ (int)MySqlDbType.Double, ("(double?)", "double.Parse({0})", "{0}.ToString()", "double?", typeof(double), typeof(double?), "{0}.Value", "GetDouble") },
{ (int)MySqlDbType.Float, ("(float?)", "float.Parse({0})", "{0}.ToString()", "float?", typeof(float), typeof(float?), "{0}.Value", "GetFloat") },
{ (int)MySqlDbType.Decimal, ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") },
{ (int)MySqlDbType.Year, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
{ (int)MySqlDbType.Time, ("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") },
{ (int)MySqlDbType.Date, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
{ (int)MySqlDbType.Timestamp, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
{ (int)MySqlDbType.DateTime, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
{ (int)MySqlDbType.TinyBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
{ (int)MySqlDbType.Blob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
{ (int)MySqlDbType.MediumBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
{ (int)MySqlDbType.LongBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
{ (int)MySqlDbType.Binary, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
{ (int)MySqlDbType.VarBinary, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
{ (int)MySqlDbType.TinyText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)MySqlDbType.Text, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)MySqlDbType.MediumText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)MySqlDbType.LongText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)MySqlDbType.Guid, ("(Guid?)", "Guid.Parse({0})", "{0}.ToString()", "Guid?", typeof(Guid), typeof(Guid?), "{0}", "GetString") },
{ (int)MySqlDbType.String, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)MySqlDbType.VarString, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)MySqlDbType.VarChar, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)MySqlDbType.Set, ("(long?)", "long.Parse({0})", "{0}.ToInt64().ToString()", "Set", typeof(Enum), typeof(Enum), "{0}", "GetInt64") },
{ (int)MySqlDbType.Enum, ("(long?)", "long.Parse({0})", "{0}.ToInt64().ToString()", "Enum", typeof(Enum), typeof(Enum), "{0}", "GetInt64") },
{ (int)MySqlDbType.Geometry, ("(MygisGeometry)", "MygisGeometry.Parse({0}.Replace(StringifySplit, \"|\"))", "{0}.AsText().Replace(\"|\", StringifySplit)", "MygisGeometry", typeof(MygisGeometry), typeof(MygisGeometry), "{0}", "GetString") },
};
public string GetCsConvert(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? (column.IsNullable ? trydc.csConvert : trydc.csConvert.Replace("?", "")) : null;
public string GetCsParse(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csParse : null;
public string GetCsStringify(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csStringify : null;
public string GetCsType(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? (column.IsNullable ? trydc.csType : trydc.csType.Replace("?", "")) : null;
public Type GetCsTypeInfo(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csTypeInfo : null;
public string GetCsTypeValue(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csTypeValue : null;
public string GetDataReaderMethod(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.dataReaderMethod : null;
public List<string> GetDatabases() {
var sql = @" select schema_name from information_schema.schemata where schema_name not in ('information_schema', 'mysql', 'performance_schema')";
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList();
}
public List<DbTableInfo> GetTablesByDatabase(params string[] database2) {
var loc1 = new List<DbTableInfo>();
var loc2 = new Dictionary<string, DbTableInfo>();
var loc3 = new Dictionary<string, Dictionary<string, DbColumnInfo>>();
var database = database2?.ToArray();
if (database == null || database.Any() == false) {
using (var conn = _orm.Ado.MasterPool.Get()) {
if (string.IsNullOrEmpty(conn.Value.Database)) return loc1;
database = new[] { conn.Value.Database };
}
}
var databaseIn = string.Join(",", database.Select(a => _commonUtils.FormatSql("{0}", a)));
var sql = string.Format(@"
select
concat(a.table_schema, '.', a.table_name) 'id',
a.table_schema 'schema',
a.table_name 'table',
a.table_comment,
a.table_type 'type'
from information_schema.tables a
where a.table_schema in ({0})", databaseIn);
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var loc6 = new List<string>();
var loc66 = new List<string>();
foreach (var row in ds) {
var table_id = string.Concat(row[0]);
var schema = string.Concat(row[1]);
var table = string.Concat(row[2]);
var comment = string.Concat(row[3]);
var type = string.Concat(row[4]) == "VIEW" ? DbTableType.VIEW : DbTableType.TABLE;
if (database.Length == 1) {
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
schema = "";
}
loc2.Add(table_id, new DbTableInfo { Id = table_id, Schema = schema, Name = table, Comment = comment, Type = type });
loc3.Add(table_id, new Dictionary<string, DbColumnInfo>());
switch (type) {
case DbTableType.TABLE:
case DbTableType.VIEW:
loc6.Add(table.Replace("'", "''"));
break;
case DbTableType.StoreProcedure:
loc66.Add(table.Replace("'", "''"));
break;
}
}
if (loc6.Count == 0) return loc1;
var loc8 = "'" + string.Join("','", loc6.ToArray()) + "'";
var loc88 = "'" + string.Join("','", loc66.ToArray()) + "'";
sql = string.Format(@"
select
concat(a.table_schema, '.', a.table_name),
a.column_name,
a.data_type,
ifnull(a.character_maximum_length, 0) 'len',
a.column_type,
case when a.is_nullable = 'YES' then 1 else 0 end 'is_nullable',
case when locate('auto_increment', a.extra) > 0 then 1 else 0 end 'is_identity',
a.column_comment 'comment'
from information_schema.columns a
where a.table_schema in ({1}) and a.table_name in ({0})
", loc8, databaseIn);
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
foreach (var row in ds) {
string table_id = string.Concat(row[0]);
string column = string.Concat(row[1]);
string type = string.Concat(row[2]);
//long max_length = long.Parse(string.Concat(row[3]));
string sqlType = string.Concat(row[4]);
var m_len = Regex.Match(sqlType, @"\w+\((\d+)");
int max_length = m_len.Success ? int.Parse(m_len.Groups[1].Value) : -1;
bool is_nullable = string.Concat(row[5]) == "1";
bool is_identity = string.Concat(row[6]) == "1";
string comment = string.Concat(row[7]);
if (max_length == 0) max_length = -1;
if (database.Length == 1) {
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
}
loc3[table_id].Add(column, new DbColumnInfo {
Name = column,
MaxLength = max_length,
IsIdentity = is_identity,
IsNullable = is_nullable,
IsPrimary = false,
DbTypeText = type,
DbTypeTextFull = sqlType,
Table = loc2[table_id],
Coment = comment
});
loc3[table_id][column].DbType = this.GetDbType(loc3[table_id][column]);
loc3[table_id][column].CsType = this.GetCsTypeInfo(loc3[table_id][column]);
}
sql = string.Format(@"
select
concat(a.constraint_schema, '.', a.table_name) 'table_id',
a.column_name,
a.constraint_name 'index_id',
1 'IsUnique',
case when a.constraint_name = 'PRIMARY' then 1 else 0 end 'IsPrimaryKey',
0 'IsClustered',
0 'IsDesc'
from information_schema.key_column_usage a
where a.constraint_schema in ({1}) and a.table_name in ({0}) and isnull(position_in_unique_constraint)
", loc8, databaseIn);
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var indexColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
var uniqueColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
foreach (var row in ds) {
string table_id = string.Concat(row[0]);
string column = string.Concat(row[1]);
string index_id = string.Concat(row[2]);
bool is_unique = string.Concat(row[3]) == "1";
bool is_primary_key = string.Concat(row[4]) == "1";
bool is_clustered = string.Concat(row[5]) == "1";
int is_desc = int.Parse(string.Concat(row[6]));
if (database.Length == 1) {
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
}
if (loc3.ContainsKey(table_id) == false || loc3[table_id].ContainsKey(column) == false) continue;
var loc9 = loc3[table_id][column];
if (loc9.IsPrimary == false && is_primary_key) loc9.IsPrimary = is_primary_key;
Dictionary<string, List<DbColumnInfo>> loc10 = null;
List<DbColumnInfo> loc11 = null;
if (!indexColumns.TryGetValue(table_id, out loc10))
indexColumns.Add(table_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
if (!loc10.TryGetValue(index_id, out loc11))
loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
loc11.Add(loc9);
if (is_unique && !is_primary_key) {
if (!uniqueColumns.TryGetValue(table_id, out loc10))
uniqueColumns.Add(table_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
if (!loc10.TryGetValue(index_id, out loc11))
loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
loc11.Add(loc9);
}
}
foreach (string table_id in indexColumns.Keys) {
foreach (var column in indexColumns[table_id])
loc2[table_id].IndexesDict.Add(column.Key, column.Value);
}
foreach (string table_id in uniqueColumns.Keys) {
foreach (var column in uniqueColumns[table_id]) {
column.Value.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
loc2[table_id].UniquesDict.Add(column.Key, column.Value);
}
}
sql = string.Format(@"
select
concat(a.constraint_schema, '.', a.table_name) 'table_id',
a.column_name,
a.constraint_name 'FKId',
concat(a.referenced_table_schema, '.', a.referenced_table_name) 'ref_table_id',
1 'IsForeignKey',
a.referenced_column_name 'ref_column'
from information_schema.key_column_usage a
where a.constraint_schema in ({1}) and a.table_name in ({0}) and not isnull(position_in_unique_constraint)
", loc8, databaseIn);
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var fkColumns = new Dictionary<string, Dictionary<string, DbForeignInfo>>();
foreach (var row in ds) {
string table_id = string.Concat(row[0]);
string column = string.Concat(row[1]);
string fk_id = string.Concat(row[2]);
string ref_table_id = string.Concat(row[3]);
bool is_foreign_key = string.Concat(row[4]) == "1";
string referenced_column = string.Concat(row[5]);
if (database.Length == 1) {
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
ref_table_id = ref_table_id.Substring(ref_table_id.IndexOf('.') + 1);
}
if (loc3.ContainsKey(table_id) == false || loc3[table_id].ContainsKey(column) == false) continue;
var loc9 = loc3[table_id][column];
if (loc2.ContainsKey(ref_table_id) == false) continue;
var loc10 = loc2[ref_table_id];
var loc11 = loc3[ref_table_id][referenced_column];
Dictionary<string, DbForeignInfo> loc12 = null;
DbForeignInfo loc13 = null;
if (!fkColumns.TryGetValue(table_id, out loc12))
fkColumns.Add(table_id, loc12 = new Dictionary<string, DbForeignInfo>());
if (!loc12.TryGetValue(fk_id, out loc13))
loc12.Add(fk_id, loc13 = new DbForeignInfo { Table = loc2[table_id], ReferencedTable = loc10 });
loc13.Columns.Add(loc9);
loc13.ReferencedColumns.Add(loc11);
}
foreach (var table_id in fkColumns.Keys)
foreach (var fk in fkColumns[table_id])
loc2[table_id].ForeignsDict.Add(fk.Key, fk.Value);
foreach (var table_id in loc3.Keys) {
foreach (var loc5 in loc3[table_id].Values) {
loc2[table_id].Columns.Add(loc5);
if (loc5.IsIdentity) loc2[table_id].Identitys.Add(loc5);
if (loc5.IsPrimary) loc2[table_id].Primarys.Add(loc5);
}
}
foreach (var loc4 in loc2.Values) {
if (loc4.Primarys.Count == 0 && loc4.UniquesDict.Count > 0) {
foreach (var loc5 in loc4.UniquesDict.First().Value) {
loc5.IsPrimary = true;
loc4.Primarys.Add(loc5);
}
}
loc4.Primarys.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
loc4.Columns.Sort((c1, c2) => {
int compare = c2.IsPrimary.CompareTo(c1.IsPrimary);
if (compare == 0) {
bool b1 = loc4.ForeignsDict.Values.Where(fk => fk.Columns.Where(c3 => c3.Name == c1.Name).Any()).Any();
bool b2 = loc4.ForeignsDict.Values.Where(fk => fk.Columns.Where(c3 => c3.Name == c2.Name).Any()).Any();
compare = b2.CompareTo(b1);
}
if (compare == 0) compare = c1.Name.CompareTo(c2.Name);
return compare;
});
loc1.Add(loc4);
}
loc1.Sort((t1, t2) => {
var ret = t1.Schema.CompareTo(t2.Schema);
if (ret == 0) ret = t1.Name.CompareTo(t2.Name);
return ret;
});
loc2.Clear();
loc3.Clear();
return loc1;
}
public List<DbEnumInfo> GetEnumsByDatabase(params string[] database) {
return new List<DbEnumInfo>();
}
}
}

View File

@ -1,398 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace FreeSql.MySql {
class MySqlExpression : CommonExpression {
public MySqlExpression(CommonUtils common) : base(common) { }
internal override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
switch (exp.NodeType) {
case ExpressionType.Convert:
var operandExp = (exp as UnaryExpression)?.Operand;
var gentype = exp.Type.NullableTypeOrThis();
if (gentype != operandExp.Type.NullableTypeOrThis()) {
switch (gentype.ToString()) {
case "System.Boolean": return $"({getExp(operandExp)} not in ('0','false'))";
case "System.Byte": return $"cast({getExp(operandExp)} as unsigned)";
case "System.Char": return $"substr(cast({getExp(operandExp)} as char), 1, 1)";
case "System.DateTime": return $"cast({getExp(operandExp)} as datetime)";
case "System.Decimal": return $"cast({getExp(operandExp)} as decimal(36,18))";
case "System.Double": return $"cast({getExp(operandExp)} as decimal(32,16))";
case "System.Int16":
case "System.Int32":
case "System.Int64":
case "System.SByte": return $"cast({getExp(operandExp)} as signed)";
case "System.Single": return $"cast({getExp(operandExp)} as decimal(14,7))";
case "System.String": return $"cast({getExp(operandExp)} as char)";
case "System.UInt16":
case "System.UInt32":
case "System.UInt64": return $"cast({getExp(operandExp)} as unsigned)";
case "System.Guid": return $"substr(cast({getExp(operandExp)} as char), 1, 36)";
}
}
break;
case ExpressionType.Call:
var callExp = exp as MethodCallExpression;
switch (callExp.Method.Name) {
case "Parse":
case "TryParse":
switch (callExp.Method.DeclaringType.NullableTypeOrThis().ToString()) {
case "System.Boolean": return $"({getExp(callExp.Arguments[0])} not in ('0','false'))";
case "System.Byte": return $"cast({getExp(callExp.Arguments[0])} as unsigned)";
case "System.Char": return $"substr(cast({getExp(callExp.Arguments[0])} as char), 1, 1)";
case "System.DateTime": return $"cast({getExp(callExp.Arguments[0])} as datetime)";
case "System.Decimal": return $"cast({getExp(callExp.Arguments[0])} as decimal(36,18))";
case "System.Double": return $"cast({getExp(callExp.Arguments[0])} as decimal(32,16))";
case "System.Int16":
case "System.Int32":
case "System.Int64":
case "System.SByte": return $"cast({getExp(callExp.Arguments[0])} as signed)";
case "System.Single": return $"cast({getExp(callExp.Arguments[0])} as decimal(14,7))";
case "System.UInt16":
case "System.UInt32":
case "System.UInt64": return $"cast({getExp(callExp.Arguments[0])} as unsigned)";
case "System.Guid": return $"substr(cast({getExp(callExp.Arguments[0])} as char), 1, 36)";
}
break;
case "NewGuid":
break;
case "Next":
if (callExp.Object?.Type == typeof(Random)) return "cast(rand()*1000000000 as signed)";
break;
case "NextDouble":
if (callExp.Object?.Type == typeof(Random)) return "rand()";
break;
case "Random":
if (callExp.Method.DeclaringType.IsNumberType()) return "rand()";
break;
case "ToString":
if (callExp.Object != null) return $"cast({getExp(callExp.Object)} as char)";
break;
}
var objExp = callExp.Object;
var objType = objExp?.Type;
if (objType?.FullName == "System.Byte[]") return null;
var argIndex = 0;
if (objType == null && callExp.Method.DeclaringType == typeof(Enumerable)) {
objExp = callExp.Arguments.FirstOrDefault();
objType = objExp?.Type;
argIndex++;
}
if (objType == null) objType = callExp.Method.DeclaringType;
if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) {
var left = objExp == null ? null : getExp(objExp);
switch (callExp.Method.Name) {
case "Contains":
//判断 in
return $"({getExp(callExp.Arguments[argIndex])}) in {left}";
}
}
break;
case ExpressionType.NewArrayInit:
var arrExp = exp as NewArrayExpression;
var arrSb = new StringBuilder();
arrSb.Append("(");
for (var a = 0; a < arrExp.Expressions.Count; a++) {
if (a > 0) arrSb.Append(",");
arrSb.Append(getExp(arrExp.Expressions[a]));
}
if (arrSb.Length == 1) arrSb.Append("NULL");
return arrSb.Append(")").ToString();
case ExpressionType.ListInit:
var listExp = exp as ListInitExpression;
var listSb = new StringBuilder();
listSb.Append("(");
for (var a = 0; a < listExp.Initializers.Count; a++) {
if (listExp.Initializers[a].Arguments.Any() == false) continue;
if (a > 0) listSb.Append(",");
listSb.Append(getExp(listExp.Initializers[a].Arguments.FirstOrDefault()));
}
if (listSb.Length == 1) listSb.Append("NULL");
return listSb.Append(")").ToString();
case ExpressionType.New:
var newExp = exp as NewExpression;
if (typeof(IList).IsAssignableFrom(newExp.Type)) {
if (newExp.Arguments.Count == 0) return "(NULL)";
if (typeof(IEnumerable).IsAssignableFrom(newExp.Arguments[0].Type) == false) return "(NULL)";
return getExp(newExp.Arguments[0]);
}
return null;
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Empty": return "''";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Length": return $"char_length({left})";
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Now": return "now()";
case "UtcNow": return "utc_timestamp()";
case "Today": return "curdate()";
case "MinValue": return "cast('0001/1/1 0:00:00' as datetime)";
case "MaxValue": return "cast('9999/12/31 23:59:59' as datetime)";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Date": return $"cast(date_format({left},'%Y-%m-%d') as datetime)";
case "TimeOfDay": return $"timestampdiff(microsecond, date_format({left},'%Y-%m-%d'), {left})";
case "DayOfWeek": return $"(dayofweek({left})-1)";
case "Day": return $"dayofmonth({left})";
case "DayOfYear": return $"dayofyear({left})";
case "Month": return $"month({left})";
case "Year": return $"year({left})";
case "Hour": return $"hour({left})";
case "Minute": return $"minute({left})";
case "Second": return $"second({left})";
case "Millisecond": return $"floor(microsecond({left})/1000)";
case "Ticks": return $"(timestampdiff(microsecond, '0001-1-1', {left})*10)";
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Zero": return "0";
case "MinValue": return "-922337203685477580"; //微秒 Ticks / 10
case "MaxValue": return "922337203685477580";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Days": return $"(({left}) div {(long)1000000 * 60 * 60 * 24})";
case "Hours": return $"(({left}) div {(long)1000000 * 60 * 60} mod 24)";
case "Milliseconds": return $"(({left}) div 1000 mod 1000)";
case "Minutes": return $"(({left}) div {(long)1000000 * 60} mod 60)";
case "Seconds": return $"(({left}) div 1000000 mod 60)";
case "Ticks": return $"(({left}) * 10)";
case "TotalDays": return $"(({left}) / {(long)1000000 * 60 * 60 * 24})";
case "TotalHours": return $"(({left}) / {(long)1000000 * 60 * 60})";
case "TotalMilliseconds": return $"(({left}) / 1000)";
case "TotalMinutes": return $"(({left}) / {(long)1000000 * 60})";
case "TotalSeconds": return $"(({left}) / 1000000)";
}
return null;
}
internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "IsNullOrEmpty":
var arg1 = getExp(exp.Arguments[0]);
return $"({arg1} is null or {arg1} = '')";
case "Concat":
return _common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), null);
}
} else {
var left = getExp(exp.Object);
switch (exp.Method.Name) {
case "StartsWith":
case "EndsWith":
case "Contains":
var args0Value = getExp(exp.Arguments[0]);
if (args0Value == "NULL") return $"({left}) IS NULL";
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"concat({args0Value}, '%')")}";
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"concat('%', {args0Value})")}";
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
return $"({left}) LIKE concat('%', {args0Value}, '%')";
case "ToLower": return $"lower({left})";
case "ToUpper": return $"upper({left})";
case "Substring":
var substrArgs1 = getExp(exp.Arguments[0]);
if (long.TryParse(substrArgs1, out var testtrylng1)) substrArgs1 = (testtrylng1 + 1).ToString();
else substrArgs1 += "+1";
if (exp.Arguments.Count == 1) return $"substr({left}, {substrArgs1})";
return $"substr({left}, {substrArgs1}, {getExp(exp.Arguments[1])})";
case "IndexOf":
var indexOfFindStr = getExp(exp.Arguments[0]);
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") {
var locateArgs1 = getExp(exp.Arguments[1]);
if (long.TryParse(locateArgs1, out var testtrylng2)) locateArgs1 = (testtrylng2 + 1).ToString();
else locateArgs1 += "+1";
return $"(locate({left}, {indexOfFindStr}, {locateArgs1})-1)";
}
return $"(locate({left}, {indexOfFindStr})-1)";
case "PadLeft":
if (exp.Arguments.Count == 1) return $"lpad({left}, {getExp(exp.Arguments[0])})";
return $"lpad({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "PadRight":
if (exp.Arguments.Count == 1) return $"rpad({left}, {getExp(exp.Arguments[0])})";
return $"rpad({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "Trim":
case "TrimStart":
case "TrimEnd":
if (exp.Arguments.Count == 0) {
if (exp.Method.Name == "Trim") return $"trim({left})";
if (exp.Method.Name == "TrimStart") return $"ltrim({left})";
if (exp.Method.Name == "TrimEnd") return $"rtrim({left})";
}
foreach (var argsTrim02 in exp.Arguments) {
var argsTrim01s = new[] { argsTrim02 };
if (argsTrim02.NodeType == ExpressionType.NewArrayInit) {
var arritem = argsTrim02 as NewArrayExpression;
argsTrim01s = arritem.Expressions.ToArray();
}
foreach (var argsTrim01 in argsTrim01s) {
if (exp.Method.Name == "Trim") left = $"trim({getExp(argsTrim01)} from {left})";
if (exp.Method.Name == "TrimStart") left = $"trim(leading {getExp(argsTrim01)} from {left})";
if (exp.Method.Name == "TrimEnd") left = $"trim(trailing {getExp(argsTrim01)} from {left})";
}
}
return left;
case "Replace": return $"replace({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "CompareTo": return $"strcmp({left}, {getExp(exp.Arguments[0])})";
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
}
}
throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
switch (exp.Method.Name) {
case "Abs": return $"abs({getExp(exp.Arguments[0])})";
case "Sign": return $"sign({getExp(exp.Arguments[0])})";
case "Floor": return $"floor({getExp(exp.Arguments[0])})";
case "Ceiling": return $"ceiling({getExp(exp.Arguments[0])})";
case "Round":
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"round({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
return $"round({getExp(exp.Arguments[0])})";
case "Exp": return $"exp({getExp(exp.Arguments[0])})";
case "Log": return $"log({getExp(exp.Arguments[0])})";
case "Log10": return $"log10({getExp(exp.Arguments[0])})";
case "Pow": return $"pow({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "Sqrt": return $"sqrt({getExp(exp.Arguments[0])})";
case "Cos": return $"cos({getExp(exp.Arguments[0])})";
case "Sin": return $"sin({getExp(exp.Arguments[0])})";
case "Tan": return $"tan({getExp(exp.Arguments[0])})";
case "Acos": return $"acos({getExp(exp.Arguments[0])})";
case "Asin": return $"asin({getExp(exp.Arguments[0])})";
case "Atan": return $"atan({getExp(exp.Arguments[0])})";
case "Atan2": return $"atan2({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "Truncate": return $"truncate({getExp(exp.Arguments[0])}, 0)";
}
throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "Compare": return $"({getExp(exp.Arguments[0])} - ({getExp(exp.Arguments[1])}))";
case "DaysInMonth": return $"dayofmonth(last_day(concat({getExp(exp.Arguments[0])}, '-', {getExp(exp.Arguments[1])}, '-01')))";
case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})";
case "IsLeapYear":
var isLeapYearArgs1 = getExp(exp.Arguments[0]);
return $"(({isLeapYearArgs1})%4=0 AND ({isLeapYearArgs1})%100<>0 OR ({isLeapYearArgs1})%400=0)";
case "Parse": return $"cast({getExp(exp.Arguments[0])} as datetime)";
case "ParseExact":
case "TryParse":
case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as datetime)";
}
} else {
var left = getExp(exp.Object);
var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]);
switch (exp.Method.Name) {
case "Add": return $"date_add({left}, interval ({args1}) microsecond)";
case "AddDays": return $"date_add({left}, interval ({args1}) day)";
case "AddHours": return $"date_add({left}, interval ({args1}) hour)";
case "AddMilliseconds": return $"date_add({left}, interval ({args1})*1000 microsecond)";
case "AddMinutes": return $"date_add({left}, interval ({args1}) minute)";
case "AddMonths": return $"date_add({left}, interval ({args1}) month)";
case "AddSeconds": return $"date_add({left}, interval ({args1}) second)";
case "AddTicks": return $"date_add({left}, interval ({args1})/10 microsecond)";
case "AddYears": return $"date_add({left}, interval ({args1}) year)";
case "Subtract":
switch((exp.Arguments[0].Type.IsNullableType() ? exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault() : exp.Arguments[0].Type).FullName) {
case "System.DateTime": return $"timestampdiff(microsecond, {args1}, {left})";
case "System.TimeSpan": return $"date_sub({left}, interval ({args1}) microsecond)";
}
break;
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
case "CompareTo": return $"timestampdiff(microsecond,{args1},{left})";
case "ToString": return $"date_format({left}, '%Y-%m-%d %H:%i:%s.%f')";
}
}
throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "Compare": return $"({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])}))";
case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})";
case "FromDays": return $"(({getExp(exp.Arguments[0])})*{(long)1000000 * 60 * 60 * 24})";
case "FromHours": return $"(({getExp(exp.Arguments[0])})*{(long)1000000 * 60 * 60})";
case "FromMilliseconds": return $"(({getExp(exp.Arguments[0])})*1000)";
case "FromMinutes": return $"(({getExp(exp.Arguments[0])})*{(long)1000000 * 60})";
case "FromSeconds": return $"(({getExp(exp.Arguments[0])})*1000000)";
case "FromTicks": return $"(({getExp(exp.Arguments[0])})/10)";
case "Parse": return $"cast({getExp(exp.Arguments[0])} as signed)";
case "ParseExact":
case "TryParse":
case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as signed)";
}
} else {
var left = getExp(exp.Object);
var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]);
switch (exp.Method.Name) {
case "Add": return $"({left}+{args1})";
case "Subtract": return $"({left}-({args1}))";
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
case "CompareTo": return $"({left}-({getExp(exp.Arguments[0])}))";
case "ToString": return $"cast({left} as char)";
}
}
throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))";
case "ToByte": return $"cast({getExp(exp.Arguments[0])} as unsigned)";
case "ToChar": return $"substr(cast({getExp(exp.Arguments[0])} as char), 1, 1)";
case "ToDateTime": return $"cast({getExp(exp.Arguments[0])} as datetime)";
case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as decimal(36,18))";
case "ToDouble": return $"cast({getExp(exp.Arguments[0])} as decimal(32,16))";
case "ToInt16":
case "ToInt32":
case "ToInt64":
case "ToSByte": return $"cast({getExp(exp.Arguments[0])} as signed)";
case "ToSingle": return $"cast({getExp(exp.Arguments[0])} as decimal(14,7))";
case "ToString": return $"cast({getExp(exp.Arguments[0])} as char)";
case "ToUInt16":
case "ToUInt32":
case "ToUInt64": return $"cast({getExp(exp.Arguments[0])} as unsigned)";
}
}
throw new Exception($"MySqlExpression 未实现函数表达式 {exp} 解析");
}
}
}

View File

@ -1,11 +0,0 @@
public static partial class FreeSqlGlobalExtensions {
/// <summary>
/// 特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换
/// </summary>
/// <param name="that"></param>
/// <param name="args"></param>
/// <returns></returns>
public static string FormatMySql(this string that, params object[] args) => _mysqlAdo.Addslashes(that, args);
static FreeSql.MySql.MySqlAdo _mysqlAdo = new FreeSql.MySql.MySqlAdo();
}

View File

@ -1,71 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.CommonProvider;
using FreeSql.MySql.Curd;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Data.Common;
namespace FreeSql.MySql {
class MySqlProvider<TMark> : IFreeSql<TMark> {
static MySqlProvider() {
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(MygisPoint)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(MygisLineString)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(MygisPolygon)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(MygisMultiPoint)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(MygisMultiLineString)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(MygisMultiPolygon)] = true;
}
public ISelect<T1> Select<T1>() where T1 : class => new MySqlSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public ISelect<T1> Select<T1>(object dywhere) where T1 : class => new MySqlSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsert<T1> Insert<T1>() where T1 : class => new MySqlInsert<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IInsert<T1> Insert<T1>(T1 source) where T1 : class => this.Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(T1[] source) where T1 : class => this.Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(IEnumerable<T1> source) where T1 : class => this.Insert<T1>().AppendData(source);
public IUpdate<T1> Update<T1>() where T1 : class => new MySqlUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new MySqlUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new MySqlDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new MySqlDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IAdo Ado { get; }
public IAop Aop { get; }
public ICache Cache { get; }
public ICodeFirst CodeFirst { get; }
public IDbFirst DbFirst { get; }
public MySqlProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) {
if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.MySql");
this.InternalCommonUtils = new MySqlUtils(this);
this.InternalCommonExpression = new MySqlExpression(this.InternalCommonUtils);
this.Cache = new CacheProvider(cache, log);
this.Ado = new MySqlAdo(this.InternalCommonUtils, this.Cache, log, masterConnectionString, slaveConnectionString);
this.Aop = new AopProvider();
this.DbFirst = new MySqlDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
this.CodeFirst = new MySqlCodeFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
}
internal CommonUtils InternalCommonUtils { get; }
internal CommonExpression InternalCommonExpression { get; }
public void Transaction(Action handler) => Ado.Transaction(handler);
public void Transaction(Action handler, TimeSpan timeout) => Ado.Transaction(handler, timeout);
~MySqlProvider() {
this.Dispose();
}
bool _isdisposed = false;
public void Dispose() {
if (_isdisposed) return;
(this.Ado as AdoProvider).Dispose();
(this.Cache as CacheProvider)?.Dispose();
}
}
}

View File

@ -1,103 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
namespace FreeSql.MySql {
class MySqlUtils : CommonUtils {
public MySqlUtils(IFreeSql orm) : base(orm) {
}
internal override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value) {
if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}";
var ret = new MySqlParameter { ParameterName = QuoteParamterName(parameterName), Value = value };
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null) {
if ((MySqlDbType)tp.Value == MySqlDbType.Geometry) {
ret.MySqlDbType = MySqlDbType.Text;
if (value != null) ret.Value = (value as MygisGeometry).AsText();
} else
ret.MySqlDbType = (MySqlDbType)tp.Value;
}
_params?.Add(ret);
return ret;
}
internal override DbParameter[] GetDbParamtersByObject(string sql, object obj) =>
Utils.GetDbParamtersByObject<MySqlParameter>(sql, obj, "?", (name, type, value) => {
var ret = new MySqlParameter { ParameterName = $"?{name}", Value = value };
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null) {
if ((MySqlDbType)tp.Value == MySqlDbType.Geometry) {
ret.MySqlDbType = MySqlDbType.Text;
if (value != null) ret.Value = (value as MygisGeometry).AsText();
} else
ret.MySqlDbType = (MySqlDbType)tp.Value;
}
return ret;
});
internal override string FormatSql(string sql, params object[] args) => sql?.FormatMySql(args);
internal override string QuoteSqlName(string name) {
var nametrim = name.Trim();
if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
return nametrim; //原生SQL
return $"`{nametrim.Trim('`').Replace(".", "`.`")}`";
}
internal override string TrimQuoteSqlName(string name) {
var nametrim = name.Trim();
if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
return nametrim; //原生SQL
return $"{nametrim.Trim('`').Replace("`.`", ".").Replace(".`", ".")}";
}
internal override string QuoteParamterName(string name) => $"?{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
internal override string IsNull(string sql, object value) => $"ifnull({sql}, {value})";
internal override string StringConcat(string[] objs, Type[] types) => $"concat({string.Join(", ", objs)})";
internal override string Mod(string left, string right, Type leftType, Type rightType) => $"{left} % {right}";
internal override string QuoteWriteParamter(Type type, string paramterName) {
switch (type.FullName) {
case "MygisPoint":
case "MygisLineString":
case "MygisPolygon":
case "MygisMultiPoint":
case "MygisMultiLineString":
case "MygisMultiPolygon": return $"ST_GeomFromText({paramterName})";
}
return paramterName;
}
internal override string QuoteReadColumn(Type type, string columnName) {
switch (type.FullName) {
case "MygisPoint":
case "MygisLineString":
case "MygisPolygon":
case "MygisMultiPoint":
case "MygisMultiLineString":
case "MygisMultiPolygon": return $"AsText({columnName})";
}
return columnName;
}
internal override string GetNoneParamaterSqlValue(List<DbParameter> specialParams, Type type, object value) {
if (value == null) return "NULL";
if (type == typeof(byte[])) {
var bytes = value as byte[];
var sb = new StringBuilder().Append("0x");
foreach (var vc in bytes) {
if (vc < 10) sb.Append("0");
sb.Append(vc.ToString("X"));
}
return sb.ToString(); //val = Encoding.UTF8.GetString(val as byte[]);
} else if (type == typeof(TimeSpan) || type == typeof(TimeSpan?)) {
var ts = (TimeSpan)value;
value = $"{Math.Floor(ts.TotalHours)}:{ts.Minutes}:{ts.Seconds}";
}
return FormatSql("{0}", value, 1);
}
}
}

View File

@ -1,22 +0,0 @@
using FreeSql.Internal;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.Oracle.Curd {
class OracleDelete<T1> : Internal.CommonProvider.DeleteProvider<T1> where T1 : class {
public OracleDelete(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
: base(orm, commonUtils, commonExpression, dywhere) {
}
public override List<T1> ExecuteDeleted() {
throw new NotImplementedException();
}
public override Task<List<T1>> ExecuteDeletedAsync() {
throw new NotImplementedException();
}
}
}

View File

@ -1,185 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using Oracle.ManagedDataAccess.Client;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.Oracle.Curd {
class OracleInsert<T1> : Internal.CommonProvider.InsertProvider<T1> where T1 : class {
public OracleInsert(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression) {
}
public override int ExecuteAffrows() => base.SplitExecuteAffrows(500, 999);
public override Task<int> ExecuteAffrowsAsync() => base.SplitExecuteAffrowsAsync(500, 999);
public override long ExecuteIdentity() => base.SplitExecuteIdentity(500, 999);
public override Task<long> ExecuteIdentityAsync() => base.SplitExecuteIdentityAsync(500, 999);
public override List<T1> ExecuteInserted() => base.SplitExecuteInserted(500, 999);
public override Task<List<T1>> ExecuteInsertedAsync() => base.SplitExecuteInsertedAsync(500, 999);
public override string ToSql() {
if (_source == null || _source.Any() == false) return null;
var sb = new StringBuilder();
sb.Append("INSERT ");
if (_source.Count > 1) sb.Append("ALL");
_identCol = null;
var sbtb = new StringBuilder();
sbtb.Append("INTO ");
sbtb.Append(_commonUtils.QuoteSqlName(_tableRule?.Invoke(_table.DbName) ?? _table.DbName)).Append("(");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (col.Attribute.IsIdentity == true) {
_identCol = col;
continue;
}
if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.Attribute.Name) == false) {
if (colidx > 0) sbtb.Append(", ");
sbtb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name));
++colidx;
}
}
sbtb.Append(") ");
_params = _noneParameter ? new DbParameter[0] : new DbParameter[colidx * _source.Count];
var specialParams = new List<DbParameter>();
var didx = 0;
foreach (var d in _source) {
if (_source.Count > 1) sb.Append("\r\n");
sb.Append(sbtb);
sb.Append("VALUES");
sb.Append("(");
var colidx2 = 0;
foreach (var col in _table.Columns.Values) {
if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.Attribute.Name) == false) {
if (colidx2 > 0) sb.Append(", ");
object val = col.GetMapValue(d);
if (col.Attribute.IsPrimary && col.Attribute.MapType.NullableTypeOrThis() == typeof(Guid) && (val == null || (Guid)val == Guid.Empty))
col.SetMapValue(d, val = FreeUtil.NewMongodbId());
if (_noneParameter)
sb.Append(_commonUtils.GetNoneParamaterSqlValue(specialParams, col.Attribute.MapType, val));
else {
sb.Append(_commonUtils.QuoteWriteParamter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"{col.CsName}_{didx}")));
_params[didx * colidx + colidx2] = _commonUtils.AppendParamter(null, $"{col.CsName}_{didx}", col.Attribute.MapType, val);
}
++colidx2;
}
}
sb.Append(")");
++didx;
}
if (_source.Count > 1) sb.Append("\r\n SELECT 1 FROM DUAL");
return sb.ToString();
}
ColumnInfo _identCol;
internal override long RawExecuteIdentity() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
long ret = 0;
Exception exception = null;
Aop.CurdBeforeEventArgs before = null;
if (_identCol == null || _source.Count > 1) {
before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
try {
ret = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _params);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return 0;
}
var identColName = _commonUtils.QuoteSqlName(_identCol.Attribute.Name);
var identParam = _commonUtils.AppendParamter(null, $"{_identCol.CsName}99", _identCol.Attribute.MapType, 0) as OracleParameter;
identParam.Direction = ParameterDirection.Output;
sql = $"{sql} RETURNING {identColName} INTO {identParam.ParameterName}";
var dbParms = _params.Concat(new[] { identParam }).ToArray();
before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
try {
_orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, dbParms);
long.TryParse(string.Concat(identParam.Value), out ret);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
async internal override Task<long> RawExecuteIdentityAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
long ret = 0;
Exception exception = null;
Aop.CurdBeforeEventArgs before = null;
if (_identCol == null || _source.Count > 1) {
before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
try {
ret = await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, _params);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return 0;
}
var identColName = _commonUtils.QuoteSqlName(_identCol.Attribute.Name);
var identParam = _commonUtils.AppendParamter(null, $"{_identCol.CsName}99", _identCol.Attribute.MapType, 0) as OracleParameter;
identParam.Direction = ParameterDirection.Output;
sql = $"{sql} RETURNING {identColName} INTO {identParam.ParameterName}";
var dbParms = _params.Concat(new[] { identParam }).ToArray();
before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
try {
await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, dbParms);
long.TryParse(string.Concat(identParam.Value), out ret);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
internal override List<T1> RawExecuteInserted() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
this.RawExecuteAffrows();
return _source;
}
async internal override Task<List<T1>> RawExecuteInsertedAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
await this.RawExecuteAffrowsAsync();
return _source;
}
}
}

View File

@ -1,140 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace FreeSql.Oracle.Curd {
class OracleSelect<T1> : FreeSql.Internal.CommonProvider.Select1Provider<T1> where T1 : class {
internal static string ToSqlStatic(CommonUtils _commonUtils, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables, Func<Type, string, string> tableRuleInvoke, IFreeSql _orm) {
if (_orm.CodeFirst.IsAutoSyncStructure)
_orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray());
var sb = new StringBuilder();
var sbnav = new StringBuilder();
sb.Append(_select);
if (_distinct) sb.Append("DISTINCT ");
sb.Append(field);
if (string.IsNullOrEmpty(_orderby) && _skip > 0) sb.Append(", ROWNUM AS \"__rownum__\"");
sb.Append(" \r\nFROM ");
var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray();
var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray();
for (var a = 0; a < tbsfrom.Length; a++) {
sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[a].Table.Type, tbsfrom[a].Table.DbName))).Append(" ").Append(tbsfrom[a].Alias);
if (tbsjoin.Length > 0) {
//如果存在 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(tableRuleInvoke(tbsfrom[b].Table.Type, tbsfrom[b].Table.DbName))).Append(" ").Append(tbsfrom[b].Alias);
if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On)) sb.Append(" ON 1 = 1");
else sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On);
}
break;
} else {
if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")");
if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")");
}
if (a < tbsfrom.Length - 1) sb.Append(", ");
}
foreach (var tb in tbsjoin) {
if (tb.Type == SelectTableInfoType.Parent) continue;
switch (tb.Type) {
case SelectTableInfoType.LeftJoin:
sb.Append(" \r\nLEFT JOIN ");
break;
case SelectTableInfoType.InnerJoin:
sb.Append(" \r\nINNER JOIN ");
break;
case SelectTableInfoType.RightJoin:
sb.Append(" \r\nRIGHT JOIN ");
break;
}
sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tb.Table.Type, tb.Table.DbName))).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition);
if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")");
}
if (_join.Length > 0) sb.Append(_join);
sbnav.Append(_where);
foreach (var tb in _tables) {
if (tb.Type == SelectTableInfoType.Parent) continue;
if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false)
sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")");
}
if (string.IsNullOrEmpty(_orderby) && (_skip > 0 || _limit > 0)) {
sbnav.Append(" AND ROWNUM < ").Append(_skip + _limit + 1);
}
if (sbnav.Length > 0) {
sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5));
}
if (string.IsNullOrEmpty(_groupby) == false) {
sb.Append(_groupby);
if (string.IsNullOrEmpty(_having) == false)
sb.Append(" \r\nHAVING ").Append(_having.Substring(5));
}
sb.Append(_orderby);
if (string.IsNullOrEmpty(_orderby)) {
if (_skip > 0)
sb.Insert(0, "SELECT t.* FROM (").Append(") t WHERE t.\"__rownum__\" > ").Append(_skip);
} else {
if (_skip > 0 && _limit > 0) sb.Insert(0, "SELECT t.* FROM (SELECT rt.*, ROWNUM AS \"__rownum__\" FROM (").Append(") rt WHERE ROWNUM < ").Append(_skip + _limit + 1).Append(") t WHERE t.\"__rownum__\" > ").Append(_skip);
else if (_skip > 0) sb.Insert(0, "SELECT t.* FROM (").Append(") t WHERE ROWNUM > ").Append(_skip);
else if (_limit > 0) sb.Insert(0, "SELECT t.* FROM (").Append(") t WHERE ROWNUM < ").Append(_limit + 1);
}
sbnav.Clear();
return sb.ToString();
}
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override ISelect<T1, T2> From<T2>(Expression<Func<ISelectFromExpression<T1>, T2, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3> From<T2, T3>(Expression<Func<ISelectFromExpression<T1>, T2, T3, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4> From<T2, T3, T4>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3, T4>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5> From<T2, T3, T4, T5>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3, T4, T5>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6> From<T2, T3, T4, T5, T6>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3, T4, T5, T6>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7> From<T2, T3, T4, T5, T6, T7>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3, T4, T5, T6, T7>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8> From<T2, T3, T4, T5, T6, T7, T8>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3, T4, T5, T6, T7, T8>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> From<T2, T3, T4, T5, T6, T7, T8, T9>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class OracleSelect<T1, T2> : FreeSql.Internal.CommonProvider.Select2Provider<T1, T2> where T1 : class where T2 : class {
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class OracleSelect<T1, T2, T3> : FreeSql.Internal.CommonProvider.Select3Provider<T1, T2, T3> where T1 : class where T2 : class where T3 : class {
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class OracleSelect<T1, T2, T3, T4> : FreeSql.Internal.CommonProvider.Select4Provider<T1, T2, T3, T4> where T1 : class where T2 : class where T3 : class where T4 : class {
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class OracleSelect<T1, T2, T3, T4, T5> : FreeSql.Internal.CommonProvider.Select5Provider<T1, T2, T3, T4, T5> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class {
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class OracleSelect<T1, T2, T3, T4, T5, T6> : FreeSql.Internal.CommonProvider.Select6Provider<T1, T2, T3, T4, T5, T6> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class {
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class OracleSelect<T1, T2, T3, T4, T5, T6, T7> : FreeSql.Internal.CommonProvider.Select7Provider<T1, T2, T3, T4, T5, T6, T7> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class {
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class OracleSelect<T1, T2, T3, T4, T5, T6, T7, T8> : FreeSql.Internal.CommonProvider.Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class {
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class OracleSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> : FreeSql.Internal.CommonProvider.Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class {
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class OracleSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : FreeSql.Internal.CommonProvider.Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class {
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
}

View File

@ -1,61 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.Oracle.Curd {
class OracleUpdate<T1> : Internal.CommonProvider.UpdateProvider<T1> where T1 : class {
public OracleUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
: base(orm, commonUtils, commonExpression, dywhere) {
}
public override int ExecuteAffrows() => base.SplitExecuteAffrows(200, 999);
public override Task<int> ExecuteAffrowsAsync() => base.SplitExecuteAffrowsAsync(200, 999);
public override List<T1> ExecuteUpdated() => base.SplitExecuteUpdated(200, 999);
public override Task<List<T1>> ExecuteUpdatedAsync() => base.SplitExecuteUpdatedAsync(200, 999);
internal override List<T1> RawExecuteUpdated() {
throw new NotImplementedException();
}
internal override Task<List<T1>> RawExecuteUpdatedAsync() {
throw new NotImplementedException();
}
protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
if (_table.Primarys.Length == 1) {
caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().Attribute.MapType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
return;
}
caseWhen.Append("(");
var pkidx = 0;
foreach (var pk in _table.Primarys) {
if (pkidx > 0) caseWhen.Append(" || ");
caseWhen.Append(_commonUtils.QuoteReadColumn(pk.Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name)));
++pkidx;
}
caseWhen.Append(")");
}
protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
if (_table.Primarys.Length == 1) {
sb.Append(_commonUtils.FormatSql("{0}", _table.Primarys.First().GetMapValue(d)));
return;
}
sb.Append("(");
var pkidx = 0;
foreach (var pk in _table.Primarys) {
if (pkidx > 0) sb.Append(" || ");
sb.Append(_commonUtils.FormatSql("{0}", pk.GetMapValue(d)));
++pkidx;
}
sb.Append(")");
}
}
}

View File

@ -1,62 +0,0 @@
using FreeSql.Internal;
using Microsoft.Extensions.Logging;
using Oracle.ManagedDataAccess.Client;
using SafeObjectPool;
using System;
using System.Collections;
using System.Data.Common;
using System.Text;
using System.Threading;
namespace FreeSql.Oracle {
class OracleAdo : FreeSql.Internal.CommonProvider.AdoProvider {
public OracleAdo() : base(null, null, DataType.Oracle) { }
public OracleAdo(CommonUtils util, ICache cache, ILogger log, string masterConnectionString, string[] slaveConnectionStrings) : base(cache, log, DataType.Oracle) {
base._util = util;
if (!string.IsNullOrEmpty(masterConnectionString))
MasterPool = new OracleConnectionPool("主库", masterConnectionString, null, null);
if (slaveConnectionStrings != null) {
foreach (var slaveConnectionString in slaveConnectionStrings) {
var slavePool = new OracleConnectionPool($"从库{SlavePools.Count + 1}", slaveConnectionString, () => Interlocked.Decrement(ref slaveUnavailables), () => Interlocked.Increment(ref slaveUnavailables));
SlavePools.Add(slavePool);
}
}
}
static DateTime dt1970 = new DateTime(1970, 1, 1);
public override object AddslashesProcessParam(object param, Type mapType) {
if (param == null) return "NULL";
if (mapType != null && mapType != param.GetType())
param = Utils.GetDataReaderValue(mapType, param);
if (param is bool || param is bool?)
return (bool)param ? 1 : 0;
else if (param is string || param is char)
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
else if (param is Enum)
return ((Enum)param).ToInt64();
else if (decimal.TryParse(string.Concat(param), out var trydec))
return param;
else if (param is DateTime || param is DateTime?)
return string.Concat("to_timestamp('", ((DateTime)param).ToString("yyyy-MM-dd HH:mm:ss.ffffff"), "','YYYY-MM-DD HH24:MI:SS.FF6')");
else if (param is TimeSpan || param is TimeSpan?)
return $"numtodsinterval({((TimeSpan)param).Ticks * 1.0 / 10000000},'second')";
else if (param is IEnumerable) {
var sb = new StringBuilder();
var ie = param as IEnumerable;
foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType));
return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
}
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
//if (param is string) return string.Concat('N', nparms[a]);
}
protected override DbCommand CreateCommand() {
return new OracleCommand();
}
protected override void ReturnConnection(ObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex) {
(pool as OracleConnectionPool).Return(conn, ex);
}
protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj);
}
}

View File

@ -1,191 +0,0 @@
using Oracle.ManagedDataAccess.Client;
using SafeObjectPool;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace FreeSql.Oracle {
class OracleConnectionPool : ObjectPool<DbConnection> {
internal Action availableHandler;
internal Action unavailableHandler;
internal string UserId { get; set; }
public OracleConnectionPool(string name, string connectionString, Action availableHandler, Action unavailableHandler) : base(null) {
var userIdMatch = Regex.Match(connectionString, @"User\s+Id\s*=\s*([^;]+)", RegexOptions.IgnoreCase);
if (userIdMatch.Success == false) throw new Exception(@"从 ConnectionString 中无法匹配 User\s+Id\s+=([^;]+)");
this.UserId = userIdMatch.Groups[1].Value.Trim().ToUpper();
var policy = new OracleConnectionPoolPolicy {
_pool = this,
Name = name
};
this.Policy = policy;
policy.ConnectionString = connectionString;
this.availableHandler = availableHandler;
this.unavailableHandler = unavailableHandler;
}
public void Return(Object<DbConnection> obj, Exception exception, bool isRecreate = false) {
if (exception != null && exception is OracleException) {
if (exception is System.IO.IOException) {
base.SetUnavailable(exception);
} else if (obj.Value.Ping() == false) {
base.SetUnavailable(exception);
}
}
base.Return(obj, isRecreate);
}
}
class OracleConnectionPoolPolicy : IPolicy<DbConnection> {
internal OracleConnectionPool _pool;
public string Name { get; set; } = "Oracle Connection 对象池";
public int PoolSize { get; set; } = 100;
public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
public TimeSpan IdleTimeout { get; set; } = TimeSpan.Zero;
public int AsyncGetCapacity { get; set; } = 10000;
public bool IsThrowGetTimeoutException { get; set; } = true;
public int CheckAvailableInterval { get; set; } = 5;
static ConcurrentDictionary<string, int> dicConnStrIncr = new ConcurrentDictionary<string, int>(StringComparer.CurrentCultureIgnoreCase);
private string _connectionString;
public string ConnectionString {
get => _connectionString;
set {
_connectionString = value ?? "";
var pattern = @"Max\s*pool\s*size\s*=\s*(\d+)";
Match m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success == false || int.TryParse(m.Groups[1].Value, out var poolsize) == false || poolsize <= 0) poolsize = 100;
var connStrIncr = dicConnStrIncr.AddOrUpdate(_connectionString, 1, (oldkey, oldval) => oldval + 1);
PoolSize = poolsize + connStrIncr;
_connectionString = m.Success ?
Regex.Replace(_connectionString, pattern, $"Max pool size={PoolSize}", RegexOptions.IgnoreCase) :
$"{_connectionString};Max pool size={PoolSize}";
pattern = @"Connection\s*LifeTime\s*=\s*(\d+)";
m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success) {
IdleTimeout = TimeSpan.FromSeconds(int.Parse(m.Groups[1].Value));
_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase);
}
var minPoolSize = 0;
pattern = @"Min\s*pool\s*size\s*=\s*(\d+)";
m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success) {
minPoolSize = int.Parse(m.Groups[1].Value);
_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase);
}
FreeUtil.PrevReheatConnectionPool(_pool, minPoolSize);
}
}
public bool OnCheckAvailable(Object<DbConnection> obj) {
if (obj.Value.State == ConnectionState.Closed) obj.Value.Open();
return obj.Value.Ping(true);
}
public DbConnection OnCreate() {
var conn = new OracleConnection(_connectionString);
return conn;
}
public void OnDestroy(DbConnection obj) {
if (obj.State != ConnectionState.Closed) obj.Close();
obj.Dispose();
}
public void OnGet(Object<DbConnection> obj) {
if (_pool.IsAvailable) {
if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && obj.Value.Ping() == false) {
try {
obj.Value.Open();
} catch (Exception ex) {
if (_pool.SetUnavailable(ex) == true)
throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}");
}
}
}
}
async public Task OnGetAsync(Object<DbConnection> obj) {
if (_pool.IsAvailable) {
if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && (await obj.Value.PingAsync()) == false) {
try {
await obj.Value.OpenAsync();
} catch (Exception ex) {
if (_pool.SetUnavailable(ex) == true)
throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}");
}
}
}
}
public void OnGetTimeout() {
}
public void OnReturn(Object<DbConnection> obj) {
}
public void OnAvailable() {
_pool.availableHandler?.Invoke();
}
public void OnUnavailable() {
_pool.unavailableHandler?.Invoke();
}
}
static class DbConnectionExtensions {
static DbCommand PingCommand(DbConnection conn) {
var cmd = conn.CreateCommand();
cmd.CommandTimeout = 5;
cmd.CommandText = "select 1 from dual";
return cmd;
}
public static bool Ping(this DbConnection that, bool isThrow = false) {
try {
PingCommand(that).ExecuteNonQuery();
return true;
} catch {
if (that.State != ConnectionState.Closed) try { that.Close(); } catch { }
if (isThrow) throw;
return false;
}
}
async public static Task<bool> PingAsync(this DbConnection that, bool isThrow = false) {
try {
await PingCommand(that).ExecuteNonQueryAsync();
return true;
} catch {
if (that.State != ConnectionState.Closed) try { that.Close(); } catch { }
if (isThrow) throw;
return false;
}
}
}
}

View File

@ -1,372 +0,0 @@
using FreeSql.DataAnnotations;
using FreeSql.DatabaseModel;
using FreeSql.Internal;
using FreeSql.Internal.Model;
using Oracle.ManagedDataAccess.Client;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace FreeSql.Oracle {
class OracleCodeFirst : ICodeFirst {
IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
public OracleCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) {
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
}
public bool IsAutoSyncStructure { get; set; } = false;
public bool IsSyncStructureToLower { get; set; } = false;
public bool IsSyncStructureToUpper { get; set; } = false;
public bool IsConfigEntityFromDbFirst { get; set; } = false;
public bool IsNoneCommandParameter { get; set; } = false;
public bool IsLazyLoading { get; set; } = false;
static object _dicCsToDbLock = new object();
static Dictionary<string, (OracleDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)> _dicCsToDb = new Dictionary<string, (OracleDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)>() {
{ typeof(bool).FullName, (OracleDbType.Boolean, "number","number(1) NOT NULL", null, false, false) },{ typeof(bool?).FullName, (OracleDbType.Boolean, "number","number(1) NULL", null, true, null) },
{ typeof(sbyte).FullName, (OracleDbType.Decimal, "number", "number(4) NOT NULL", false, false, 0) },{ typeof(sbyte?).FullName, (OracleDbType.Decimal, "number", "number(4) NULL", false, true, null) },
{ typeof(short).FullName, (OracleDbType.Int16, "number","number(6) NOT NULL", false, false, 0) },{ typeof(short?).FullName, (OracleDbType.Int16, "number", "number(6) NULL", false, true, null) },
{ typeof(int).FullName, (OracleDbType.Int32, "number", "number(11) NOT NULL", false, false, 0) },{ typeof(int?).FullName, (OracleDbType.Int32, "number", "number(11) NULL", false, true, null) },
{ typeof(long).FullName, (OracleDbType.Int64, "number","number(21) NOT NULL", false, false, 0) },{ typeof(long?).FullName, (OracleDbType.Int64, "number","number(21) NULL", false, true, null) },
{ typeof(byte).FullName, (OracleDbType.Byte, "number","number(3) NOT NULL", true, false, 0) },{ typeof(byte?).FullName, (OracleDbType.Byte, "number","number(3) NULL", true, true, null) },
{ typeof(ushort).FullName, (OracleDbType.Decimal, "number","number(5) NOT NULL", true, false, 0) },{ typeof(ushort?).FullName, (OracleDbType.Decimal, "number", "number(5) NULL", true, true, null) },
{ typeof(uint).FullName, (OracleDbType.Decimal, "number", "number(10) NOT NULL", true, false, 0) },{ typeof(uint?).FullName, (OracleDbType.Decimal, "number", "number(10) NULL", true, true, null) },
{ typeof(ulong).FullName, (OracleDbType.Decimal, "number", "number(20) NOT NULL", true, false, 0) },{ typeof(ulong?).FullName, (OracleDbType.Decimal, "number", "number(20) NULL", true, true, null) },
{ typeof(double).FullName, (OracleDbType.Double, "float", "float(126) NOT NULL", false, false, 0) },{ typeof(double?).FullName, (OracleDbType.Double, "float", "float(126) NULL", false, true, null) },
{ typeof(float).FullName, (OracleDbType.Single, "float","float(63) NOT NULL", false, false, 0) },{ typeof(float?).FullName, (OracleDbType.Single, "float","float(63) NULL", false, true, null) },
{ typeof(decimal).FullName, (OracleDbType.Decimal, "number", "number(10,2) NOT NULL", false, false, 0) },{ typeof(decimal?).FullName, (OracleDbType.Decimal, "number", "number(10,2) NULL", false, true, null) },
{ typeof(TimeSpan).FullName, (OracleDbType.IntervalDS, "interval day to second","interval day(2) to second(6) NOT NULL", false, false, 0) },{ typeof(TimeSpan?).FullName, (OracleDbType.IntervalDS, "interval day to second", "interval day(2) to second(6) NULL",false, true, null) },
{ typeof(DateTime).FullName, (OracleDbType.TimeStamp, "timestamp", "timestamp(6) NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, (OracleDbType.TimeStamp, "timestamp", "timestamp(6) NULL", false, true, null) },
{ typeof(DateTimeOffset).FullName, (OracleDbType.TimeStampLTZ, "timestamp with local time zone", "timestamp(6) with local time zone NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTimeOffset?).FullName, (OracleDbType.TimeStampLTZ, "timestamp with local time zone", "timestamp(6) with local time zone NULL", false, true, null) },
{ typeof(byte[]).FullName, (OracleDbType.Blob, "blob", "blob NULL", false, null, new byte[0]) },
{ typeof(string).FullName, (OracleDbType.NVarchar2, "nvarchar2", "nvarchar2(255) NULL", false, null, "") },
{ typeof(Guid).FullName, (OracleDbType.Char, "char", "char(36 CHAR) NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName, (OracleDbType.Char, "char", "char(36 CHAR) NULL", false, true, null) },
};
public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) {
if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (int, string, string, bool?, object)?(((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue));
if (type.IsArray) return null;
var enumType = type.IsEnum ? type : null;
if (enumType == null && type.IsNullableType() && type.GenericTypeArguments.Length == 1 && type.GenericTypeArguments.First().IsEnum) enumType = type.GenericTypeArguments.First();
if (enumType != null) {
var newItem = enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Any() ?
(OracleDbType.Int32, "number", $"number(16){(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0)) :
(OracleDbType.Int64, "number", $"number(32){(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0));
if (_dicCsToDb.ContainsKey(type.FullName) == false) {
lock (_dicCsToDbLock) {
if (_dicCsToDb.ContainsKey(type.FullName) == false)
_dicCsToDb.Add(type.FullName, newItem);
}
}
return ((int)newItem.Item1, newItem.Item2, newItem.Item3, newItem.Item5, newItem.Item6);
}
return null;
}
public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity));
public string GetComparisonDDLStatements(params Type[] entityTypes) {
var userId = (_orm.Ado.MasterPool as OracleConnectionPool).UserId;
var seqcols = new List<(ColumnInfo, string[], bool)>(); //序列
var sb = new StringBuilder();
var sbDeclare = new StringBuilder();
foreach (var entityType in entityTypes) {
if (sb.Length > 0) sb.Append("\r\n");
var tb = _commonUtils.GetTableByEntity(entityType);
if (tb == null) throw new Exception($"类型 {entityType.FullName} 不可迁移");
if (tb.Columns.Any() == false) throw new Exception($"类型 {entityType.FullName} 不可迁移可迁移属性0个");
var tbname = tb.DbName.Split(new[] { '.' }, 2);
if (tbname?.Length == 1) tbname = new[] { userId, tbname[0] };
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //旧表名
if (tboldname?.Length == 1) tboldname = new[] { userId, tboldname[0] };
if (string.Compare(tbname[0], userId) != 0 && _orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(" select 1 from sys.dba_users where username={0}", tbname[0])) == null) //创建数据库
throw new NotImplementedException($"Oracle CodeFirst 不支持代码创建 tablespace 与 schemas {tbname[0]}");
var sbalter = new StringBuilder();
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
if (_orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(" select 1 from all_tab_comments where owner={0} and table_name={1}", tbname)) == null) { //表不存在
if (tboldname != null) {
if (_orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(" select 1 from all_tab_comments where owner={0} and table_name={1}", tboldname)) == null)
//模式或表不存在
tboldname = null;
}
if (tboldname == null) {
//创建表
sb.Append("execute immediate 'CREATE TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ( ");
foreach (var tbcol in tb.Columns.Values) {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(",");
if (tbcol.Attribute.IsIdentity == true) seqcols.Add((tbcol, tbname, true));
}
if (tb.Primarys.Any()) {
sb.Append(" \r\n CONSTRAINT ").Append(tbname[0]).Append("_").Append(tbname[1]).Append("_pk1 PRIMARY KEY (");
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
foreach (var uk in tb.Uniques) {
sb.Append(" \r\n CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(" UNIQUE (");
foreach (var tbcol in uk.Value) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
sb.Remove(sb.Length - 1, 1);
sb.Append("\r\n) \r\nLOGGING \r\nNOCOMPRESS \r\nNOCACHE\r\n';\r\n");
continue;
}
//如果新表,旧表在一个模式下,直接修改表名
if (string.Compare(tbname[0], tboldname[0], true) == 0)
sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}")).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[1]}")).Append("';\r\n");
else {
//如果新表,旧表不在一起,创建新表,导入数据,删除旧表
istmpatler = true;
}
} else
tboldname = null; //如果新表已经存在,不走改表名逻辑
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
var sql = _commonUtils.FormatSql($@"
select
column_name,
data_type,
data_length,
data_precision,
data_scale,
char_used,
case when nullable = 'Y' then 1 else 0 end,
nvl((select 1 from user_sequences where sequence_name='{Utils.GetCsName((tboldname ?? tbname).Last())}_seq_'||all_tab_columns.column_name), 0),
nvl((select 1 from user_triggers where trigger_name='{Utils.GetCsName((tboldname ?? tbname).Last())}_seq_'||all_tab_columns.column_name||'TI'), 0)
from all_tab_columns
where owner={{0}} and table_name={{1}}", tboldname ?? tbname);
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => {
var sqlType = GetOracleSqlTypeFullName(a);
return new {
column = string.Concat(a[0]),
sqlType,
is_nullable = string.Concat(a[6]) == "1",
is_identity = string.Concat(a[7]) == "1" && string.Concat(a[8]) == "1"
};
}, StringComparer.CurrentCultureIgnoreCase);
if (istmpatler == false) {
foreach (var tbcol in tb.Columns.Values) {
var dbtypeNoneNotNull = Regex.Replace(tbcol.Attribute.DbType, @"NOT\s+NULL", "NULL");
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false)
istmpatler = true;
//sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY (").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(dbtypeNoneNotNull).Append(")';\r\n");
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) {
if (tbcol.Attribute.IsNullable == false)
sbalter.Append("execute immediate 'UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" = ").Append(_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''")).Append(" WHERE ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" IS NULL';\r\n");
sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(tbcol.Attribute.IsNullable == true ? "" : "NOT").Append(" NULL';\r\n");
}
if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity)
seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity == true));
if (tbstructcol.column == tbcol.Attribute.OldName)
//修改列名
sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.OldName)).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append("';\r\n");
continue;
}
//添加列
sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD (").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(dbtypeNoneNotNull).Append(")';\r\n");
if (tbcol.Attribute.IsNullable == false) {
sbalter.Append("execute immediate 'UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" = ").Append(_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''")).Append("';\r\n");
sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" NOT NULL';\r\n");
}
if (tbcol.Attribute.IsIdentity == true) seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity == true));
}
var dsuksql = _commonUtils.FormatSql(@"
select
c.column_name,
c.constraint_name
from
all_constraints a,
all_cons_columns c
where
a.constraint_name = c.constraint_name
and a.owner = c.owner
and a.table_name = c.table_name
and a.constraint_type in ('U')
and a.owner in ({0}) and a.table_name in ({1})", tboldname ?? tbname);
var dsuk = _orm.Ado.ExecuteArray(CommandType.Text, dsuksql).Select(a => new[] { string.Concat(a[0]), string.Concat(a[1]) });
foreach (var uk in tb.Uniques) {
if (string.IsNullOrEmpty(uk.Key) || uk.Value.Any() == false) continue;
var dsukfind1 = dsuk.Where(a => string.Compare(a[1], uk.Key, true) == 0).ToArray();
if (dsukfind1.Any() == false || dsukfind1.Length != uk.Value.Count || dsukfind1.Where(a => uk.Value.Where(b => string.Compare(b.Attribute.Name, a[0], true) == 0).Any()).Count() != uk.Value.Count) {
if (dsukfind1.Any()) sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" DROP CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append("';\r\n");
sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(" UNIQUE(");
foreach (var tbcol in uk.Value) sbalter.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sbalter.Remove(sbalter.Length - 2, 2).Append(")';\r\n");
}
}
}
if (istmpatler == false) {
sb.Append(sbalter);
continue;
}
var oldpk = _orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(@"select constraint_name from user_constraints where owner={0} and table_name={1} and constraint_type='P'", tbname))?.ToString();
if (string.IsNullOrEmpty(oldpk) == false)
sb.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" DROP CONSTRAINT ").Append(oldpk).Append("';\r\n");
//创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名
var tablename = tboldname == null ? _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}") : _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}");
var tmptablename = _commonUtils.QuoteSqlName($"{tbname[0]}.FTmp_{tbname[1]}");
//创建临时表
sb.Append("execute immediate 'CREATE TABLE ").Append(tmptablename).Append(" ( ");
foreach (var tbcol in tb.Columns.Values) {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(",");
if (tbcol.Attribute.IsIdentity == true) seqcols.Add((tbcol, tbname, true));
}
if (tb.Primarys.Any()) {
sb.Append(" \r\n CONSTRAINT ").Append(tbname[0]).Append("_").Append(tbname[1]).Append("_pk2 PRIMARY KEY (");
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
foreach (var uk in tb.Uniques) {
sb.Append(" \r\n CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(" UNIQUE (");
foreach (var tbcol in uk.Value) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
sb.Remove(sb.Length - 1, 1);
sb.Append("\r\n) LOGGING \r\nNOCOMPRESS \r\nNOCACHE\r\n';\r\n");
sb.Append("execute immediate 'INSERT INTO ").Append(tmptablename).Append(" (");
foreach (var tbcol in tb.Columns.Values)
sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append(")\r\nSELECT ");
foreach (var tbcol in tb.Columns.Values) {
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)) {
insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column);
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) {
var dbtypeNoneNotNull = Regex.Replace(tbcol.Attribute.DbType, @"(NOT\s+)?NULL", "");
insertvalue = $"cast({insertvalue} as {dbtypeNoneNotNull})";
}
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable)
insertvalue = $"nvl({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue)})";
} else if (tbcol.Attribute.IsNullable == false)
insertvalue = _commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue);
sb.Append(insertvalue.Replace("'", "''")).Append(", ");
}
sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append("';\r\n");
sb.Append("execute immediate 'DROP TABLE ").Append(tablename).Append("';\r\n");
sb.Append("execute immediate 'ALTER TABLE ").Append(tmptablename).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[1]}")).Append("';\r\n");
}
Dictionary<string, bool> dicDeclare = new Dictionary<string, bool>();
foreach (var seqcol in seqcols) {
var tbname = seqcol.Item2;
var seqname = Utils.GetCsName($"{tbname[1]}_seq_{seqcol.Item1.Attribute.Name}");
var tiggerName = seqname + "TI";
var tbname2 = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}");
var colname2 = _commonUtils.QuoteSqlName(seqcol.Item1.Attribute.Name);
if (dicDeclare.ContainsKey(seqname) == false) {
sbDeclare.Append("\r\n").Append(seqname).Append("IS NUMBER; \r\n");
dicDeclare.Add(seqname, true);
}
sb.Append(seqname).Append("IS := 0; \r\n")
.Append(" select count(1) into ").Append(seqname).Append(_commonUtils.FormatSql("IS from user_sequences where sequence_name={0}; \r\n", seqname))
.Append("if ").Append(seqname).Append("IS > 0 then \r\n")
.Append(" execute immediate 'DROP SEQUENCE ").Append(_commonUtils.QuoteSqlName(seqname)).Append("';\r\n")
.Append("end if; \r\n");
if (seqcol.Item3) {
var startWith = _orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(" select 1 from all_tab_comments where owner={0} and table_name={1}", tbname)) == null ? 1 :
_orm.Ado.ExecuteScalar(CommandType.Text, $" select nvl(max({colname2})+1,1) from {tbname2}");
sb.Append("execute immediate 'CREATE SEQUENCE ").Append(_commonUtils.QuoteSqlName(seqname)).Append(" start with ").Append(startWith).Append("';\r\n");
sb.Append("execute immediate 'CREATE OR REPLACE TRIGGER ").Append(_commonUtils.QuoteSqlName(tiggerName))
.Append(" \r\nbefore insert on ").Append(tbname2)
.Append(" \r\nfor each row \r\nbegin\r\nselect ").Append(_commonUtils.QuoteSqlName(seqname))
.Append(".nextval into :new.").Append(colname2).Append(" from dual;\r\nend;';\r\n");
} else {
if (dicDeclare.ContainsKey(tiggerName) == false) {
sbDeclare.Append("\r\n").Append(tiggerName).Append("IS NUMBER; \r\n");
dicDeclare.Add(tiggerName, true);
}
sb.Append(tiggerName).Append("IS := 0; \r\n")
.Append(" select count(1) into ").Append(tiggerName).Append(_commonUtils.FormatSql("IS from user_triggers where trigger_name={0}; \r\n", tiggerName))
.Append("if ").Append(tiggerName).Append("IS > 0 then \r\n")
.Append(" execute immediate 'DROP TRIGGER ").Append(_commonUtils.QuoteSqlName(tiggerName)).Append("';\r\n")
.Append("end if; \r\n");
}
}
if (sbDeclare.Length > 0) sbDeclare.Insert(0, "declare ");
return sb.Length == 0 ? null : sb.Insert(0, "BEGIN \r\n").Insert(0, sbDeclare.ToString()).Append("END;").ToString();
}
internal static string GetOracleSqlTypeFullName(object[] row) {
var a = row;
var sqlType = string.Concat(a[1]).ToUpper();
var data_length = long.Parse(string.Concat(a[2]));
long.TryParse(string.Concat(a[3]), out var data_precision);
long.TryParse(string.Concat(a[4]), out var data_scale);
var char_used = string.Concat(a[5]);
if (Regex.IsMatch(sqlType, @"INTERVAL DAY\(\d+\) TO SECOND\(\d+\)", RegexOptions.IgnoreCase)) {
} else if (Regex.IsMatch(sqlType, @"INTERVAL YEAR\(\d+\) TO MONTH", RegexOptions.IgnoreCase)) {
} else if (sqlType.StartsWith("TIMESTAMP", StringComparison.CurrentCultureIgnoreCase)) {
} else if (sqlType.StartsWith("BLOB")) {
} else if (char_used.ToLower() == "c")
sqlType += sqlType.StartsWith("N") ? $"({data_length / 2})" : $"({data_length / 4} CHAR)";
else if (char_used.ToLower() == "b")
sqlType += $"({data_length} BYTE)";
else if (sqlType.ToLower() == "float")
sqlType += $"({data_precision})";
else if (data_precision > 0 && data_scale > 0)
sqlType += $"({data_precision},{data_scale})";
else if (data_precision > 0)
sqlType += $"({data_precision})";
else
sqlType += $"({data_length})";
return sqlType;
}
static object syncStructureLock = new object();
ConcurrentDictionary<string, bool> dicSyced = new ConcurrentDictionary<string, bool>();
public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity));
public bool SyncStructure(params Type[] entityTypes) {
if (entityTypes == null) return true;
var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray();
if (syncTypes.Any() == false) return true;
var before = new Aop.SyncStructureBeforeEventArgs(entityTypes);
_orm.Aop.SyncStructureBefore?.Invoke(this, before);
Exception exception = null;
string ddl = null;
try {
lock (syncStructureLock) {
ddl = this.GetComparisonDDLStatements(syncTypes);
if (string.IsNullOrEmpty(ddl)) {
foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true);
return true;
}
var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl);
foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true);
return affrows > 0;
}
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception);
_orm.Aop.SyncStructureAfter?.Invoke(this, after);
}
}
public ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) => _commonUtils.ConfigEntity(entity);
public ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) => _commonUtils.ConfigEntity(type, entity);
public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type);
public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type);
}
}

View File

@ -1,427 +0,0 @@
using FreeSql.DatabaseModel;
using FreeSql.Internal;
using Oracle.ManagedDataAccess.Client;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text.RegularExpressions;
namespace FreeSql.Oracle {
class OracleDbFirst : IDbFirst {
IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
public OracleDbFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) {
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
}
public int GetDbType(DbColumnInfo column) => (int)GetSqlDbType(column);
OracleDbType GetSqlDbType(DbColumnInfo column) {
var dbfull = column.DbTypeTextFull.ToLower();
switch (dbfull) {
case "number(1)": return OracleDbType.Boolean;
case "number(4)": return OracleDbType.Decimal;
case "number(6)": return OracleDbType.Int16;
case "number(11)": return OracleDbType.Int32;
case "number(21)": return OracleDbType.Int64;
case "number(3)": return OracleDbType.Byte;
case "number(5)": return OracleDbType.Decimal;
case "number(10)": return OracleDbType.Decimal;
case "number(20)": return OracleDbType.Decimal;
case "float(126)": return OracleDbType.Double;
case "float(63)": return OracleDbType.Single;
case "number(10,2)": return OracleDbType.Decimal;
case "interval day(2) to second(6)": return OracleDbType.IntervalDS;
case "timestamp(6)": return OracleDbType.TimeStamp;
case "timestamp(6) with local time zone": return OracleDbType.TimeStampLTZ;
case "blob": return OracleDbType.Blob;
case "nvarchar2(255)": return OracleDbType.NVarchar2;
case "char(36 char)": return OracleDbType.Char;
}
switch (column.DbTypeText.ToLower()) {
case "number":
_dicDbToCs.TryAdd(dbfull, _dicDbToCs["number(10,2)"]);
return OracleDbType.Decimal;
case "float":
_dicDbToCs.TryAdd(dbfull, _dicDbToCs["float(126)"]);
return OracleDbType.Double;
case "interval day to second":
_dicDbToCs.TryAdd(dbfull, _dicDbToCs["interval day(2) to second(6)"]);
return OracleDbType.IntervalDS;
case "timestamp":
_dicDbToCs.TryAdd(dbfull, _dicDbToCs["timestamp(6)"]);
return OracleDbType.TimeStamp;
case "timestamp with local time zone":
_dicDbToCs.TryAdd(dbfull, _dicDbToCs["timestamp(6) with local time zone"]);
return OracleDbType.TimeStampLTZ;
case "blob":
_dicDbToCs.TryAdd(dbfull, _dicDbToCs["blob"]);
return OracleDbType.Blob;
case "nvarchar2":
_dicDbToCs.TryAdd(dbfull, _dicDbToCs["nvarchar2(255)"]);
return OracleDbType.NVarchar2;
case "varchar2":
_dicDbToCs.TryAdd(dbfull, _dicDbToCs["nvarchar2(255)"]);
return OracleDbType.Varchar2;
case "char":
_dicDbToCs.TryAdd(dbfull, _dicDbToCs["char(36 char)"]);
return OracleDbType.Char;
case "clob":
_dicDbToCs.TryAdd(dbfull, _dicDbToCs["nvarchar2(255)"]);
return OracleDbType.Clob;
case "nclob":
_dicDbToCs.TryAdd(dbfull, _dicDbToCs["nvarchar2(255)"]);
return OracleDbType.NClob;
}
throw new NotImplementedException($"未实现 {column.DbTypeTextFull} 类型映射");
}
static ConcurrentDictionary<string, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)> _dicDbToCs = new ConcurrentDictionary<string, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)>();
static OracleDbFirst() {
var defaultDbToCs = new Dictionary<string, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)>() {
{ "number(1)", ("(bool?)", "{0} == \"1\"", "{0} == true ? \"1\" : \"0\"", "bool?", typeof(bool), typeof(bool?), "{0}.Value", "GetBoolean") },
{ "number(4)", ("(sbyte?)", "sbyte.Parse({0})", "{0}.ToString()", "sbyte?", typeof(sbyte), typeof(sbyte?), "{0}.Value", "GetInt16") },
{ "number(6)", ("(short?)", "short.Parse({0})", "{0}.ToString()", "short?", typeof(short), typeof(short?), "{0}.Value", "GetInt16") },
{ "number(11)", ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
{ "number(21)", ("(long?)", "long.Parse({0})", "{0}.ToString()", "long?", typeof(long), typeof(long?), "{0}.Value", "GetInt64") },
{ "number(3)", ("(byte?)", "byte.Parse({0})", "{0}.ToString()", "byte?", typeof(byte), typeof(byte?), "{0}.Value", "GetByte") },
{ "number(5)", ("(ushort?)", "ushort.Parse({0})", "{0}.ToString()", "ushort?", typeof(ushort), typeof(ushort?), "{0}.Value", "GetInt32") },
{ "number(10)", ("(uint?)", "uint.Parse({0})", "{0}.ToString()", "uint?", typeof(uint), typeof(uint?), "{0}.Value", "GetInt64") },
{ "number(20)", ("(ulong?)", "ulong.Parse({0})", "{0}.ToString()", "ulong?", typeof(ulong), typeof(ulong?), "{0}.Value", "GetDecimal") },
{ "float(126)", ("(double?)", "double.Parse({0})", "{0}.ToString()", "double?", typeof(double), typeof(double?), "{0}.Value", "GetDouble") },
{ "float(63)", ("(float?)", "float.Parse({0})", "{0}.ToString()", "float?", typeof(float), typeof(float?), "{0}.Value", "GetFloat") },
{ "number(10,2)", ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") },
{ "interval day(2) to second(6)", ("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") },
{ "timestamp(6)", ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetValue") },
{ "timestamp(6) with local time zone", ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetValue") },
{ "blob", ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
{ "nvarchar2(255)", ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ "char(36 char)", ("(Guid?)", "Guid.Parse({0})", "{0}.ToString()", "Guid?", typeof(Guid), typeof(Guid?), "{0}.Value", "GetGuid") },
};
foreach (var kv in defaultDbToCs)
_dicDbToCs.TryAdd(kv.Key, kv.Value);
}
public string GetCsConvert(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbTypeTextFull, out var trydc) ? (column.IsNullable ? trydc.csConvert : trydc.csConvert.Replace("?", "")) : null;
public string GetCsParse(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbTypeTextFull, out var trydc) ? trydc.csParse : null;
public string GetCsStringify(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbTypeTextFull, out var trydc) ? trydc.csStringify : null;
public string GetCsType(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbTypeTextFull, out var trydc) ? (column.IsNullable ? trydc.csType : trydc.csType.Replace("?", "")) : null;
public Type GetCsTypeInfo(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbTypeTextFull, out var trydc) ? trydc.csTypeInfo : null;
public string GetCsTypeValue(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbTypeTextFull, out var trydc) ? trydc.csTypeValue : null;
public string GetDataReaderMethod(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbTypeTextFull, out var trydc) ? trydc.dataReaderMethod : null;
public List<string> GetDatabases() {
var sql = @" select username from all_users";
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList();
}
public List<DbTableInfo> GetTablesByDatabase(params string[] database2) {
var loc1 = new List<DbTableInfo>();
var loc2 = new Dictionary<string, DbTableInfo>();
var loc3 = new Dictionary<string, Dictionary<string, DbColumnInfo>>();
var database = database2?.ToArray();
if (database == null || database.Any() == false) {
var userUsers = _orm.Ado.ExecuteScalar("select username from user_users")?.ToString();
if (string.IsNullOrEmpty(userUsers)) return loc1;
database = new[] { userUsers };
}
var databaseIn = string.Join(",", database.Select(a => _commonUtils.FormatSql("{0}", a)));
var sql = string.Format(@"
select
a.owner || '.' || a.table_name,
a.owner,
a.table_name,
b.comments,
'TABLE'
from all_tables a
left join all_tab_comments b on b.owner = a.owner and b.table_name = a.table_name and b.table_type = 'TABLE'
where a.owner in ({0})", databaseIn);
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var loc6 = new List<string>();
var loc66 = new List<string>();
foreach (var row in ds) {
var table_id = string.Concat(row[0]);
var schema = string.Concat(row[1]);
var table = string.Concat(row[2]);
var comment = string.Concat(row[3]);
var type = string.Concat(row[4]) == "VIEW" ? DbTableType.VIEW : DbTableType.TABLE;
if (database.Length == 1) {
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
schema = "";
}
loc2.Add(table_id, new DbTableInfo { Id = table_id, Schema = schema, Name = table, Comment = comment, Type = type });
loc3.Add(table_id, new Dictionary<string, DbColumnInfo>());
switch (type) {
case DbTableType.TABLE:
case DbTableType.VIEW:
loc6.Add(table.Replace("'", "''"));
break;
case DbTableType.StoreProcedure:
loc66.Add(table.Replace("'", "''"));
break;
}
}
if (loc6.Count == 0) return loc1;
var loc8 = "'" + string.Join("','", loc6.ToArray()) + "'";
var loc88 = "'" + string.Join("','", loc66.ToArray()) + "'";
sql = string.Format(@"
select
a.owner || '.' || a.table_name,
a.column_name,
a.data_type,
a.data_length,
a.data_precision,
a.data_scale,
a.char_used,
case when nullable = 'Y' then 1 else 0 end,
nvl((select 1 from user_sequences where upper(sequence_name)=upper(a.table_name||'_seq_'||a.column_name)), 0),
b.comments
from all_tab_cols a
left join all_col_comments b on b.owner = a.owner and b.table_name = a.table_name and b.column_name = a.column_name
where a.owner in ({1}) and a.table_name in ({0})
", loc8, databaseIn);
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var ds2 = new List<object[]>();
foreach (var row in ds) {
var ds2item = new object[8];
ds2item[0] = row[0];
ds2item[1] = row[1];
ds2item[2] = Regex.Replace(string.Concat(row[2]), @"\(\d+\)", "");
ds2item[4] = OracleCodeFirst.GetOracleSqlTypeFullName(new object[] { row[1], row[2], row[3], row[4], row[5], row[6] });
ds2item[5] = string.Concat(row[7]) == "1";
ds2item[6] = string.Concat(row[8]) == "1";
ds2item[7] = string.Concat(row[9]);
ds2.Add(ds2item);
}
foreach (var row in ds2) {
string table_id = string.Concat(row[0]);
string column = string.Concat(row[1]);
string type = string.Concat(row[2]);
//long max_length = long.Parse(string.Concat(row[3]));
string sqlType = string.Concat(row[4]);
var m_len = Regex.Match(sqlType, @"\w+\((\d+)");
int max_length = m_len.Success ? int.Parse(m_len.Groups[1].Value) : -1;
bool is_nullable = string.Concat(row[5]) == "1";
bool is_identity = string.Concat(row[6]) == "1";
string comment = string.Concat(row[7]);
if (max_length == 0) max_length = -1;
if (database.Length == 1) {
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
}
loc3[table_id].Add(column, new DbColumnInfo {
Name = column,
MaxLength = max_length,
IsIdentity = is_identity,
IsNullable = is_nullable,
IsPrimary = false,
DbTypeText = type,
DbTypeTextFull = sqlType,
Table = loc2[table_id],
Coment = comment
});
loc3[table_id][column].DbType = this.GetDbType(loc3[table_id][column]);
loc3[table_id][column].CsType = this.GetCsTypeInfo(loc3[table_id][column]);
}
sql = string.Format(@"
select
a.owner || '.' || a.table_name,
c.column_name,
c.constraint_name,
case when a.constraint_type = 'U' then 1 else 0 end,
case when a.constraint_type = 'P' then 1 else 0 end,
0,
0
from
all_constraints a,
all_cons_columns c
where
a.constraint_name = c.constraint_name
and a.owner = c.owner
and a.table_name = c.table_name
and a.constraint_type in ('P', 'U')
and a.owner in ({1}) and a.table_name in ({0})
", loc8, databaseIn);
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var indexColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
var uniqueColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
foreach (var row in ds) {
string table_id = string.Concat(row[0]);
string column = string.Concat(row[1]);
string index_id = string.Concat(row[2]);
bool is_unique = string.Concat(row[3]) == "1";
bool is_primary_key = string.Concat(row[4]) == "1";
bool is_clustered = string.Concat(row[5]) == "1";
int is_desc = int.Parse(string.Concat(row[6]));
if (database.Length == 1) {
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
}
if (loc3.ContainsKey(table_id) == false || loc3[table_id].ContainsKey(column) == false) continue;
var loc9 = loc3[table_id][column];
if (loc9.IsPrimary == false && is_primary_key) loc9.IsPrimary = is_primary_key;
Dictionary<string, List<DbColumnInfo>> loc10 = null;
List<DbColumnInfo> loc11 = null;
if (!indexColumns.TryGetValue(table_id, out loc10))
indexColumns.Add(table_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
if (!loc10.TryGetValue(index_id, out loc11))
loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
loc11.Add(loc9);
if (is_unique && !is_primary_key) {
if (!uniqueColumns.TryGetValue(table_id, out loc10))
uniqueColumns.Add(table_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
if (!loc10.TryGetValue(index_id, out loc11))
loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
loc11.Add(loc9);
}
}
foreach (string table_id in indexColumns.Keys) {
foreach (var column in indexColumns[table_id])
loc2[table_id].IndexesDict.Add(column.Key, column.Value);
}
foreach (string table_id in uniqueColumns.Keys) {
foreach (var column in uniqueColumns[table_id]) {
column.Value.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
loc2[table_id].UniquesDict.Add(column.Key, column.Value);
}
}
sql = string.Format(@"
select
a.owner || '.' || a.table_name,
c.column_name,
c.constraint_name,
b.owner || '.' || b.table_name,
1,
d.column_name
-- a.owner 外键拥有者,
-- a.table_name 外键表,
-- c.column_name 外键列,
-- b.owner 主键拥有者,
-- b.table_name 主键表,
-- d.column_name 主键列,
-- c.constraint_name 外键名,
-- d.constraint_name 主键名
from
all_constraints a,
all_constraints b,
all_cons_columns c, --外键表
all_cons_columns d --主键表
where
a.r_constraint_name = b.constraint_name   
and a.constraint_type = 'R'   
and b.constraint_type = 'P'   
and a.r_owner = b.owner   
and a.constraint_name = c.constraint_name   
and b.constraint_name = d.constraint_name   
and a.owner = c.owner   
and a.table_name = c.table_name   
and b.owner = d.owner   
and b.table_name = d.table_name
and a.owner in ({1}) and a.table_name in ({0})
", loc8, databaseIn);
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var fkColumns = new Dictionary<string, Dictionary<string, DbForeignInfo>>();
foreach (var row in ds) {
string table_id = string.Concat(row[0]);
string column = string.Concat(row[1]);
string fk_id = string.Concat(row[2]);
string ref_table_id = string.Concat(row[3]);
bool is_foreign_key = string.Concat(row[4]) == "1";
string referenced_column = string.Concat(row[5]);
if (database.Length == 1) {
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
ref_table_id = ref_table_id.Substring(ref_table_id.IndexOf('.') + 1);
}
if (loc3.ContainsKey(table_id) == false || loc3[table_id].ContainsKey(column) == false) continue;
var loc9 = loc3[table_id][column];
if (loc2.ContainsKey(ref_table_id) == false) continue;
var loc10 = loc2[ref_table_id];
var loc11 = loc3[ref_table_id][referenced_column];
Dictionary<string, DbForeignInfo> loc12 = null;
DbForeignInfo loc13 = null;
if (!fkColumns.TryGetValue(table_id, out loc12))
fkColumns.Add(table_id, loc12 = new Dictionary<string, DbForeignInfo>());
if (!loc12.TryGetValue(fk_id, out loc13))
loc12.Add(fk_id, loc13 = new DbForeignInfo { Table = loc2[table_id], ReferencedTable = loc10 });
loc13.Columns.Add(loc9);
loc13.ReferencedColumns.Add(loc11);
}
foreach (var table_id in fkColumns.Keys)
foreach (var fk in fkColumns[table_id])
loc2[table_id].ForeignsDict.Add(fk.Key, fk.Value);
foreach (var table_id in loc3.Keys) {
foreach (var loc5 in loc3[table_id].Values) {
loc2[table_id].Columns.Add(loc5);
if (loc5.IsIdentity) loc2[table_id].Identitys.Add(loc5);
if (loc5.IsPrimary) loc2[table_id].Primarys.Add(loc5);
}
}
foreach (var loc4 in loc2.Values) {
if (loc4.Primarys.Count == 0 && loc4.UniquesDict.Count > 0) {
foreach (var loc5 in loc4.UniquesDict.First().Value) {
loc5.IsPrimary = true;
loc4.Primarys.Add(loc5);
}
}
loc4.Primarys.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
loc4.Columns.Sort((c1, c2) => {
int compare = c2.IsPrimary.CompareTo(c1.IsPrimary);
if (compare == 0) {
bool b1 = loc4.ForeignsDict.Values.Where(fk => fk.Columns.Where(c3 => c3.Name == c1.Name).Any()).Any();
bool b2 = loc4.ForeignsDict.Values.Where(fk => fk.Columns.Where(c3 => c3.Name == c2.Name).Any()).Any();
compare = b2.CompareTo(b1);
}
if (compare == 0) compare = c1.Name.CompareTo(c2.Name);
return compare;
});
loc1.Add(loc4);
}
loc1.Sort((t1, t2) => {
var ret = t1.Schema.CompareTo(t2.Schema);
if (ret == 0) ret = t1.Name.CompareTo(t2.Name);
return ret;
});
loc2.Clear();
loc3.Clear();
return loc1;
}
public List<DbEnumInfo> GetEnumsByDatabase(params string[] database) {
return new List<DbEnumInfo>();
}
}
}

View File

@ -1,399 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace FreeSql.Oracle {
class OracleExpression : CommonExpression {
public OracleExpression(CommonUtils common) : base(common) { }
internal override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
switch (exp.NodeType) {
case ExpressionType.Convert:
var operandExp = (exp as UnaryExpression)?.Operand;
var gentype = exp.Type.NullableTypeOrThis();
if (gentype != operandExp.Type.NullableTypeOrThis()) {
switch (exp.Type.NullableTypeOrThis().ToString()) {
//case "System.Boolean": return $"({getExp(operandExp)} not in ('0','false'))";
case "System.Byte": return $"cast({getExp(operandExp)} as number)";
case "System.Char": return $"substr(to_char({getExp(operandExp)}), 1, 1)";
case "System.DateTime": return $"to_timestamp({getExp(operandExp)},'YYYY-MM-DD HH24:MI:SS.FF6')";
case "System.Decimal": return $"cast({getExp(operandExp)} as number)";
case "System.Double": return $"cast({getExp(operandExp)} as number)";
case "System.Int16":
case "System.Int32":
case "System.Int64":
case "System.SByte": return $"cast({getExp(operandExp)} as number)";
case "System.Single": return $"cast({getExp(operandExp)} as number)";
case "System.String": return $"to_char({getExp(operandExp)})";
case "System.UInt16":
case "System.UInt32":
case "System.UInt64": return $"cast({getExp(operandExp)} as number)";
case "System.Guid": return $"substr(to_char({getExp(operandExp)}), 1, 36)";
}
}
break;
case ExpressionType.Call:
var callExp = exp as MethodCallExpression;
switch (callExp.Method.Name) {
case "Parse":
case "TryParse":
switch (callExp.Method.DeclaringType.NullableTypeOrThis().ToString()) {
//case "System.Boolean": return $"({getExp(callExp.Arguments[0])} not in ('0','false'))";
case "System.Byte": return $"cast({getExp(callExp.Arguments[0])} as number)";
case "System.Char": return $"substr(to_char({getExp(callExp.Arguments[0])}), 1, 1)";
case "System.DateTime": return $"to_timestamp({getExp(callExp.Arguments[0])},'YYYY-MM-DD HH24:MI:SS.FF6')";
case "System.Decimal": return $"cast({getExp(callExp.Arguments[0])} as number)";
case "System.Double": return $"cast({getExp(callExp.Arguments[0])} as number)";
case "System.Int16":
case "System.Int32":
case "System.Int64":
case "System.SByte": return $"cast({getExp(callExp.Arguments[0])} as number)";
case "System.Single": return $"cast({getExp(callExp.Arguments[0])} as number)";
case "System.UInt16":
case "System.UInt32":
case "System.UInt64": return $"cast({getExp(callExp.Arguments[0])} as number)";
case "System.Guid": return $"substr(to_char({getExp(callExp.Arguments[0])}), 1, 36)";
}
break;
case "NewGuid":
break;
case "Next":
if (callExp.Object?.Type == typeof(Random)) return "cast(dbms_random.value*1000000000 as smallint)";
break;
case "NextDouble":
if (callExp.Object?.Type == typeof(Random)) return "dbms_random.value";
break;
case "Random":
if (callExp.Method.DeclaringType.IsNumberType()) return "dbms_random.value";
break;
case "ToString":
if (callExp.Object != null) return $"to_char({getExp(callExp.Object)})";
break;
}
var objExp = callExp.Object;
var objType = objExp?.Type;
if (objType?.FullName == "System.Byte[]") return null;
var argIndex = 0;
if (objType == null && callExp.Method.DeclaringType == typeof(Enumerable)) {
objExp = callExp.Arguments.FirstOrDefault();
objType = objExp?.Type;
argIndex++;
}
if (objType == null) objType = callExp.Method.DeclaringType;
if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) {
var left = objExp == null ? null : getExp(objExp);
switch (callExp.Method.Name) {
case "Contains":
//判断 in
return $"({getExp(callExp.Arguments[argIndex])}) in {left}";
}
}
break;
case ExpressionType.NewArrayInit:
var arrExp = exp as NewArrayExpression;
var arrSb = new StringBuilder();
arrSb.Append("(");
for (var a = 0; a < arrExp.Expressions.Count; a++) {
if (a > 0) arrSb.Append(",");
arrSb.Append(getExp(arrExp.Expressions[a]));
}
if (arrSb.Length == 1) arrSb.Append("NULL");
return arrSb.Append(")").ToString();
case ExpressionType.ListInit:
var listExp = exp as ListInitExpression;
var listSb = new StringBuilder();
listSb.Append("(");
for (var a = 0; a < listExp.Initializers.Count; a++) {
if (listExp.Initializers[a].Arguments.Any() == false) continue;
if (a > 0) listSb.Append(",");
listSb.Append(getExp(listExp.Initializers[a].Arguments.FirstOrDefault()));
}
if (listSb.Length == 1) listSb.Append("NULL");
return listSb.Append(")").ToString();
case ExpressionType.New:
var newExp = exp as NewExpression;
if (typeof(IList).IsAssignableFrom(newExp.Type)) {
if (newExp.Arguments.Count == 0) return "(NULL)";
if (typeof(IEnumerable).IsAssignableFrom(newExp.Arguments[0].Type) == false) return "(NULL)";
return getExp(newExp.Arguments[0]);
}
return null;
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Empty": return "''";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Length": return $"length({left})";
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Now": return "systimestamp";
case "UtcNow": return "sys_extract_utc(systimestamp)";
case "Today": return "trunc(systimestamp)";
case "MinValue": return "to_timestamp('0001-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS.FF6')";
case "MaxValue": return "to_timestamp('9999-12-31 23:59:59','YYYY-MM-DD HH24:MI:SS.FF6')";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Date": return $"trunc({left})";
case "TimeOfDay": return $"({left}-trunc({left}))";
case "DayOfWeek": return $"case when to_char({left})='7' then 0 else cast(to_char({left}) as number) end";
case "Day": return $"cast(to_char({left},'DD') as number)";
case "DayOfYear": return $"cast(to_char({left},'DDD') as number)";
case "Month": return $"cast(to_char({left},'MM') as number)";
case "Year": return $"cast(to_char({left},'YYYY') as number)";
case "Hour": return $"cast(to_char({left},'HH24') as number)";
case "Minute": return $"cast(to_char({left},'MI') as number)";
case "Second": return $"cast(to_char({left},'SS') as number)";
case "Millisecond": return $"cast(to_char({left},'FF3') as number)";
case "Ticks": return $"cast(to_char({left},'FF7') as number)";
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Zero": return "numtodsinterval(0,'second')";
case "MinValue": return "numtodsinterval(-233720368.5477580,'second')";
case "MaxValue": return "numtodsinterval(233720368.5477580,'second')";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Days": return $"extract(day from {left})";
case "Hours": return $"extract(hour from {left})";
case "Milliseconds": return $"cast(substr(extract(second from {left})-floor(extract(second from {left})),2,3) as number)";
case "Minutes": return $"extract(minute from {left})";
case "Seconds": return $"floor(extract(second from {left}))";
case "Ticks": return $"(extract(day from {left})*86400+extract(hour from {left})*3600+extract(minute from {left})*60+extract(second from {left}))*10000000";
case "TotalDays": return $"extract(day from {left})";
case "TotalHours": return $"(extract(day from {left})*24+extract(hour from {left}))";
case "TotalMilliseconds": return $"(extract(day from {left})*86400+extract(hour from {left})*3600+extract(minute from {left})*60+extract(second from {left}))*1000";
case "TotalMinutes": return $"(extract(day from {left})*1440+extract(hour from {left})*60+extract(minute from {left}))";
case "TotalSeconds": return $"(extract(day from {left})*86400+extract(hour from {left})*3600+extract(minute from {left})*60+extract(second from {left}))";
}
return null;
}
internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "IsNullOrEmpty":
var arg1 = getExp(exp.Arguments[0]);
return $"({arg1} is null or {arg1} = '')";
case "Concat":
return _common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), null);
}
} else {
var left = getExp(exp.Object);
switch (exp.Method.Name) {
case "StartsWith":
case "EndsWith":
case "Contains":
var args0Value = getExp(exp.Arguments[0]);
if (args0Value == "NULL") return $"({left}) IS NULL";
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(to_char({args0Value})||'%')")}";
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%'||to_char({args0Value}))")}";
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
return $"({left}) LIKE ('%'||to_char({args0Value})||'%')";
case "ToLower": return $"lower({left})";
case "ToUpper": return $"upper({left})";
case "Substring":
var substrArgs1 = getExp(exp.Arguments[0]);
if (long.TryParse(substrArgs1, out var testtrylng1)) substrArgs1 = (testtrylng1 + 1).ToString();
else substrArgs1 += "+1";
if (exp.Arguments.Count == 1) return $"substr({left}, {substrArgs1})";
return $"substr({left}, {substrArgs1}, {getExp(exp.Arguments[1])})";
case "IndexOf":
var indexOfFindStr = getExp(exp.Arguments[0]);
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") {
var locateArgs1 = getExp(exp.Arguments[1]);
if (long.TryParse(locateArgs1, out var testtrylng2)) locateArgs1 = (testtrylng2 + 1).ToString();
else locateArgs1 += "+1";
return $"(instr({left}, {indexOfFindStr}, {locateArgs1}, 1)-1)";
}
return $"(instr({left}, {indexOfFindStr}, 1, 1))-1";
case "PadLeft":
if (exp.Arguments.Count == 1) return $"lpad({left}, {getExp(exp.Arguments[0])}, ' ')";
return $"lpad({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "PadRight":
if (exp.Arguments.Count == 1) return $"rpad({left}, {getExp(exp.Arguments[0])}, ' ')";
return $"rpad({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "Trim":
case "TrimStart":
case "TrimEnd":
if (exp.Arguments.Count == 0) {
if (exp.Method.Name == "Trim") return $"trim({left})";
if (exp.Method.Name == "TrimStart") return $"ltrim({left})";
if (exp.Method.Name == "TrimEnd") return $"rtrim({left})";
}
foreach (var argsTrim02 in exp.Arguments) {
var argsTrim01s = new[] { argsTrim02 };
if (argsTrim02.NodeType == ExpressionType.NewArrayInit) {
var arritem = argsTrim02 as NewArrayExpression;
argsTrim01s = arritem.Expressions.ToArray();
}
foreach (var argsTrim01 in argsTrim01s) {
if (exp.Method.Name == "Trim") left = $"trim(both {getExp(argsTrim01)} from {left})";
if (exp.Method.Name == "TrimStart") left = $"ltrim({left},{getExp(argsTrim01)})";
if (exp.Method.Name == "TrimEnd") left = $"rtrim({left},{getExp(argsTrim01)})";
}
}
return left;
case "Replace": return $"replace({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "CompareTo": return $"case when {left} = {getExp(exp.Arguments[0])} then 0 when {left} > {getExp(exp.Arguments[0])} then 1 else -1 end";
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
}
}
throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
switch (exp.Method.Name) {
case "Abs": return $"abs({getExp(exp.Arguments[0])})";
case "Sign": return $"sign({getExp(exp.Arguments[0])})";
case "Floor": return $"floor({getExp(exp.Arguments[0])})";
case "Ceiling": return $"ceil({getExp(exp.Arguments[0])})";
case "Round":
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"round({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
return $"round({getExp(exp.Arguments[0])})";
case "Exp": return $"exp({getExp(exp.Arguments[0])})";
case "Log": if (exp.Arguments.Count > 1) return $"log({getExp(exp.Arguments[1])},{getExp(exp.Arguments[0])})";
return $"log(2.7182818284590451,{getExp(exp.Arguments[0])})";
case "Log10": return $"log(10,{getExp(exp.Arguments[0])})";
case "Pow": return $"power({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "Sqrt": return $"sqrt({getExp(exp.Arguments[0])})";
case "Cos": return $"cos({getExp(exp.Arguments[0])})";
case "Sin": return $"sin({getExp(exp.Arguments[0])})";
case "Tan": return $"tan({getExp(exp.Arguments[0])})";
case "Acos": return $"acos({getExp(exp.Arguments[0])})";
case "Asin": return $"asin({getExp(exp.Arguments[0])})";
case "Atan": return $"atan({getExp(exp.Arguments[0])})";
//case "Atan2": return $"atan2({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "Truncate": return $"trunc({getExp(exp.Arguments[0])}, 0)";
}
throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "Compare": return $"extract(day from ({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])})))";
case "DaysInMonth": return $"cast(to_char(last_day(({getExp(exp.Arguments[0])})||'-'||({getExp(exp.Arguments[1])})||'-01'),'DD') as number)";
case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})";
case "IsLeapYear":
var isLeapYearArgs1 = getExp(exp.Arguments[0]);
return $"(mod({isLeapYearArgs1},4)=0 AND mod({isLeapYearArgs1},100)<>0 OR mod({isLeapYearArgs1},400)=0)";
case "Parse": return $"to_timestamp({getExp(exp.Arguments[0])},'YYYY-MM-DD HH24:MI:SS.FF6')";
case "ParseExact":
case "TryParse":
case "TryParseExact": return $"to_timestamp({getExp(exp.Arguments[0])},'YYYY-MM-DD HH24:MI:SS.FF6')";
}
} else {
var left = getExp(exp.Object);
var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]);
switch (exp.Method.Name) {
case "Add": return $"({left}+{args1})";
case "AddDays": return $"({left}+{args1})";
case "AddHours": return $"({left}+({args1})/24)";
case "AddMilliseconds": return $"({left}+({args1})/86400000)";
case "AddMinutes": return $"({left}+({args1})/1440)";
case "AddMonths": return $"add_months({left},{args1})";
case "AddSeconds": return $"({left}+({args1})/86400)";
case "AddTicks": return $"({left}+({args1})/864000000000)";
case "AddYears": return $"add_months({left},({args1})*12)";
case "Subtract":
switch ((exp.Arguments[0].Type.IsNullableType() ? exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault() : exp.Arguments[0].Type).FullName) {
case "System.DateTime": return $"({args1}-{left})";
case "System.TimeSpan": return $"({left}-{args1})";
}
break;
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
case "CompareTo": return $"extract(day from ({left}-({getExp(exp.Arguments[0])})))";
case "ToString": return $"to_char({left},'YYYY-MM-DD HH24:MI:SS.FF6')";
}
}
throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "Compare": return $"extract(day from ({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])})))";
case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})";
case "FromDays": return $"numtodsinterval(({getExp(exp.Arguments[0])})*{(long)60 * 60 * 24},'second')";
case "FromHours": return $"numtodsinterval(({getExp(exp.Arguments[0])})*{(long)60 * 60},'second')";
case "FromMilliseconds": return $"numtodsinterval(({getExp(exp.Arguments[0])})/1000,'second')";
case "FromMinutes": return $"numtodsinterval(({getExp(exp.Arguments[0])})*60,'second')";
case "FromSeconds": return $"numtodsinterval(({getExp(exp.Arguments[0])}),'second')";
case "FromTicks": return $"numtodsinterval(({getExp(exp.Arguments[0])})/10000000,'second')";
case "Parse": return $"cast({getExp(exp.Arguments[0])} as interval day(9) to second(7))";
case "ParseExact":
case "TryParse":
case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as interval day(9) to second(7))";
}
} else {
var left = getExp(exp.Object);
var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]);
switch (exp.Method.Name) {
case "Add": return $"({left}+{args1})";
case "Subtract": return $"({left}-({args1}))";
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
case "CompareTo": return $"extract(day from ({left}-({getExp(exp.Arguments[0])})))";
case "ToString": return $"to_char({left})";
}
}
throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
//case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))";
case "ToByte": return $"cast({getExp(exp.Arguments[0])} as number)";
case "ToChar": return $"substr(to_char({getExp(exp.Arguments[0])}), 1, 1)";
case "ToDateTime": return $"to_timestamp({getExp(exp.Arguments[0])},'YYYY-MM-DD HH24:MI:SS.FF6')";
case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as number)";
case "ToDouble": return $"cast({getExp(exp.Arguments[0])} as number)";
case "ToInt16":
case "ToInt32":
case "ToInt64":
case "ToSByte": return $"cast({getExp(exp.Arguments[0])} as number)";
case "ToSingle": return $"cast({getExp(exp.Arguments[0])} as number)";
case "ToString": return $"to_char({getExp(exp.Arguments[0])})";
case "ToUInt16":
case "ToUInt32":
case "ToUInt64": return $"cast({getExp(exp.Arguments[0])} as number)";
}
}
throw new Exception($"OracleExpression 未实现函数表达式 {exp} 解析");
}
}
}

View File

@ -1,11 +0,0 @@
public static partial class FreeSqlGlobalExtensions {
/// <summary>
/// 特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换
/// </summary>
/// <param name="that"></param>
/// <param name="args"></param>
/// <returns></returns>
public static string FormatOracleSQL(this string that, params object[] args) => _oracleAdo.Addslashes(that, args);
static FreeSql.Oracle.OracleAdo _oracleAdo = new FreeSql.Oracle.OracleAdo();
}

View File

@ -1,62 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.CommonProvider;
using FreeSql.Oracle.Curd;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Data.Common;
namespace FreeSql.Oracle {
class OracleProvider<TMark> : IFreeSql<TMark> {
public ISelect<T1> Select<T1>() where T1 : class => new OracleSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public ISelect<T1> Select<T1>(object dywhere) where T1 : class => new OracleSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsert<T1> Insert<T1>() where T1 : class => new OracleInsert<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IInsert<T1> Insert<T1>(T1 source) where T1 : class => this.Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(T1[] source) where T1 : class => this.Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(IEnumerable<T1> source) where T1 : class => this.Insert<T1>().AppendData(source);
public IUpdate<T1> Update<T1>() where T1 : class => new OracleUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new OracleUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new OracleDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new OracleDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IAdo Ado { get; }
public IAop Aop { get; }
public ICache Cache { get; }
public ICodeFirst CodeFirst { get; }
public IDbFirst DbFirst { get; }
public OracleProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) {
if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.Oracle");
this.InternalCommonUtils = new OracleUtils(this);
this.InternalCommonExpression = new OracleExpression(this.InternalCommonUtils);
this.Cache = new CacheProvider(cache, log);
this.Ado = new OracleAdo(this.InternalCommonUtils, this.Cache, log, masterConnectionString, slaveConnectionString);
this.Aop = new AopProvider();
this.DbFirst = new OracleDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
this.CodeFirst = new OracleCodeFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
}
internal CommonUtils InternalCommonUtils { get; }
internal CommonExpression InternalCommonExpression { get; }
public void Transaction(Action handler) => Ado.Transaction(handler);
public void Transaction(Action handler, TimeSpan timeout) => Ado.Transaction(handler, timeout);
~OracleProvider() {
this.Dispose();
}
bool _isdisposed = false;
public void Dispose() {
if (_isdisposed) return;
(this.Ado as AdoProvider).Dispose();
(this.Cache as CacheProvider)?.Dispose();
}
}
}

View File

@ -1,75 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using Oracle.ManagedDataAccess.Client;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Text;
namespace FreeSql.Oracle {
class OracleUtils : CommonUtils {
public OracleUtils(IFreeSql orm) : base(orm) {
}
internal override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value) {
if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}";
var dbtype = (OracleDbType)_orm.CodeFirst.GetDbInfo(type)?.type;
if (dbtype == OracleDbType.Boolean) {
if (value == null) value = null;
else value = (bool)value == true ? 1 : 0;
dbtype = OracleDbType.Int16;
}
var ret = new OracleParameter { ParameterName = QuoteParamterName(parameterName), OracleDbType = dbtype, Value = value };
_params?.Add(ret);
return ret;
}
internal override DbParameter[] GetDbParamtersByObject(string sql, object obj) =>
Utils.GetDbParamtersByObject<OracleParameter>(sql, obj, ":", (name, type, value) => {
var dbtype = (OracleDbType)_orm.CodeFirst.GetDbInfo(type)?.type;
if (dbtype == OracleDbType.Boolean) {
if (value == null) value = null;
else value = (bool)value == true ? 1 : 0;
dbtype = OracleDbType.Int16;
}
var ret = new OracleParameter { ParameterName = $":{name}", OracleDbType = dbtype, Value = value };
return ret;
});
internal override string FormatSql(string sql, params object[] args) => sql?.FormatOracleSQL(args);
internal override string QuoteSqlName(string name) {
var nametrim = name.Trim();
if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
return nametrim; //原生SQL
return $"\"{nametrim.Trim('"').Replace(".", "\".\"")}\"";
}
internal override string TrimQuoteSqlName(string name) {
var nametrim = name.Trim();
if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
return nametrim; //原生SQL
return $"{nametrim.Trim('"').Replace("\".\"", ".").Replace(".\"", ".")}";
}
internal override string QuoteParamterName(string name) => $":{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
internal override string IsNull(string sql, object value) => $"nvl({sql}, {value})";
internal override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}";
internal override string Mod(string left, string right, Type leftType, Type rightType) => $"mod({left}, {right})";
internal override string QuoteWriteParamter(Type type, string paramterName) => paramterName;
internal override string QuoteReadColumn(Type type, string columnName) => columnName;
internal override string GetNoneParamaterSqlValue(List<DbParameter> specialParams, Type type, object value) {
if (value == null) return "NULL";
if (type == typeof(byte[])) {
var bytes = value as byte[];
var sb = new StringBuilder().Append("rawtohex('0x");
foreach (var vc in bytes) {
if (vc < 10) sb.Append("0");
sb.Append(vc.ToString("X"));
}
return sb.Append("')").ToString();
}
return FormatSql("{0}", value, 1);
}
}
}

View File

@ -1,78 +0,0 @@
using FreeSql.Internal;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.PostgreSQL.Curd {
class PostgreSQLDelete<T1> : Internal.CommonProvider.DeleteProvider<T1> where T1 : class {
public PostgreSQLDelete(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
: base(orm, commonUtils, commonExpression, dywhere) {
}
public override List<T1> ExecuteDeleted() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(sql).Append(" RETURNING ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
sql = sb.ToString();
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Delete, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
async public override Task<List<T1>> ExecuteDeletedAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(sql).Append(" RETURNING ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
sql = sb.ToString();
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Delete, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
}
}

View File

@ -1,164 +0,0 @@
using FreeSql.Internal;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.PostgreSQL.Curd {
class PostgreSQLInsert<T1> : Internal.CommonProvider.InsertProvider<T1> where T1 : class {
public PostgreSQLInsert(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression) {
}
public override int ExecuteAffrows() => base.SplitExecuteAffrows(5000, 3000);
public override Task<int> ExecuteAffrowsAsync() => base.SplitExecuteAffrowsAsync(5000, 3000);
public override long ExecuteIdentity() => base.SplitExecuteIdentity(5000, 3000);
public override Task<long> ExecuteIdentityAsync() => base.SplitExecuteIdentityAsync(5000, 3000);
public override List<T1> ExecuteInserted() => base.SplitExecuteInserted(5000, 3000);
public override Task<List<T1>> ExecuteInsertedAsync() => base.SplitExecuteInsertedAsync(5000, 3000);
internal override long RawExecuteIdentity() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
long ret = 0;
Exception exception = null;
Aop.CurdBeforeEventArgs before = null;
var identCols = _table.Columns.Where(a => a.Value.Attribute.IsIdentity == true);
if (identCols.Any() == false) {
before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
try {
ret = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _params);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return 0;
}
sql = string.Concat(sql, " RETURNING ", _commonUtils.QuoteSqlName(identCols.First().Value.Attribute.Name));
before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
try {
long.TryParse(string.Concat(_orm.Ado.ExecuteScalar(_connection, _transaction, CommandType.Text, sql, _params)), out ret);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
async internal override Task<long> RawExecuteIdentityAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
long ret = 0;
Exception exception = null;
Aop.CurdBeforeEventArgs before = null;
var identCols = _table.Columns.Where(a => a.Value.Attribute.IsIdentity == true);
if (identCols.Any() == false) {
before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
try {
ret = await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, _params);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return 0;
}
sql = string.Concat(sql, " RETURNING ", _commonUtils.QuoteSqlName(identCols.First().Value.Attribute.Name));
before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
try {
long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync(_connection, _transaction, CommandType.Text, sql, _params)), out ret);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
internal override List<T1> RawExecuteInserted() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(sql).Append(" RETURNING ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
sql = sb.ToString();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sql, _params);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
async internal override Task<List<T1>> RawExecuteInsertedAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(sql).Append(" RETURNING ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
sql = sb.ToString();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sql, _params);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
}
}

View File

@ -1,130 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace FreeSql.PostgreSQL.Curd {
class PostgreSQLSelect<T1> : FreeSql.Internal.CommonProvider.Select1Provider<T1> where T1 : class {
internal static string ToSqlStatic(CommonUtils _commonUtils, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables, Func<Type, string, string> tableRuleInvoke, IFreeSql _orm) {
if (_orm.CodeFirst.IsAutoSyncStructure)
_orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray());
var sb = new StringBuilder();
var sbnav = new StringBuilder();
sb.Append(_select);
if (_distinct) sb.Append("DISTINCT ");
sb.Append(field).Append(" \r\nFROM ");
var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray();
var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray();
for (var a = 0; a < tbsfrom.Length; a++) {
sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[a].Table.Type, tbsfrom[a].Table.DbName))).Append(" ").Append(tbsfrom[a].Alias);
if (tbsjoin.Length > 0) {
//如果存在 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(tableRuleInvoke(tbsfrom[b].Table.Type, tbsfrom[b].Table.DbName))).Append(" ").Append(tbsfrom[b].Alias);
if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On)) sb.Append(" ON 1 = 1");
else sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On);
}
break;
} else {
if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")");
if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")");
}
if (a < tbsfrom.Length - 1) sb.Append(", ");
}
foreach (var tb in tbsjoin) {
if (tb.Type == SelectTableInfoType.Parent) continue;
switch (tb.Type) {
case SelectTableInfoType.LeftJoin:
sb.Append(" \r\nLEFT JOIN ");
break;
case SelectTableInfoType.InnerJoin:
sb.Append(" \r\nINNER JOIN ");
break;
case SelectTableInfoType.RightJoin:
sb.Append(" \r\nRIGHT JOIN ");
break;
}
sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tb.Table.Type, tb.Table.DbName))).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition);
if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")");
}
if (_join.Length > 0) sb.Append(_join);
sbnav.Append(_where);
foreach (var tb in _tables) {
if (tb.Type == SelectTableInfoType.Parent) continue;
if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false)
sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")");
}
if (sbnav.Length > 0) {
sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5));
}
if (string.IsNullOrEmpty(_groupby) == false) {
sb.Append(_groupby);
if (string.IsNullOrEmpty(_having) == false)
sb.Append(" \r\nHAVING ").Append(_having.Substring(5));
}
sb.Append(_orderby);
if (_limit > 0)
sb.Append(" \r\nlimit ").Append(_limit);
if (_skip > 0)
sb.Append(" \r\noffset ").Append(_skip);
sbnav.Clear();
return sb.ToString();
}
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override ISelect<T1, T2> From<T2>(Expression<Func<ISelectFromExpression<T1>, T2, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new PostgreSQLSelect<T1, T2>(_orm, _commonUtils, _commonExpression, null); PostgreSQLSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3> From<T2, T3>(Expression<Func<ISelectFromExpression<T1>, T2, T3, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new PostgreSQLSelect<T1, T2, T3>(_orm, _commonUtils, _commonExpression, null); PostgreSQLSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4> From<T2, T3, T4>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new PostgreSQLSelect<T1, T2, T3, T4>(_orm, _commonUtils, _commonExpression, null); PostgreSQLSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5> From<T2, T3, T4, T5>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new PostgreSQLSelect<T1, T2, T3, T4, T5>(_orm, _commonUtils, _commonExpression, null); PostgreSQLSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6> From<T2, T3, T4, T5, T6>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new PostgreSQLSelect<T1, T2, T3, T4, T5, T6>(_orm, _commonUtils, _commonExpression, null); PostgreSQLSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7> From<T2, T3, T4, T5, T6, T7>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7>(_orm, _commonUtils, _commonExpression, null); PostgreSQLSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8> From<T2, T3, T4, T5, T6, T7, T8>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7, T8>(_orm, _commonUtils, _commonExpression, null); PostgreSQLSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> From<T2, T3, T4, T5, T6, T7, T8, T9>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>(_orm, _commonUtils, _commonExpression, null); PostgreSQLSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); PostgreSQLSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class PostgreSQLSelect<T1, T2> : FreeSql.Internal.CommonProvider.Select2Provider<T1, T2> where T1 : class where T2 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class PostgreSQLSelect<T1, T2, T3> : FreeSql.Internal.CommonProvider.Select3Provider<T1, T2, T3> where T1 : class where T2 : class where T3 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class PostgreSQLSelect<T1, T2, T3, T4> : FreeSql.Internal.CommonProvider.Select4Provider<T1, T2, T3, T4> where T1 : class where T2 : class where T3 : class where T4 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class PostgreSQLSelect<T1, T2, T3, T4, T5> : FreeSql.Internal.CommonProvider.Select5Provider<T1, T2, T3, T4, T5> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class PostgreSQLSelect<T1, T2, T3, T4, T5, T6> : FreeSql.Internal.CommonProvider.Select6Provider<T1, T2, T3, T4, T5, T6> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7> : FreeSql.Internal.CommonProvider.Select7Provider<T1, T2, T3, T4, T5, T6, T7> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7, T8> : FreeSql.Internal.CommonProvider.Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> : FreeSql.Internal.CommonProvider.Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class PostgreSQLSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : FreeSql.Internal.CommonProvider.Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class {
public PostgreSQLSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => PostgreSQLSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
}

View File

@ -1,119 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.PostgreSQL.Curd {
class PostgreSQLUpdate<T1> : Internal.CommonProvider.UpdateProvider<T1> where T1 : class {
public PostgreSQLUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
: base(orm, commonUtils, commonExpression, dywhere) {
}
public override int ExecuteAffrows() => base.SplitExecuteAffrows(500, 3000);
public override Task<int> ExecuteAffrowsAsync() => base.SplitExecuteAffrowsAsync(500, 3000);
public override List<T1> ExecuteUpdated() => base.SplitExecuteUpdated(500, 3000);
public override Task<List<T1>> ExecuteUpdatedAsync() => base.SplitExecuteUpdatedAsync(500, 3000);
internal override List<T1> RawExecuteUpdated() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(sql).Append(" RETURNING ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
sql = sb.ToString();
var dbParms = _params.Concat(_paramsSource).ToArray();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Update, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sql, dbParms);
ValidateVersionAndThrow(ret.Count);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
async internal override Task<List<T1>> RawExecuteUpdatedAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(sql).Append(" RETURNING ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
sql = sb.ToString();
var dbParms = _params.Concat(_paramsSource).ToArray();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Update, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sql, dbParms);
ValidateVersionAndThrow(ret.Count);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
if (_table.Primarys.Length == 1) {
caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().Attribute.MapType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
return;
}
caseWhen.Append("(");
var pkidx = 0;
foreach (var pk in _table.Primarys) {
if (pkidx > 0) caseWhen.Append(" || ");
caseWhen.Append(_commonUtils.QuoteReadColumn(pk.Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name))).Append("::varchar");
++pkidx;
}
caseWhen.Append(")");
}
protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
if (_table.Primarys.Length == 1) {
sb.Append(_commonUtils.FormatSql("{0}", _table.Primarys.First().GetMapValue(d)));
return;
}
sb.Append("(");
var pkidx = 0;
foreach (var pk in _table.Primarys) {
if (pkidx > 0) sb.Append(" || ");
sb.Append(_commonUtils.FormatSql("{0}", pk.GetMapValue(d))).Append("::varchar");
++pkidx;
}
sb.Append(")");
}
}
}

View File

@ -1,78 +0,0 @@
using FreeSql.Internal;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using Npgsql;
using SafeObjectPool;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.Text;
using System.Threading;
namespace FreeSql.PostgreSQL {
class PostgreSQLAdo : FreeSql.Internal.CommonProvider.AdoProvider {
public PostgreSQLAdo() : base(null, null, DataType.PostgreSQL) { }
public PostgreSQLAdo(CommonUtils util, ICache cache, ILogger log, string masterConnectionString, string[] slaveConnectionStrings) : base(cache, log, DataType.PostgreSQL) {
base._util = util;
if (!string.IsNullOrEmpty(masterConnectionString))
MasterPool = new PostgreSQLConnectionPool("主库", masterConnectionString, null, null);
if (slaveConnectionStrings != null) {
foreach (var slaveConnectionString in slaveConnectionStrings) {
var slavePool = new PostgreSQLConnectionPool($"从库{SlavePools.Count + 1}", slaveConnectionString, () => Interlocked.Decrement(ref slaveUnavailables), () => Interlocked.Increment(ref slaveUnavailables));
SlavePools.Add(slavePool);
}
}
}
static DateTime dt1970 = new DateTime(1970, 1, 1);
public override object AddslashesProcessParam(object param, Type mapType) {
if (param == null) return "NULL";
if (mapType != null && mapType != param.GetType())
param = Utils.GetDataReaderValue(mapType, param);
bool isdic = false;
if (param is bool || param is bool?)
return (bool)param ? "'t'" : "'f'";
else if (param is string || param is char)
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
else if (param is Enum)
return ((Enum)param).ToInt64();
else if (decimal.TryParse(string.Concat(param), out var trydec))
return param;
else if (param is DateTime || param is DateTime?)
return string.Concat("'", ((DateTime)param).ToString("yyyy-MM-dd HH:mm:ss.ffffff"), "'");
else if (param is TimeSpan || param is TimeSpan?)
return ((TimeSpan)param).Ticks / 10;
else if (param is JToken || param is JObject || param is JArray)
return string.Concat("'", param.ToString().Replace("'", "''"), "'::jsonb");
else if ((isdic = param is Dictionary<string, string>) ||
param is IEnumerable<KeyValuePair<string, string>>) {
var pgdics = isdic ? param as Dictionary<string, string> :
param as IEnumerable<KeyValuePair<string, string>>;
if (pgdics == null) return string.Concat("''::hstore");
var pghstore = new StringBuilder();
pghstore.Append("'");
foreach (var dic in pgdics)
pghstore.Append("\"").Append(dic.Key.Replace("'", "''")).Append("\"=>")
.Append(dic.Key.Replace("'", "''")).Append(",");
return pghstore.Append("'::hstore");
} else if (param is IEnumerable) {
var sb = new StringBuilder();
var ie = param as IEnumerable;
foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType));
return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
}
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
}
protected override DbCommand CreateCommand() {
return new NpgsqlCommand();
}
protected override void ReturnConnection(ObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex) {
(pool as PostgreSQLConnectionPool).Return(conn, ex);
}
protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj);
}
}

View File

@ -1,186 +0,0 @@
using Npgsql;
using SafeObjectPool;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace FreeSql.PostgreSQL {
class PostgreSQLConnectionPool : ObjectPool<DbConnection> {
internal Action availableHandler;
internal Action unavailableHandler;
public PostgreSQLConnectionPool(string name, string connectionString, Action availableHandler, Action unavailableHandler) : base(null) {
var policy = new PostgreSQLConnectionPoolPolicy {
_pool = this,
Name = name
};
this.Policy = policy;
policy.ConnectionString = connectionString;
this.availableHandler = availableHandler;
this.unavailableHandler = unavailableHandler;
}
public void Return(Object<DbConnection> obj, Exception exception, bool isRecreate = false) {
if (exception != null && exception is NpgsqlException) {
if (exception is System.IO.IOException) {
base.SetUnavailable(exception);
} else if (obj.Value.Ping() == false) {
base.SetUnavailable(exception);
}
}
base.Return(obj, isRecreate);
}
}
class PostgreSQLConnectionPoolPolicy : IPolicy<DbConnection> {
internal PostgreSQLConnectionPool _pool;
public string Name { get; set; } = "PostgreSQL NpgsqlConnection 对象池";
public int PoolSize { get; set; } = 50;
public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
public TimeSpan IdleTimeout { get; set; } = TimeSpan.Zero;
public int AsyncGetCapacity { get; set; } = 10000;
public bool IsThrowGetTimeoutException { get; set; } = true;
public int CheckAvailableInterval { get; set; } = 5;
static ConcurrentDictionary<string, int> dicConnStrIncr = new ConcurrentDictionary<string, int>(StringComparer.CurrentCultureIgnoreCase);
private string _connectionString;
public string ConnectionString {
get => _connectionString;
set {
_connectionString = value ?? "";
var pattern = @"Max(imum)?\s*pool\s*size\s*=\s*(\d+)";
Match m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success == false || int.TryParse(m.Groups[2].Value, out var poolsize) == false || poolsize <= 0) poolsize = 50;
var connStrIncr = dicConnStrIncr.AddOrUpdate(_connectionString, 1, (oldkey, oldval) => oldval + 1);
PoolSize = poolsize + connStrIncr;
_connectionString = m.Success ?
Regex.Replace(_connectionString, pattern, $"Maximum pool size={PoolSize}", RegexOptions.IgnoreCase) :
$"{_connectionString};Maximum pool size={PoolSize}";
pattern = @"Connection\s*LifeTime\s*=\s*(\d+)";
m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success) {
IdleTimeout = TimeSpan.FromSeconds(int.Parse(m.Groups[1].Value));
_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase);
}
var minPoolSize = 0;
pattern = @"Min(imum)?\s*pool\s*size\s*=\s*(\d+)";
m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success) {
minPoolSize = int.Parse(m.Groups[2].Value);
_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase);
}
FreeUtil.PrevReheatConnectionPool(_pool, minPoolSize);
}
}
public bool OnCheckAvailable(Object<DbConnection> obj) {
if (obj.Value.State == ConnectionState.Closed) obj.Value.Open();
return obj.Value.Ping(true);
}
public DbConnection OnCreate() {
var conn = new NpgsqlConnection(_connectionString);
return conn;
}
public void OnDestroy(DbConnection obj) {
if (obj.State != ConnectionState.Closed) obj.Close();
obj.Dispose();
}
public void OnGet(Object<DbConnection> obj) {
if (_pool.IsAvailable) {
if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && obj.Value.Ping() == false) {
try {
obj.Value.Open();
} catch (Exception ex) {
if (_pool.SetUnavailable(ex) == true)
throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}");
}
}
}
}
async public Task OnGetAsync(Object<DbConnection> obj) {
if (_pool.IsAvailable) {
if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && (await obj.Value.PingAsync()) == false) {
try {
await obj.Value.OpenAsync();
} catch (Exception ex) {
if (_pool.SetUnavailable(ex) == true)
throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}");
}
}
}
}
public void OnGetTimeout() {
}
public void OnReturn(Object<DbConnection> obj) {
}
public void OnAvailable() {
_pool.availableHandler?.Invoke();
}
public void OnUnavailable() {
_pool.unavailableHandler?.Invoke();
}
}
static class DbConnectionExtensions {
static DbCommand PingCommand(DbConnection conn) {
var cmd = conn.CreateCommand();
cmd.CommandTimeout = 5;
cmd.CommandText = "select 1";
return cmd;
}
public static bool Ping(this DbConnection that, bool isThrow = false) {
try {
PingCommand(that).ExecuteNonQuery();
return true;
} catch {
if (that.State != ConnectionState.Closed) try { that.Close(); } catch { }
if (isThrow) throw;
return false;
}
}
async public static Task<bool> PingAsync(this DbConnection that, bool isThrow = false) {
try {
await PingCommand(that).ExecuteNonQueryAsync();
return true;
} catch {
if (that.State != ConnectionState.Closed) try { that.Close(); } catch { }
if (isThrow) throw;
return false;
}
}
}
}

View File

@ -1,140 +0,0 @@
using Newtonsoft.Json.Linq;
using Npgsql;
using NpgsqlTypes;
using System;
using System.Collections;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
namespace Newtonsoft.Json {
public class PostgreSQLTypesConverter : JsonConverter {
private static readonly Type typeof_BitArray = typeof(BitArray);
private static readonly Type typeof_NpgsqlPoint = typeof(NpgsqlPoint);
private static readonly Type typeof_NpgsqlLine = typeof(NpgsqlLine);
private static readonly Type typeof_NpgsqlLSeg = typeof(NpgsqlLSeg);
private static readonly Type typeof_NpgsqlBox = typeof(NpgsqlBox);
private static readonly Type typeof_NpgsqlPath = typeof(NpgsqlPath);
private static readonly Type typeof_NpgsqlPolygon = typeof(NpgsqlPolygon);
private static readonly Type typeof_NpgsqlCircle = typeof(NpgsqlCircle);
private static readonly Type typeof_Cidr = typeof((IPAddress, int));
private static readonly Type typeof_IPAddress = typeof(IPAddress);
private static readonly Type typeof_PhysicalAddress = typeof(PhysicalAddress);
private static readonly Type typeof_String = typeof(string);
private static readonly Type typeof_NpgsqlRange_int = typeof(NpgsqlRange<int>);
private static readonly Type typeof_NpgsqlRange_long = typeof(NpgsqlRange<long>);
private static readonly Type typeof_NpgsqlRange_decimal = typeof(NpgsqlRange<decimal>);
private static readonly Type typeof_NpgsqlRange_DateTime = typeof(NpgsqlRange<DateTime>);
public override bool CanConvert(Type objectType) {
Type ctype = objectType.IsArray ? objectType.GetElementType() : objectType;
var ctypeGenericType1 = ctype.GenericTypeArguments.FirstOrDefault();
if (ctype == typeof_BitArray) return true;
if (ctype == typeof_NpgsqlPoint || ctypeGenericType1 == typeof_NpgsqlPoint) return true;
if (ctype == typeof_NpgsqlLine || ctypeGenericType1 == typeof_NpgsqlLine) return true;
if (ctype == typeof_NpgsqlLSeg || ctypeGenericType1 == typeof_NpgsqlLSeg) return true;
if (ctype == typeof_NpgsqlBox || ctypeGenericType1 == typeof_NpgsqlBox) return true;
if (ctype == typeof_NpgsqlPath || ctypeGenericType1 == typeof_NpgsqlPath) return true;
if (ctype == typeof_NpgsqlPolygon || ctypeGenericType1 == typeof_NpgsqlPolygon) return true;
if (ctype == typeof_NpgsqlCircle || ctypeGenericType1 == typeof_NpgsqlCircle) return true;
if (ctype == typeof_Cidr || ctypeGenericType1 == typeof_Cidr) return true;
if (ctype == typeof_IPAddress) return true;
if (ctype == typeof_PhysicalAddress) return true;
if (ctype == typeof_NpgsqlRange_int || ctypeGenericType1 == typeof_NpgsqlRange_int) return true;
if (ctype == typeof_NpgsqlRange_long || ctypeGenericType1 == typeof_NpgsqlRange_long) return true;
if (ctype == typeof_NpgsqlRange_decimal || ctypeGenericType1 == typeof_NpgsqlRange_decimal) return true;
if (ctype == typeof_NpgsqlRange_DateTime || ctypeGenericType1 == typeof_NpgsqlRange_DateTime) return true;
return false;
}
private object YieldJToken(Type ctype, JToken jt, int rank) {
if (jt.Type == JTokenType.Null) return null;
if (rank == 0) {
var ctypeGenericType1 = ctype.GenericTypeArguments.FirstOrDefault();//ctype.Namespace == "System" && ctype.Name.StartsWith("Nullable`") ? ctype.GenericTypeArguments.FirstOrDefault() : null;
if (ctype == typeof_BitArray) return jt.ToString().ToBitArray();
if (ctype == typeof_NpgsqlPoint || ctypeGenericType1 == typeof_NpgsqlPoint) return NpgsqlPoint.Parse(jt.ToString());
if (ctype == typeof_NpgsqlLine || ctypeGenericType1 == typeof_NpgsqlLine) return NpgsqlLine.Parse(jt.ToString());
if (ctype == typeof_NpgsqlLSeg || ctypeGenericType1 == typeof_NpgsqlLSeg) return NpgsqlLSeg.Parse(jt.ToString());
if (ctype == typeof_NpgsqlBox || ctypeGenericType1 == typeof_NpgsqlBox) return NpgsqlBox.Parse(jt.ToString());
if (ctype == typeof_NpgsqlPath || ctypeGenericType1 == typeof_NpgsqlPath) return NpgsqlPath.Parse(jt.ToString());
if (ctype == typeof_NpgsqlPolygon || ctypeGenericType1 == typeof_NpgsqlPolygon) return NpgsqlPolygon.Parse(jt.ToString());
if (ctype == typeof_NpgsqlCircle || ctypeGenericType1 == typeof_NpgsqlCircle) return NpgsqlCircle.Parse(jt.ToString());
if (ctype == typeof_Cidr || ctypeGenericType1 == typeof_Cidr) {
var cidrArgs = jt.ToString().Split(new[] { '/' }, 2);
return (IPAddress.Parse(cidrArgs.First()), cidrArgs.Length >= 2 ? int.TryParse(cidrArgs[1], out var tryCdirSubnet) ? tryCdirSubnet : 0 : 0);
}
if (ctype == typeof_IPAddress) return IPAddress.Parse(jt.ToString());
if (ctype == typeof_PhysicalAddress) return PhysicalAddress.Parse(jt.ToString());
if (ctype == typeof_NpgsqlRange_int || ctypeGenericType1 == typeof_NpgsqlRange_int) return jt.ToString().ToNpgsqlRange<int>();
if (ctype == typeof_NpgsqlRange_long || ctypeGenericType1 == typeof_NpgsqlRange_long) return jt.ToString().ToNpgsqlRange<long>();
if (ctype == typeof_NpgsqlRange_decimal || ctypeGenericType1 == typeof_NpgsqlRange_decimal) return jt.ToString().ToNpgsqlRange<decimal>();
if (ctype == typeof_NpgsqlRange_DateTime || ctypeGenericType1 == typeof_NpgsqlRange_DateTime) return jt.ToString().ToNpgsqlRange<DateTime>();
return null;
}
var jtarr = jt.ToArray();
var ret = Array.CreateInstance(ctype, jtarr.Length);
var jtarrIdx = 0;
foreach (var a in jtarr) {
var t2 = YieldJToken(ctype, a, rank - 1);
ret.SetValue(t2, jtarrIdx++);
}
return ret;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
int rank = objectType.IsArray ? objectType.GetArrayRank() : 0;
Type ctype = objectType.IsArray ? objectType.GetElementType() : objectType;
var ret = YieldJToken(ctype, JToken.Load(reader), rank);
if (ret != null && rank > 0) return ret;
return ret;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
Type objectType = value.GetType();
if (objectType.IsArray) {
int rank = objectType.GetArrayRank();
int[] indices = new int[rank];
GetJObject(value as Array, indices, 0).WriteTo(writer);
} else
GetJObject(value).WriteTo(writer);
}
public static JToken GetJObject(object value) {
if (value is BitArray) return JToken.FromObject((value as BitArray)?.To1010());
if (value is IPAddress) return JToken.FromObject((value as IPAddress)?.ToString());
if (value is ValueTuple<IPAddress, int> || value is ValueTuple<IPAddress, int>?) {
ValueTuple<IPAddress, int>? cidrValue = (ValueTuple<IPAddress, int>?)value;
return JToken.FromObject(cidrValue == null ? null : $"{cidrValue.Value.Item1.ToString()}/{cidrValue.Value.Item2.ToString()}");
}
return JToken.FromObject(value?.ToString());
}
public static JToken GetJObject(Array value, int[] indices, int idx) {
if (idx == indices.Length) {
return GetJObject(value.GetValue(indices));
}
JArray ja = new JArray();
if (indices.Length == 1) {
foreach(object a in value)
ja.Add(GetJObject(a));
return ja;
}
int lb = value.GetLowerBound(idx);
int ub = value.GetUpperBound(idx);
for (int b = lb; b <= ub; b++) {
indices[idx] = b;
ja.Add(GetJObject(value, indices, idx + 1));
}
return ja;
}
}
}

View File

@ -1,65 +0,0 @@
using Npgsql.LegacyPostgis;
using NpgsqlTypes;
using System;
using System.Collections;
public static partial class PostgreSQLTypesExtensions {
/// <summary>
/// 测量两个经纬度的距离,返回单位:米
/// </summary>
/// <param name="that">经纬坐标1</param>
/// <param name="point">经纬坐标2</param>
/// <returns>返回距离(单位:米)</returns>
public static double Distance(this NpgsqlPoint that, NpgsqlPoint point) {
double radLat1 = (double)(that.Y) * Math.PI / 180d;
double radLng1 = (double)(that.X) * Math.PI / 180d;
double radLat2 = (double)(point.Y) * Math.PI / 180d;
double radLng2 = (double)(point.X) * Math.PI / 180d;
return 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin((radLat1 - radLat2) / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin((radLng1 - radLng2) / 2), 2))) * 6378137;
}
/// <summary>
/// 测量两个经纬度的距离,返回单位:米
/// </summary>
/// <param name="that">经纬坐标1</param>
/// <param name="point">经纬坐标2</param>
/// <returns>返回距离(单位:米)</returns>
public static double Distance(this PostgisPoint that, PostgisPoint point) {
double radLat1 = (double)(that.Y) * Math.PI / 180d;
double radLng1 = (double)(that.X) * Math.PI / 180d;
double radLat2 = (double)(point.Y) * Math.PI / 180d;
double radLng2 = (double)(point.X) * Math.PI / 180d;
return 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin((radLat1 - radLat2) / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin((radLng1 - radLng2) / 2), 2))) * 6378137;
}
public static string To1010(this BitArray ba) {
char[] ret = new char[ba.Length];
for (int a = 0; a < ba.Length; a++) ret[a] = ba[a] ? '1' : '0';
return new string(ret);
}
/// <summary>
/// 将 1010101010 这样的二进制字符串转换成 BitArray
/// </summary>
/// <param name="_1010Str">1010101010</param>
/// <returns></returns>
public static BitArray ToBitArray(this string _1010Str) {
if (_1010Str == null) return null;
BitArray ret = new BitArray(_1010Str.Length);
for (int a = 0; a < _1010Str.Length; a++) ret[a] = _1010Str[a] == '1';
return ret;
}
public static NpgsqlRange<T> ToNpgsqlRange<T>(this string that) {
var s = that;
if (string.IsNullOrEmpty(s) || s == "empty") return NpgsqlRange<T>.Empty;
string s1 = s.Trim('(', ')', '[', ']');
string[] ss = s1.Split(new char[] { ',' }, 2);
if (ss.Length != 2) return NpgsqlRange<T>.Empty;
T t1 = default(T);
T t2 = default(T);
if (!string.IsNullOrEmpty(ss[0])) t1 = (T)Convert.ChangeType(ss[0], typeof(T));
if (!string.IsNullOrEmpty(ss[1])) t2 = (T)Convert.ChangeType(ss[1], typeof(T));
return new NpgsqlRange<T>(t1, s[0] == '[', s[0] == '(', t2, s[s.Length - 1] == ']', s[s.Length - 1] == ')');
}
}

View File

@ -1,377 +0,0 @@
using FreeSql.DataAnnotations;
using FreeSql.DatabaseModel;
using FreeSql.Internal;
using FreeSql.Internal.Model;
using Newtonsoft.Json.Linq;
using Npgsql.LegacyPostgis;
using NpgsqlTypes;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
using System.Text.RegularExpressions;
namespace FreeSql.PostgreSQL {
class PostgreSQLCodeFirst : ICodeFirst {
IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
public PostgreSQLCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) {
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
}
public bool IsAutoSyncStructure { get; set; } = false;
public bool IsSyncStructureToLower { get; set; } = false;
public bool IsSyncStructureToUpper { get; set; } = false;
public bool IsConfigEntityFromDbFirst { get; set; } = false;
public bool IsNoneCommandParameter { get; set; } = false;
public bool IsLazyLoading { get; set; } = false;
static object _dicCsToDbLock = new object();
static Dictionary<string, (NpgsqlDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)> _dicCsToDb = new Dictionary<string, (NpgsqlDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)>() {
{ typeof(sbyte).FullName, (NpgsqlDbType.Smallint, "int2","int2 NOT NULL", false, false, 0) },{ typeof(sbyte?).FullName, (NpgsqlDbType.Smallint, "int2", "int2", false, true, null) },
{ typeof(short).FullName, (NpgsqlDbType.Smallint, "int2","int2 NOT NULL", false, false, 0) },{ typeof(short?).FullName, (NpgsqlDbType.Smallint, "int2", "int2", false, true, null) },
{ typeof(int).FullName, (NpgsqlDbType.Integer, "int4","int4 NOT NULL", false, false, 0) },{ typeof(int?).FullName, (NpgsqlDbType.Integer, "int4", "int4", false, true, null) },
{ typeof(long).FullName, (NpgsqlDbType.Bigint, "int8","int8 NOT NULL", false, false, 0) },{ typeof(long?).FullName, (NpgsqlDbType.Bigint, "int8", "int8", false, true, null) },
{ typeof(byte).FullName, (NpgsqlDbType.Smallint, "int2","int2 NOT NULL", false, false, 0) },{ typeof(byte?).FullName, (NpgsqlDbType.Smallint, "int2", "int2", false, true, null) },
{ typeof(ushort).FullName, (NpgsqlDbType.Integer, "int4","int4 NOT NULL", false, false, 0) },{ typeof(ushort?).FullName, (NpgsqlDbType.Integer, "int4", "int4", false, true, null) },
{ typeof(uint).FullName, (NpgsqlDbType.Bigint, "int8","int8 NOT NULL", false, false, 0) },{ typeof(uint?).FullName, (NpgsqlDbType.Bigint, "int8", "int8", false, true, null) },
{ typeof(ulong).FullName, (NpgsqlDbType.Numeric, "numeric","numeric(20,0) NOT NULL", false, false, 0) },{ typeof(ulong?).FullName, (NpgsqlDbType.Numeric, "numeric", "numeric(20,0)", false, true, null) },
{ typeof(float).FullName, (NpgsqlDbType.Real, "float4","float4 NOT NULL", false, false, 0) },{ typeof(float?).FullName, (NpgsqlDbType.Real, "float4", "float4", false, true, null) },
{ typeof(double).FullName, (NpgsqlDbType.Double, "float8","float8 NOT NULL", false, false, 0) },{ typeof(double?).FullName, (NpgsqlDbType.Double, "float8", "float8", false, true, null) },
{ typeof(decimal).FullName, (NpgsqlDbType.Numeric, "numeric", "numeric(10,2) NOT NULL", false, false, 0) },{ typeof(decimal?).FullName, (NpgsqlDbType.Numeric, "numeric", "numeric(10,2)", false, true, null) },
{ typeof(string).FullName, (NpgsqlDbType.Varchar, "varchar", "varchar(255)", false, null, "") },
{ typeof(TimeSpan).FullName, (NpgsqlDbType.Time, "time","time NOT NULL", false, false, 0) },{ typeof(TimeSpan?).FullName, (NpgsqlDbType.Time, "time", "time",false, true, null) },
{ typeof(DateTime).FullName, (NpgsqlDbType.Timestamp, "timestamp", "timestamp NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, (NpgsqlDbType.Timestamp, "timestamp", "timestamp", false, true, null) },
{ typeof(bool).FullName, (NpgsqlDbType.Boolean, "bool","bool NOT NULL", null, false, false) },{ typeof(bool?).FullName, (NpgsqlDbType.Boolean, "bool","bool", null, true, null) },
{ typeof(Byte[]).FullName, (NpgsqlDbType.Bytea, "bytea", "bytea", false, null, new byte[0]) },
{ typeof(BitArray).FullName, (NpgsqlDbType.Varbit, "varbit", "varbit(64)", false, null, new BitArray(new byte[64])) },
{ typeof(NpgsqlPoint).FullName, (NpgsqlDbType.Point, "point", "point NOT NULL", false, false, new NpgsqlPoint(0, 0)) },{ typeof(NpgsqlPoint?).FullName, (NpgsqlDbType.Point, "point", "point", false, true, null) },
{ typeof(NpgsqlLine).FullName, (NpgsqlDbType.Line, "line", "line NOT NULL", false, false, new NpgsqlLine(0, 0, 1)) },{ typeof(NpgsqlLine?).FullName, (NpgsqlDbType.Line, "line", "line", false, true, null) },
{ typeof(NpgsqlLSeg).FullName, (NpgsqlDbType.LSeg, "lseg", "lseg NOT NULL", false, false, new NpgsqlLSeg(0, 0, 0, 0)) },{ typeof(NpgsqlLSeg?).FullName, (NpgsqlDbType.LSeg, "lseg", "lseg", false, true, null) },
{ typeof(NpgsqlBox).FullName, (NpgsqlDbType.Box, "box", "box NOT NULL", false, false, new NpgsqlBox(0, 0, 0, 0)) },{ typeof(NpgsqlBox?).FullName, (NpgsqlDbType.Box, "box", "box", false, true, null) },
{ typeof(NpgsqlPath).FullName, (NpgsqlDbType.Path, "path", "path NOT NULL", false, false, new NpgsqlPath(new NpgsqlPoint(0, 0))) },{ typeof(NpgsqlPath?).FullName, (NpgsqlDbType.Path, "path", "path", false, true, null) },
{ typeof(NpgsqlPolygon).FullName, (NpgsqlDbType.Polygon, "polygon", "polygon NOT NULL", false, false, new NpgsqlPolygon(new NpgsqlPoint(0, 0), new NpgsqlPoint(0, 0))) },{ typeof(NpgsqlPolygon?).FullName, (NpgsqlDbType.Polygon, "polygon", "polygon", false, true, null) },
{ typeof(NpgsqlCircle).FullName, (NpgsqlDbType.Circle, "circle", "circle NOT NULL", false, false, new NpgsqlCircle(0, 0, 0)) },{ typeof(NpgsqlCircle?).FullName, (NpgsqlDbType.Circle, "circle", "circle", false, true, null) },
{ typeof((IPAddress Address, int Subnet)).FullName, (NpgsqlDbType.Cidr, "cidr", "cidr NOT NULL", false, false, (IPAddress.Any, 0)) },{ typeof((IPAddress Address, int Subnet)?).FullName, (NpgsqlDbType.Cidr, "cidr", "cidr", false, true, null) },
{ typeof(IPAddress).FullName, (NpgsqlDbType.Inet, "inet", "inet", false, null, IPAddress.Any) },
{ typeof(PhysicalAddress).FullName, (NpgsqlDbType.MacAddr, "macaddr", "macaddr", false, null, PhysicalAddress.None) },
{ typeof(JToken).FullName, (NpgsqlDbType.Jsonb, "jsonb", "jsonb", false, null, JToken.Parse("{}")) },
{ typeof(JObject).FullName, (NpgsqlDbType.Jsonb, "jsonb", "jsonb", false, null, JObject.Parse("{}")) },
{ typeof(JArray).FullName, (NpgsqlDbType.Jsonb, "jsonb", "jsonb", false, null, JArray.Parse("[]")) },
{ typeof(Guid).FullName, (NpgsqlDbType.Uuid, "uuid", "uuid NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName, (NpgsqlDbType.Uuid, "uuid", "uuid", false, true, null) },
{ typeof(NpgsqlRange<int>).FullName, (NpgsqlDbType.Range | NpgsqlDbType.Integer, "int4range", "int4range NOT NULL", false, false, NpgsqlRange<int>.Empty) },{ typeof(NpgsqlRange<int>?).FullName, (NpgsqlDbType.Range | NpgsqlDbType.Integer, "int4range", "int4range", false, true, null) },
{ typeof(NpgsqlRange<long>).FullName, (NpgsqlDbType.Range | NpgsqlDbType.Bigint, "int8range", "int8range NOT NULL", false, false, NpgsqlRange<long>.Empty) },{ typeof(NpgsqlRange<long>?).FullName, (NpgsqlDbType.Range | NpgsqlDbType.Bigint, "int8range", "int8range", false, true, null) },
{ typeof(NpgsqlRange<decimal>).FullName, (NpgsqlDbType.Range | NpgsqlDbType.Numeric, "numrange", "numrange NOT NULL", false, false, NpgsqlRange<decimal>.Empty) },{ typeof(NpgsqlRange<decimal>?).FullName, (NpgsqlDbType.Range | NpgsqlDbType.Numeric, "numrange", "numrange", false, true, null) },
{ typeof(NpgsqlRange<DateTime>).FullName, (NpgsqlDbType.Range | NpgsqlDbType.Timestamp, "tsrange", "tsrange NOT NULL", false, false, NpgsqlRange<DateTime>.Empty) },{ typeof(NpgsqlRange<DateTime>?).FullName, (NpgsqlDbType.Range | NpgsqlDbType.Timestamp, "tsrange", "tsrange", false, true, null) },
{ typeof(Dictionary<string, string>).FullName, (NpgsqlDbType.Hstore, "hstore", "hstore", false, null, new Dictionary<string, string>()) },
{ typeof(PostgisPoint).FullName, (NpgsqlDbType.Geometry, "geometry", "geometry", false, null, new PostgisPoint(0, 0)) },
{ typeof(PostgisLineString).FullName, (NpgsqlDbType.Geometry, "geometry", "geometry", false, null, new PostgisLineString(new []{new Coordinate2D(0, 0),new Coordinate2D(0, 0) })) },
{ typeof(PostgisPolygon).FullName, (NpgsqlDbType.Geometry, "geometry", "geometry", false, null, new PostgisPolygon(new []{new []{new Coordinate2D(0, 0),new Coordinate2D(0, 0) }, new []{new Coordinate2D(0, 0),new Coordinate2D(0, 0) } })) },
{ typeof(PostgisMultiPoint).FullName, (NpgsqlDbType.Geometry, "geometry", "geometry", false, null, new PostgisMultiPoint(new []{new Coordinate2D(0, 0),new Coordinate2D(0, 0) })) },
{ typeof(PostgisMultiLineString).FullName, (NpgsqlDbType.Geometry, "geometry", "geometry", false, null, new PostgisMultiLineString(new[]{new PostgisLineString(new []{new Coordinate2D(0, 0),new Coordinate2D(0, 0) }),new PostgisLineString(new []{new Coordinate2D(0, 0),new Coordinate2D(0, 0) }) })) },
{ typeof(PostgisMultiPolygon).FullName, (NpgsqlDbType.Geometry, "geometry", "geometry", false, null, new PostgisMultiPolygon(new[]{new PostgisPolygon(new []{new []{new Coordinate2D(0, 0),new Coordinate2D(0, 0) }, new []{new Coordinate2D(0, 0),new Coordinate2D(0, 0) } }),new PostgisPolygon(new []{new []{new Coordinate2D(0, 0),new Coordinate2D(0, 0) }, new []{new Coordinate2D(0, 0),new Coordinate2D(0, 0) } }) })) },
{ typeof(PostgisGeometry).FullName, (NpgsqlDbType.Geometry, "geometry", "geometry", false, null, new PostgisPoint(0, 0)) },
{ typeof(PostgisGeometryCollection).FullName, (NpgsqlDbType.Geometry, "geometry", "geometry", false, null, new PostgisGeometryCollection(new[]{new PostgisPoint(0, 0),new PostgisPoint(0, 0) })) },
};
public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) {
var isarray = type.FullName != "System.Byte[]" && type.IsArray;
var elementType = isarray ? type.GetElementType() : type;
var info = GetDbInfoNoneArray(elementType);
if (info == null) return null;
if (isarray == false) return ((int)info.Value.type, info.Value.dbtype, info.Value.dbtypeFull, info.Value.isnullable, info.Value.defaultValue);
var dbtypefull = Regex.Replace(info.Value.dbtypeFull, $@"{info.Value.dbtype}(\s*\([^\)]+\))?", "$0[]").Replace(" NOT NULL", "");
return ((int)(info.Value.type | NpgsqlDbType.Array), $"{info.Value.dbtype}[]", dbtypefull, null, Array.CreateInstance(elementType, 0));
}
(NpgsqlDbType type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfoNoneArray(Type type) {
if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (NpgsqlDbType, string, string, bool?, object)?((trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue));
if (type.IsArray) return null;
var enumType = type.IsEnum ? type : null;
if (enumType == null && type.IsNullableType() && type.GenericTypeArguments.Length == 1 && type.GenericTypeArguments.First().IsEnum) enumType = type.GenericTypeArguments.First();
if (enumType != null) {
var newItem = enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Any() ?
(NpgsqlDbType.Bigint, "int8", $"int8{(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0)) :
(NpgsqlDbType.Integer, "int4", $"int4{(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0));
if (_dicCsToDb.ContainsKey(type.FullName) == false) {
lock (_dicCsToDbLock) {
if (_dicCsToDb.ContainsKey(type.FullName) == false)
_dicCsToDb.Add(type.FullName, newItem);
}
}
return (newItem.Item1, newItem.Item2, newItem.Item3, newItem.Item5, newItem.Item6);
}
return null;
}
public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity));
public string GetComparisonDDLStatements(params Type[] entityTypes) {
var sb = new StringBuilder();
var seqcols = new List<(ColumnInfo, string[], bool)>(); //序列
foreach (var entityType in entityTypes) {
if (sb.Length > 0) sb.Append("\r\n");
var tb = _commonUtils.GetTableByEntity(entityType);
if (tb == null) throw new Exception($"类型 {entityType.FullName} 不可迁移");
if (tb.Columns.Any() == false) throw new Exception($"类型 {entityType.FullName} 不可迁移可迁移属性0个");
var tbname = tb.DbName.Split(new[] { '.' }, 2);
if (tbname?.Length == 1) tbname = new[] { "public", tbname[0] };
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //旧表名
if (tboldname?.Length == 1) tboldname = new[] { "public", tboldname[0] };
if (string.Compare(tbname[0], "public", true) != 0 && _orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(" select 1 from pg_namespace where nspname={0}", tbname[0])) == null) //创建模式
sb.Append("CREATE SCHEMA IF NOT EXISTS ").Append(tbname[0]).Append(";\r\n");
var sbalter = new StringBuilder();
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
if (_orm.Ado.ExecuteScalar(CommandType.Text, string.Format(" select 1 from pg_tables a inner join pg_namespace b on b.nspname = a.schemaname where b.nspname || '.' || a.tablename = '{0}.{1}'", tbname)) == null) { //表不存在
if (tboldname != null) {
if (_orm.Ado.ExecuteScalar(CommandType.Text, string.Format(" select 1 from pg_tables a inner join pg_namespace b on b.nspname = a.schemaname where b.nspname || '.' || a.tablename = '{0}.{1}'", tboldname)) == null)
//旧表不存在
tboldname = null;
}
if (tboldname == null) {
//创建表
sb.Append("CREATE TABLE IF NOT EXISTS ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ( ");
foreach (var tbcol in tb.Columns.Values) {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(",");
if (tbcol.Attribute.IsIdentity == true) seqcols.Add((tbcol, tbname, true));
}
if (tb.Primarys.Any()) {
sb.Append(" \r\n CONSTRAINT ").Append(tbname[0]).Append("_").Append(tbname[1]).Append("_pkey PRIMARY KEY (");
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
foreach (var uk in tb.Uniques) {
sb.Append(" \r\n CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(" UNIQUE(");
foreach (var tbcol in uk.Value) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
sb.Remove(sb.Length - 1, 1);
sb.Append("\r\n) WITH (OIDS=FALSE);\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[1]}")).Append(";\r\n");
else {
//如果新表,旧表不在一起,创建新表,导入数据,删除旧表
istmpatler = true;
}
} else
tboldname = null; //如果新表已经存在,不走改表名逻辑
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
var sql = _commonUtils.FormatSql(@"
select
a.attname,
t.typname,
case when a.atttypmod > 0 and a.atttypmod < 32767 then a.atttypmod - 4 else a.attlen end len,
case when t.typelem > 0 and t.typinput::varchar = 'array_in' then t2.typname else t.typname end,
case when a.attnotnull then '0' else '1' end as is_nullable,
e.adsrc,
a.attndims
from pg_class c
inner join pg_attribute a on a.attnum > 0 and a.attrelid = c.oid
inner join pg_type t on t.oid = a.atttypid
left join pg_type t2 on t2.oid = t.typelem
left join pg_description d on d.objoid = a.attrelid and d.objsubid = a.attnum
left join pg_attrdef e on e.adrelid = a.attrelid and e.adnum = a.attnum
inner join pg_namespace ns on ns.oid = c.relnamespace
inner join pg_namespace ns2 on ns2.oid = t.typnamespace
where ns.nspname = {0} and c.relname = {1}", tboldname ?? tbname);
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => {
var attndims = int.Parse(string.Concat(a[6]));
var type = string.Concat(a[1]);
var sqlType = string.Concat(a[3]);
var max_length = long.Parse(string.Concat(a[2]));
switch (sqlType.ToLower()) {
case "bool": case "name": case "bit": case "varbit": case "bpchar": case "varchar": case "bytea": case "text": case "uuid": break;
default: max_length *= 8; break;
}
if (type.StartsWith("_")) {
type = type.Substring(1);
if (attndims == 0) attndims++;
}
if (sqlType.StartsWith("_")) sqlType = sqlType.Substring(1);
return new {
column = string.Concat(a[0]),
sqlType = string.Concat(sqlType),
max_length = long.Parse(string.Concat(a[2])),
is_nullable = string.Concat(a[4]) == "1",
is_identity = string.Concat(a[5]).StartsWith(@"nextval('") && string.Concat(a[5]).EndsWith(@"'::regclass)"),
attndims
};
}, StringComparer.CurrentCultureIgnoreCase);
if (istmpatler == false) {
foreach (var tbcol in tb.Columns.Values) {
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false ||
tbcol.Attribute.DbType.Contains("[]") != (tbstructcol.attndims > 0))
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" TYPE ").Append(tbcol.Attribute.DbType.Split(' ').First()).Append(";\r\n");
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable)
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(tbcol.Attribute.IsNullable == true ? "DROP" : "SET").Append(" NOT NULL;\r\n");
if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity)
seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity == true));
if (tbstructcol.column == tbcol.Attribute.OldName)
//修改列名
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.OldName)).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 COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType.Split(' ').First()).Append(";\r\n");
sbalter.Append("UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" = ").Append(_commonUtils.FormatSql("{0};\r\n", tbcol.Attribute.DbDefautValue));
if (tbcol.Attribute.IsNullable == false) sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" SET NOT NULL;\r\n");
if (tbcol.Attribute.IsIdentity == true) seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity == true));
}
var dsuksql = _commonUtils.FormatSql(@"
select
c.attname,
b.relname
from pg_index a
inner join pg_class b on b.oid = a.indexrelid
inner join pg_attribute c on c.attnum > 0 and c.attrelid = b.oid
inner join pg_namespace ns on ns.oid = b.relnamespace
inner join pg_class d on d.oid = a.indrelid
where ns.nspname in ({0}) and d.relname in ({1}) and a.indisunique = 't'", tboldname ?? tbname);
var dsuk = _orm.Ado.ExecuteArray(CommandType.Text, dsuksql).Select(a => new[] { string.Concat(a[0]), string.Concat(a[1]) });
foreach (var uk in tb.Uniques) {
if (string.IsNullOrEmpty(uk.Key) || uk.Value.Any() == false) continue;
var dsukfind1 = dsuk.Where(a => string.Compare(a[1], uk.Key, true) == 0).ToArray();
if (dsukfind1.Any() == false || dsukfind1.Length != uk.Value.Count || dsukfind1.Where(a => uk.Value.Where(b => string.Compare(b.Attribute.Name, a[0], true) == 0).Any()).Count() != uk.Value.Count) {
if (dsukfind1.Any()) sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" DROP CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(";\r\n");
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(" UNIQUE(");
foreach (var tbcol in uk.Value) sbalter.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sbalter.Remove(sbalter.Length - 2, 2).Append(");\r\n");
}
}
}
if (istmpatler == false) {
sb.Append(sbalter);
continue;
}
var oldpk = _orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(@"select pg_constraint.conname as pk_name from pg_constraint
inner join pg_class on pg_constraint.conrelid = pg_class.oid
inner join pg_namespace on pg_namespace.oid = pg_class.relnamespace
where pg_namespace.nspname={0} and pg_class.relname={1} and pg_constraint.contype='p'
", tbname))?.ToString();
if (string.IsNullOrEmpty(oldpk) == false)
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" DROP CONSTRAINT ").Append(oldpk).Append(";\r\n");
//创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名
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.Columns.Values) {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(",");
if (tbcol.Attribute.IsIdentity == true) seqcols.Add((tbcol, tbname, true));
}
if (tb.Primarys.Any()) {
sb.Append(" \r\n CONSTRAINT ").Append(tbname[0]).Append("_").Append(tbname[1]).Append("_pkey PRIMARY KEY (");
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
foreach (var uk in tb.Uniques) {
sb.Append(" \r\n CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(" UNIQUE(");
foreach (var tbcol in uk.Value) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
sb.Remove(sb.Length - 1, 1);
sb.Append("\r\n) WITH (OIDS=FALSE);\r\n");
sb.Append("INSERT INTO ").Append(tmptablename).Append(" (");
foreach (var tbcol in tb.Columns.Values)
sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append(")\r\nSELECT ");
foreach (var tbcol in tb.Columns.Values) {
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)) {
insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column);
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 = $"coalesce({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue)})";
} else if (tbcol.Attribute.IsNullable == false)
insertvalue = _commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue);
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("ALTER TABLE ").Append(tmptablename).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName(tbname[1])).Append(";\r\n");
}
foreach (var seqcol in seqcols) {
var tbname = seqcol.Item2;
var seqname = Utils.GetCsName($"{tbname[0]}.{tbname[1]}_{seqcol.Item1.Attribute.Name}_sequence_name");
var tbname2 = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}");
var colname2 = _commonUtils.QuoteSqlName(seqcol.Item1.Attribute.Name);
sb.Append("ALTER TABLE ").Append(tbname2).Append(" ALTER COLUMN ").Append(colname2).Append(" SET DEFAULT null;\r\n");
sb.Append("DROP SEQUENCE IF EXISTS ").Append(seqname).Append(";\r\n");
if (seqcol.Item3) {
sb.Append("CREATE SEQUENCE ").Append(seqname).Append(";\r\n");
sb.Append("ALTER TABLE ").Append(tbname2).Append(" ALTER COLUMN ").Append(colname2).Append(" SET DEFAULT nextval('").Append(seqname).Append("'::regclass);\r\n");
sb.Append(" SELECT case when max(").Append(colname2).Append(") is null then 0 else setval('").Append(seqname).Append("', max(").Append(colname2).Append(")) end FROM ").Append(tbname2).Append(";\r\n");
}
}
return sb.Length == 0 ? null : sb.ToString();
}
static object syncStructureLock = new object();
ConcurrentDictionary<string, bool> dicSyced = new ConcurrentDictionary<string, bool>();
public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity));
public bool SyncStructure(params Type[] entityTypes) {
if (entityTypes == null) return true;
var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray();
if (syncTypes.Any() == false) return true;
var before = new Aop.SyncStructureBeforeEventArgs(entityTypes);
_orm.Aop.SyncStructureBefore?.Invoke(this, before);
Exception exception = null;
string ddl = null;
try {
lock (syncStructureLock) {
ddl = this.GetComparisonDDLStatements(syncTypes);
if (string.IsNullOrEmpty(ddl)) {
foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true);
return true;
}
var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl);
foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true);
return affrows > 0;
}
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception);
_orm.Aop.SyncStructureAfter?.Invoke(this, after);
}
}
public ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) => _commonUtils.ConfigEntity(entity);
public ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) => _commonUtils.ConfigEntity(type, entity);
public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type);
public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type);
}
}

View File

@ -1,522 +0,0 @@
using FreeSql.DatabaseModel;
using FreeSql.Internal;
using Newtonsoft.Json.Linq;
using Npgsql.LegacyPostgis;
using NpgsqlTypes;
using SafeObjectPool;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Text.RegularExpressions;
namespace FreeSql.PostgreSQL {
class PostgreSQLDbFirst : IDbFirst {
IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
public PostgreSQLDbFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) {
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
}
public int GetDbType(DbColumnInfo column) => (int)GetNpgsqlDbType(column);
NpgsqlDbType GetNpgsqlDbType(DbColumnInfo column) {
var dbtype = column.DbTypeText;
var isarray = dbtype.EndsWith("[]");
if (isarray) dbtype = dbtype.Remove(dbtype.Length - 2);
NpgsqlDbType ret = NpgsqlDbType.Unknown;
switch (dbtype.ToLower().TrimStart('_')) {
case "int2": ret = NpgsqlDbType.Smallint;break;
case "int4": ret = NpgsqlDbType.Integer; break;
case "int8": ret = NpgsqlDbType.Bigint; break;
case "numeric": ret = NpgsqlDbType.Numeric; break;
case "float4": ret = NpgsqlDbType.Real; break;
case "float8": ret = NpgsqlDbType.Double; break;
case "money": ret = NpgsqlDbType.Money; break;
case "bpchar": ret = NpgsqlDbType.Char; break;
case "varchar": ret = NpgsqlDbType.Varchar; break;
case "text": ret = NpgsqlDbType.Text; break;
case "timestamp": ret = NpgsqlDbType.Timestamp; break;
case "timestamptz": ret = NpgsqlDbType.TimestampTz; break;
case "date": ret = NpgsqlDbType.Date; break;
case "time": ret = NpgsqlDbType.Time; break;
case "timetz": ret = NpgsqlDbType.TimeTz; break;
case "interval": ret = NpgsqlDbType.Interval; break;
case "bool": ret = NpgsqlDbType.Boolean; break;
case "bytea": ret = NpgsqlDbType.Bytea; break;
case "bit": ret = NpgsqlDbType.Bit; break;
case "varbit": ret = NpgsqlDbType.Varbit; break;
case "point": ret = NpgsqlDbType.Point; break;
case "line": ret = NpgsqlDbType.Line; break;
case "lseg": ret = NpgsqlDbType.LSeg; break;
case "box": ret = NpgsqlDbType.Box; break;
case "path": ret = NpgsqlDbType.Path; break;
case "polygon": ret = NpgsqlDbType.Polygon; break;
case "circle": ret = NpgsqlDbType.Circle; break;
case "cidr": ret = NpgsqlDbType.Cidr; break;
case "inet": ret = NpgsqlDbType.Inet; break;
case "macaddr": ret = NpgsqlDbType.MacAddr; break;
case "json": ret = NpgsqlDbType.Json; break;
case "jsonb": ret = NpgsqlDbType.Jsonb; break;
case "uuid": ret = NpgsqlDbType.Uuid; break;
case "int4range": ret = NpgsqlDbType.Range | NpgsqlDbType.Integer; break;
case "int8range": ret = NpgsqlDbType.Range | NpgsqlDbType.Bigint; break;
case "numrange": ret = NpgsqlDbType.Range | NpgsqlDbType.Numeric; break;
case "tsrange": ret = NpgsqlDbType.Range | NpgsqlDbType.Timestamp; break;
case "tstzrange": ret = NpgsqlDbType.Range | NpgsqlDbType.TimestampTz; break;
case "daterange": ret = NpgsqlDbType.Range | NpgsqlDbType.Date; break;
case "hstore": ret = NpgsqlDbType.Hstore; break;
case "geometry": ret = NpgsqlDbType.Geometry; break;
}
return isarray ? (ret | NpgsqlDbType.Array) : ret;
}
static readonly Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)> _dicDbToCs = new Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)>() {
{ (int)NpgsqlDbType.Smallint, ("(short?)", "short.Parse({0})", "{0}.ToString()", "short?", typeof(short), typeof(short?), "{0}.Value", "GetInt16") },
{ (int)NpgsqlDbType.Integer, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
{ (int)NpgsqlDbType.Bigint, ("(long?)", "long.Parse({0})", "{0}.ToString()", "long?", typeof(long), typeof(long?), "{0}.Value", "GetInt64") },
{ (int)NpgsqlDbType.Numeric, ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") },
{ (int)NpgsqlDbType.Real, ("(float?)", "float.Parse({0})", "{0}.ToString()", "float?", typeof(float), typeof(float?), "{0}.Value", "GetFloat") },
{ (int)NpgsqlDbType.Double, ("(double?)", "double.Parse({0})", "{0}.ToString()", "double?", typeof(double), typeof(double?), "{0}.Value", "GetDouble") },
{ (int)NpgsqlDbType.Money, ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") },
{ (int)NpgsqlDbType.Char, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)NpgsqlDbType.Varchar, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)NpgsqlDbType.Text, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)NpgsqlDbType.Timestamp, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
{ (int)NpgsqlDbType.TimestampTz, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
{ (int)NpgsqlDbType.Date, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
{ (int)NpgsqlDbType.Time, ("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") },
{ (int)NpgsqlDbType.TimeTz, ("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") },
{ (int)NpgsqlDbType.Interval, ("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") },
{ (int)NpgsqlDbType.Boolean, ("(bool?)", "{0} == \"1\"", "{0} == true ? \"1\" : \"0\"", "bool?", typeof(bool), typeof(bool?), "{0}.Value", "GetBoolean") },
{ (int)NpgsqlDbType.Bytea, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
{ (int)NpgsqlDbType.Bit, ("(BitArray)", "{0}.ToBitArray()", "{0}.To1010()", "BitArray", typeof(BitArray), typeof(BitArray), "{0}", "GetValue") },
{ (int)NpgsqlDbType.Varbit, ("(BitArray)", "{0}.ToBitArray()", "{0}.To1010()", "BitArray", typeof(BitArray), typeof(BitArray), "{0}", "GetValue") },
{ (int)NpgsqlDbType.Point, ("(NpgsqlPoint?)", "NpgsqlPoint.Parse({0})", "{0}.ToString()", "NpgsqlPoint", typeof(NpgsqlPoint), typeof(NpgsqlPoint?), "{0}", "GetValue") },
{ (int)NpgsqlDbType.Line, ("(NpgsqlLine?)", "NpgsqlLine.Parse({0})", "{0}.ToString()", "NpgsqlLine", typeof(NpgsqlLine), typeof(NpgsqlLine?), "{0}", "GetValue") },
{ (int)NpgsqlDbType.LSeg, ("(NpgsqlLSeg?)", "NpgsqlLSeg.Parse({0})", "{0}.ToString()", "NpgsqlLSeg", typeof(NpgsqlLSeg), typeof(NpgsqlLSeg?), "{0}", "GetValue") },
{ (int)NpgsqlDbType.Box, ("(NpgsqlBox?)", "NpgsqlBox.Parse({0})", "{0}.ToString()", "NpgsqlBox", typeof(NpgsqlBox), typeof(NpgsqlBox?), "{0}", "GetValue") },
{ (int)NpgsqlDbType.Path, ("(NpgsqlPath?)", "NpgsqlPath.Parse({0})", "{0}.ToString()", "NpgsqlPath", typeof(NpgsqlPath), typeof(NpgsqlPath?), "{0}", "GetValue") },
{ (int)NpgsqlDbType.Polygon, ("(NpgsqlPolygon?)", "NpgsqlPolygon.Parse({0})", "{0}.ToString()", "NpgsqlPolygon", typeof(NpgsqlPolygon), typeof(NpgsqlPolygon?), "{0}", "GetValue") },
{ (int)NpgsqlDbType.Circle, ("(NpgsqlCircle?)", "NpgsqlCircle.Parse({0})", "{0}.ToString()", "NpgsqlCircle", typeof(NpgsqlCircle), typeof(NpgsqlCircle?), "{0}", "GetValue") },
{ (int)NpgsqlDbType.Cidr, ("((IPAddress, int)?)", "(IPAddress, int)({0})", "{0}.ToString()", "(IPAddress, int)", typeof((IPAddress, int)), typeof((IPAddress, int)?), "{0}", "GetValue") },
{ (int)NpgsqlDbType.Inet, ("(IPAddress)", "IPAddress.Parse({0})", "{0}.ToString()", "IPAddress", typeof(IPAddress), typeof(IPAddress), "{0}", "GetValue") },
{ (int)NpgsqlDbType.MacAddr, ("(PhysicalAddress?)", "PhysicalAddress.Parse({0})", "{0}.ToString()", "PhysicalAddress", typeof(PhysicalAddress), typeof(PhysicalAddress), "{0}", "GetValue") },
{ (int)NpgsqlDbType.Json, ("(JToken)", "JToken.Parse({0})", "{0}.ToString()", "JToken", typeof(JToken), typeof(JToken), "{0}", "GetString") },
{ (int)NpgsqlDbType.Jsonb, ("(JToken)", "JToken.Parse({0})", "{0}.ToString()", "JToken", typeof(JToken), typeof(JToken), "{0}", "GetString") },
{ (int)NpgsqlDbType.Uuid, ("(Guid?)", "Guid.Parse({0})", "{0}.ToString()", "Guid", typeof(Guid), typeof(Guid?), "{0}", "GetString") },
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Integer), ("(NpgsqlRange<int>?)", "{0}.ToNpgsqlRange<int>()", "{0}.ToString()", "NpgsqlRange<int>", typeof(NpgsqlRange<int>), typeof(NpgsqlRange<int>?), "{0}", "GetString") },
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Bigint), ("(NpgsqlRange<long>?)", "{0}.ToNpgsqlRange<long>()", "{0}.ToString()", "NpgsqlRange<long>", typeof(NpgsqlRange<long>), typeof(NpgsqlRange<long>?), "{0}", "GetString") },
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Numeric), ("(NpgsqlRange<decimal>?)", "{0}.ToNpgsqlRange<decimal>()", "{0}.ToString()", "NpgsqlRange<decimal>", typeof(NpgsqlRange<decimal>), typeof(NpgsqlRange<decimal>?), "{0}", "GetString") },
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Timestamp), ("(NpgsqlRange<DateTime>?)", "{0}.ToNpgsqlRange<DateTime>()", "{0}.ToString()", "NpgsqlRange<DateTime>", typeof(NpgsqlRange<DateTime>), typeof(NpgsqlRange<DateTime>?), "{0}", "GetString") },
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.TimestampTz), ("(NpgsqlRange<DateTime>?)", "{0}.ToNpgsqlRange<DateTime>()", "{0}.ToString()", "NpgsqlRange<DateTime>", typeof(NpgsqlRange<DateTime>), typeof(NpgsqlRange<DateTime>?), "{0}", "GetString") },
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Date), ("(NpgsqlRange<DateTime>?)", "{0}.ToNpgsqlRange<DateTime>()", "{0}.ToString()", "NpgsqlRange<DateTime>", typeof(NpgsqlRange<DateTime>), typeof(NpgsqlRange<DateTime>?), "{0}", "GetString") },
{ (int)NpgsqlDbType.Hstore, ("(Dictionary<string, string>)", "JsonConvert.DeserializeObject<Dictionary<string, string>>({0})", "JsonConvert.SerializeObject({0})", "Dictionary<string, string>", typeof(Dictionary<string, string>), typeof(Dictionary<string, string>), "{0}", "GetValue") },
{ (int)NpgsqlDbType.Geometry, ("(PostgisGeometry)", "JsonConvert.DeserializeObject<PostgisGeometry>({0})", "JsonConvert.SerializeObject({0})", "PostgisGeometry", typeof(PostgisGeometry), typeof(PostgisGeometry), "{0}", "GetValue") },
/*** array ***/
{ (int)(NpgsqlDbType.Smallint | NpgsqlDbType.Array), ("(short[])", "JsonConvert.DeserializeObject<short[]>({0})", "JsonConvert.SerializeObject({0})", "short[]", typeof(short[]), typeof(short[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Integer | NpgsqlDbType.Array), ("(int[])", "JsonConvert.DeserializeObject<int[]>({0})", "JsonConvert.SerializeObject({0})", "int[]", typeof(int[]), typeof(int[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Bigint | NpgsqlDbType.Array), ("(long[])", "JsonConvert.DeserializeObject<long[]>({0})", "JsonConvert.SerializeObject({0})", "long[]", typeof(long[]), typeof(long[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Numeric | NpgsqlDbType.Array), ("(decimal[])", "JsonConvert.DeserializeObject<decimal[]>({0})", "JsonConvert.SerializeObject({0})", "decimal[]", typeof(decimal[]), typeof(decimal[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Real | NpgsqlDbType.Array), ("(float[])", "JsonConvert.DeserializeObject<float[]>({0})", "JsonConvert.SerializeObject({0})", "float[]", typeof(float[]), typeof(float[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Double | NpgsqlDbType.Array), ("(double[])", "JsonConvert.DeserializeObject<double[]>({0})", "JsonConvert.SerializeObject({0})", "double[]", typeof(double[]), typeof(double[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Money | NpgsqlDbType.Array), ("(decimal[])", "JsonConvert.DeserializeObject<decimal[]>({0})", "JsonConvert.SerializeObject({0})", "decimal[]", typeof(decimal[]), typeof(decimal[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Char | NpgsqlDbType.Array), ("(string[])", "JsonConvert.DeserializeObject<string[]>({0})", "JsonConvert.SerializeObject({0})", "string[]", typeof(string[]), typeof(string[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Varchar | NpgsqlDbType.Array), ("(string[])", "JsonConvert.DeserializeObject<string[]>({0})", "JsonConvert.SerializeObject({0})", "string[]", typeof(string[]), typeof(string[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Text | NpgsqlDbType.Array), ("(string[])", "JsonConvert.DeserializeObject<string[]>({0})", "JsonConvert.SerializeObject({0})", "string[]", typeof(string[]), typeof(string[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Timestamp | NpgsqlDbType.Array), ("(DateTime[])", "JsonConvert.DeserializeObject<DateTime[]>({0})", "JsonConvert.SerializeObject({0})", "DateTime[]", typeof(DateTime[]), typeof(DateTime[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.TimestampTz | NpgsqlDbType.Array), ("(DateTime[])", "JsonConvert.DeserializeObject<DateTime[]>({0})", "JsonConvert.SerializeObject({0})", "DateTime[]", typeof(DateTime[]), typeof(DateTime[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Date | NpgsqlDbType.Array), ("(DateTime[])", "JsonConvert.DeserializeObject<DateTime[]>({0})", "JsonConvert.SerializeObject({0})", "DateTime[]", typeof(DateTime[]), typeof(DateTime[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Time | NpgsqlDbType.Array), ("(TimeSpan[])", "JsonConvert.DeserializeObject<TimeSpan[]>({0})", "JsonConvert.SerializeObject({0})", "TimeSpan[]", typeof(TimeSpan[]), typeof(TimeSpan[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.TimeTz | NpgsqlDbType.Array), ("(TimeSpan[])", "JsonConvert.DeserializeObject<TimeSpan[]>({0})", "JsonConvert.SerializeObject({0})", "TimeSpan[]", typeof(TimeSpan[]), typeof(TimeSpan[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Interval | NpgsqlDbType.Array), ("(TimeSpan[])", "JsonConvert.DeserializeObject<TimeSpan[]>({0})", "JsonConvert.SerializeObject({0})", "TimeSpan[]", typeof(TimeSpan[]), typeof(TimeSpan[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Boolean | NpgsqlDbType.Array), ("(bool[])", "JsonConvert.DeserializeObject<bool[]>({0})", "JsonConvert.SerializeObject({0})", "bool[]", typeof(bool[]), typeof(bool[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Bytea | NpgsqlDbType.Array), ("(byte[][])", "JsonConvert.DeserializeObject<byte[][]>({0})", "JsonConvert.SerializeObject({0})", "byte[][]", typeof(byte[][]), typeof(byte[][]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Bit | NpgsqlDbType.Array), ("(BitArray[])", "JsonConvert.DeserializeObject<BitArray[]>({0})", "JsonConvert.SerializeObject({0})", "BitArray[]", typeof(BitArray[]), typeof(BitArray[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Varbit | NpgsqlDbType.Array), ("(BitArray[])", "JsonConvert.DeserializeObject<BitArray[]>({0})", "JsonConvert.SerializeObject({0})", "BitArray[]", typeof(BitArray[]), typeof(BitArray[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Point | NpgsqlDbType.Array), ("(NpgsqlPoint[])", "JsonConvert.DeserializeObject<NpgsqlPoint[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlPoint[]", typeof(NpgsqlPoint[]), typeof(NpgsqlPoint[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Line | NpgsqlDbType.Array), ("(NpgsqlLine[])", "JsonConvert.DeserializeObject<BNpgsqlLineitArray[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlLine[]", typeof(NpgsqlLine[]), typeof(NpgsqlLine[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.LSeg | NpgsqlDbType.Array), ("(NpgsqlLSeg[])", "JsonConvert.DeserializeObject<NpgsqlLSeg[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlLSeg[]", typeof(NpgsqlLSeg[]), typeof(NpgsqlLSeg[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Box | NpgsqlDbType.Array), ("(NpgsqlBox[])", "JsonConvert.DeserializeObject<NpgsqlBox[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlBox[]", typeof(NpgsqlBox[]), typeof(NpgsqlBox[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Path | NpgsqlDbType.Array), ("(NpgsqlPath[])", "JsonConvert.DeserializeObject<NpgsqlPath[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlPath[]", typeof(NpgsqlPath[]), typeof(NpgsqlPath[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Polygon | NpgsqlDbType.Array), ("(NpgsqlPolygon[])", "JsonConvert.DeserializeObject<NpgsqlPolygon[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlPolygon[]", typeof(NpgsqlPolygon[]), typeof(NpgsqlPolygon[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Circle | NpgsqlDbType.Array), ("(NpgsqlCircle[])", "JsonConvert.DeserializeObject<NpgsqlCircle[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlCircle[]", typeof(NpgsqlCircle[]), typeof(NpgsqlCircle[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Cidr | NpgsqlDbType.Array), ("((IPAddress, int)[])", "JsonConvert.DeserializeObject<(IPAddress, int)[]>({0})", "JsonConvert.SerializeObject({0})", "(IPAddress, int)[]", typeof((IPAddress, int)[]), typeof((IPAddress, int)[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Inet | NpgsqlDbType.Array), ("(IPAddress[])", "JsonConvert.DeserializeObject<IPAddress[]>({0})", "JsonConvert.SerializeObject({0})", "IPAddress[]", typeof(IPAddress[]), typeof(IPAddress[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.MacAddr | NpgsqlDbType.Array), ("(PhysicalAddress[])", "JsonConvert.DeserializeObject<PhysicalAddress[]>({0})", "JsonConvert.SerializeObject({0})", "PhysicalAddress[]", typeof(PhysicalAddress[]), typeof(PhysicalAddress[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Json | NpgsqlDbType.Array), ("(JToken[])", "JsonConvert.DeserializeObject<JToken[]>({0})", "JsonConvert.SerializeObject({0})", "JToken[]", typeof(JToken[]), typeof(JToken[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Jsonb | NpgsqlDbType.Array), ("(JToken[])", "JsonConvert.DeserializeObject<JToken[]>({0})", "JsonConvert.SerializeObject({0})", "JToken[]", typeof(JToken[]), typeof(JToken[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Uuid | NpgsqlDbType.Array), ("(Guid[])", "JsonConvert.DeserializeObject<Guid[]>({0})", "JsonConvert.SerializeObject({0})", "Guid[]", typeof(Guid[]), typeof(Guid[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Integer | NpgsqlDbType.Array), ("(NpgsqlRange<int>[])", "JsonConvert.DeserializeObject<NpgsqlRange<int>[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlRange<int>[]", typeof(NpgsqlRange<int>[]), typeof(NpgsqlRange<int>[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Bigint | NpgsqlDbType.Array), ("(NpgsqlRange<long>[])", "JsonConvert.DeserializeObject<NpgsqlRange<long>[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlRange<long>[]", typeof(NpgsqlRange<long>[]), typeof(NpgsqlRange<long>[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Numeric | NpgsqlDbType.Array), ("(NpgsqlRange<decimal>[])", "JsonConvert.DeserializeObject<NpgsqlRange<decimal>[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlRange<decimal>[]", typeof(NpgsqlRange<decimal>[]), typeof(NpgsqlRange<decimal>[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Timestamp | NpgsqlDbType.Array), ("(NpgsqlRange<DateTime>[])", "JsonConvert.DeserializeObject<NpgsqlRange<DateTime>[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlRange<DateTime>[]", typeof(NpgsqlRange<DateTime>[]), typeof(NpgsqlRange<DateTime>[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.TimestampTz | NpgsqlDbType.Array), ("(NpgsqlRange<DateTime>[])", "JsonConvert.DeserializeObject<NpgsqlRange<DateTime>[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlRange<DateTime>[]", typeof(NpgsqlRange<DateTime>[]), typeof(NpgsqlRange<DateTime>[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Date | NpgsqlDbType.Array), ("(NpgsqlRange<DateTime>[])", "JsonConvert.DeserializeObject<NpgsqlRange<DateTime>[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlRange<DateTime>[]", typeof(NpgsqlRange<DateTime>[]), typeof(NpgsqlRange<DateTime>[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Hstore | NpgsqlDbType.Array), ("(Dictionary<string, string>[])", "JsonConvert.DeserializeObject<Dictionary<string, string>[]>({0})", "JsonConvert.SerializeObject({0})", "Dictionary<string, string>[]", typeof(Dictionary<string, string>[]), typeof(Dictionary<string, string>[]), "{0}", "GetValue") },
{ (int)(NpgsqlDbType.Geometry | NpgsqlDbType.Array), ("(PostgisGeometry[])", "JsonConvert.DeserializeObject<PostgisGeometry[]>({0})", "JsonConvert.SerializeObject({0})", "PostgisGeometry[]", typeof(PostgisGeometry[]), typeof(PostgisGeometry[]), "{0}", "GetValue") },
};
public string GetCsConvert(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? (column.IsNullable ? trydc.csConvert : trydc.csConvert.Replace("?", "")) : null;
public string GetCsParse(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csParse : null;
public string GetCsStringify(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csStringify : null;
public string GetCsType(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? (column.IsNullable ? trydc.csType : trydc.csType.Replace("?", "")) : null;
public Type GetCsTypeInfo(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csTypeInfo : null;
public string GetCsTypeValue(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csTypeValue : null;
public string GetDataReaderMethod(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.dataReaderMethod : null;
public List<string> GetDatabases() {
var sql = @" select datname from pg_database where datname not in ('template1', 'template0')";
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList();
}
public List<DbTableInfo> GetTablesByDatabase(params string[] database) {
var olddatabase = "";
using (var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5))) {
olddatabase = conn.Value.Database;
}
var dbs = database == null || database.Any() == false ? new[] { olddatabase } : database;
var tables = new List<DbTableInfo>();
foreach (var db in dbs) {
if (string.IsNullOrEmpty(db) || string.Compare(db, olddatabase, true) != 0) continue;
var loc1 = new List<DbTableInfo>();
var loc2 = new Dictionary<string, DbTableInfo>();
var loc3 = new Dictionary<string, Dictionary<string, DbColumnInfo>>();
var sql = $@"
select
b.nspname || '.' || a.tablename,
a.schemaname,
a.tablename ,
d.description,
'TABLE'
from pg_tables a
inner join pg_namespace b on b.nspname = a.schemaname
inner join pg_class c on c.relnamespace = b.oid and c.relname = a.tablename
left join pg_description d on d.objoid = c.oid and objsubid = 0
where a.schemaname not in ('pg_catalog', 'information_schema', 'topology')
and b.nspname || '.' || a.tablename not in ('public.spatial_ref_sys')
union all
select
b.nspname || '.' || a.relname,
b.nspname,
a.relname,
d.description,
'VIEW'
from pg_class a
inner join pg_namespace b on b.oid = a.relnamespace
left join pg_description d on d.objoid = a.oid and objsubid = 0
where b.nspname not in ('pg_catalog', 'information_schema') and a.relkind in ('m','v')
and b.nspname || '.' || a.relname not in ('public.geography_columns','public.geometry_columns','public.raster_columns','public.raster_overviews')
";
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var loc6 = new List<string>();
var loc66 = new List<string>();
foreach (object[] row in ds) {
var object_id = string.Concat(row[0]);
var owner = string.Concat(row[1]);
var table = string.Concat(row[2]);
var comment = string.Concat(row[3]);
Enum.TryParse<DbTableType>(string.Concat(row[4]), out var type);
loc2.Add(object_id, new DbTableInfo { Id = object_id.ToString(), Schema = owner, Name = table, Comment = comment, Type = type });
loc3.Add(object_id, new Dictionary<string, DbColumnInfo>());
switch (type) {
case DbTableType.VIEW:
case DbTableType.TABLE:
loc6.Add(object_id);
break;
case DbTableType.StoreProcedure:
loc66.Add(object_id);
break;
}
}
if (loc6.Count == 0) return loc1;
string loc8 = "'" + string.Join("','", loc6.ToArray()) + "'";
string loc88 = "'" + string.Join("','", loc66.ToArray()) + "'";
sql = $@"
select
ns.nspname || '.' || c.relname as id,
a.attname,
t.typname,
case when a.atttypmod > 0 and a.atttypmod < 32767 then a.atttypmod - 4 else a.attlen end len,
case when t.typelem = 0 then t.typname else t2.typname end,
case when a.attnotnull then 0 else 1 end as is_nullable,
e.adsrc as is_identity,
--case when e.adsrc = 'nextval(''' || case when ns.nspname = 'public' then '' else ns.nspname || '.' end || c.relname || '_' || a.attname || '_seq''::regclass)' then 1 else 0 end as is_identity,
d.description as comment,
a.attndims,
case when t.typelem = 0 then t.typtype else t2.typtype end,
ns2.nspname,
a.attnum
from pg_class c
inner join pg_attribute a on a.attnum > 0 and a.attrelid = c.oid
inner join pg_type t on t.oid = a.atttypid
left join pg_type t2 on t2.oid = t.typelem
left join pg_description d on d.objoid = a.attrelid and d.objsubid = a.attnum
left join pg_attrdef e on e.adrelid = a.attrelid and e.adnum = a.attnum
inner join pg_namespace ns on ns.oid = c.relnamespace
inner join pg_namespace ns2 on ns2.oid = t.typnamespace
where ns.nspname || '.' || c.relname in ({loc8})";
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
foreach (object[] row in ds) {
var object_id = string.Concat(row[0]);
var column = string.Concat(row[1]);
var type = string.Concat(row[2]);
var max_length = int.Parse(string.Concat(row[3]));
var sqlType = string.Concat(row[4]);
var is_nullable = string.Concat(row[5]) == "1";
var is_identity = string.Concat(row[6]).StartsWith(@"nextval('") && string.Concat(row[6]).EndsWith(@"'::regclass)");
var comment = string.Concat(row[7]);
int attndims = int.Parse(string.Concat(row[8]));
string typtype = string.Concat(row[9]);
string owner = string.Concat(row[10]);
int attnum = int.Parse(string.Concat(row[11]));
switch (sqlType.ToLower()) {
case "bool": case "name": case "bit": case "varbit": case "bpchar": case "varchar": case "bytea": case "text": case "uuid": break;
default: max_length *= 8; break;
}
if (max_length <= 0) max_length = -1;
if (type.StartsWith("_")) {
type = type.Substring(1);
if (attndims == 0) attndims++;
}
if (sqlType.StartsWith("_")) sqlType = sqlType.Substring(1);
loc3[object_id].Add(column, new DbColumnInfo {
Name = column,
MaxLength = max_length,
IsIdentity = is_identity,
IsNullable = is_nullable,
IsPrimary = false,
DbTypeText = type,
DbTypeTextFull = sqlType,
Table = loc2[object_id],
Coment = comment
});
loc3[object_id][column].DbType = this.GetDbType(loc3[object_id][column]);
loc3[object_id][column].CsType = this.GetCsTypeInfo(loc3[object_id][column]);
}
sql = $@"
select
ns.nspname || '.' || d.relname as table_id,
c.attname,
b.relname as index_id,
case when a.indisunique then 1 else 0 end IsUnique,
case when a.indisprimary then 1 else 0 end IsPrimary,
case when a.indisclustered then 0 else 1 end IsClustered,
0 IsDesc,
a.indkey::text,
c.attnum
from pg_index a
inner join pg_class b on b.oid = a.indexrelid
inner join pg_attribute c on c.attnum > 0 and c.attrelid = b.oid
inner join pg_namespace ns on ns.oid = b.relnamespace
inner join pg_class d on d.oid = a.indrelid
where ns.nspname || '.' || d.relname in ({loc8})
";
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var indexColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
var uniqueColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
foreach (object[] row in ds) {
var object_id = string.Concat(row[0]);
var column = string.Concat(row[1]);
var index_id = string.Concat(row[2]);
var is_unique = string.Concat(row[3]) == "1";
var is_primary_key = string.Concat(row[4]) == "1";
var is_clustered = string.Concat(row[5]) == "1";
var is_desc = int.Parse(string.Concat(row[6]));
var inkey = string.Concat(row[7]).Split(' ');
var attnum = int.Parse(string.Concat(row[8]));
attnum = int.Parse(inkey[attnum - 1]);
foreach (string tc in loc3[object_id].Keys) {
if (loc3[object_id][tc].DbTypeText.EndsWith("[]")) {
column = tc;
break;
}
}
if (loc3.ContainsKey(object_id) == false || loc3[object_id].ContainsKey(column) == false) continue;
var loc9 = loc3[object_id][column];
if (loc9.IsPrimary == false && is_primary_key) loc9.IsPrimary = is_primary_key;
Dictionary<string, List<DbColumnInfo>> loc10 = null;
List<DbColumnInfo> loc11 = null;
if (!indexColumns.TryGetValue(object_id, out loc10))
indexColumns.Add(object_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
if (!loc10.TryGetValue(index_id, out loc11))
loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
loc11.Add(loc9);
if (is_unique && !is_primary_key) {
if (!uniqueColumns.TryGetValue(object_id, out loc10))
uniqueColumns.Add(object_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
if (!loc10.TryGetValue(index_id, out loc11))
loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
loc11.Add(loc9);
}
}
foreach (var object_id in indexColumns.Keys) {
foreach (var column in indexColumns[object_id])
loc2[object_id].IndexesDict.Add(column.Key, column.Value);
}
foreach (var object_id in uniqueColumns.Keys) {
foreach (var column in uniqueColumns[object_id]) {
column.Value.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
loc2[object_id].UniquesDict.Add(column.Key, column.Value);
}
}
sql = $@"
select
ns.nspname || '.' || b.relname as table_id,
array(select attname from pg_attribute where attrelid = a.conrelid and attnum = any(a.conkey)) as column_name,
a.conname as FKId,
ns2.nspname || '.' || c.relname as ref_table_id,
1 as IsForeignKey,
array(select attname from pg_attribute where attrelid = a.confrelid and attnum = any(a.confkey)) as ref_column,
null ref_sln,
null ref_table
from pg_constraint a
inner join pg_class b on b.oid = a.conrelid
inner join pg_class c on c.oid = a.confrelid
inner join pg_namespace ns on ns.oid = b.relnamespace
inner join pg_namespace ns2 on ns2.oid = c.relnamespace
where ns.nspname || '.' || b.relname in ({loc8})
";
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var fkColumns = new Dictionary<string, Dictionary<string, DbForeignInfo>>();
foreach (object[] row in ds) {
var table_id = string.Concat(row[0]);
var column = row[1] as string[];
var fk_id = string.Concat(row[2]);
var ref_table_id = string.Concat(row[3]);
var is_foreign_key = string.Concat(row[4]) == "1";
var referenced_column = row[5] as string[];
var referenced_db = string.Concat(row[6]);
var referenced_table = string.Concat(row[7]);
if (loc2.ContainsKey(ref_table_id) == false) continue;
Dictionary<string, DbForeignInfo> loc12 = null;
DbForeignInfo loc13 = null;
if (!fkColumns.TryGetValue(table_id, out loc12))
fkColumns.Add(table_id, loc12 = new Dictionary<string, DbForeignInfo>());
if (!loc12.TryGetValue(fk_id, out loc13))
loc12.Add(fk_id, loc13 = new DbForeignInfo { Table = loc2[table_id], ReferencedTable = loc2[ref_table_id] });
for (int a = 0; a < column.Length; a++) {
loc13.Columns.Add(loc3[table_id][column[a]]);
loc13.ReferencedColumns.Add(loc3[ref_table_id][referenced_column[a]]);
}
}
foreach (var table_id in fkColumns.Keys)
foreach (var fk in fkColumns[table_id])
loc2[table_id].ForeignsDict.Add(fk.Key, fk.Value);
foreach (var table_id in loc3.Keys) {
foreach (var loc5 in loc3[table_id].Values) {
loc2[table_id].Columns.Add(loc5);
if (loc5.IsIdentity) loc2[table_id].Identitys.Add(loc5);
if (loc5.IsPrimary) loc2[table_id].Primarys.Add(loc5);
}
}
foreach (var loc4 in loc2.Values) {
if (loc4.Primarys.Count == 0 && loc4.UniquesDict.Count > 0) {
foreach (var loc5 in loc4.UniquesDict.First().Value) {
loc5.IsPrimary = true;
loc4.Primarys.Add(loc5);
}
}
loc4.Primarys.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
loc4.Columns.Sort((c1, c2) => {
int compare = c2.IsPrimary.CompareTo(c1.IsPrimary);
if (compare == 0) {
bool b1 = loc4.ForeignsDict.Values.Where(fk => fk.Columns.Where(c3 => c3.Name == c1.Name).Any()).Any();
bool b2 = loc4.ForeignsDict.Values.Where(fk => fk.Columns.Where(c3 => c3.Name == c2.Name).Any()).Any();
compare = b2.CompareTo(b1);
}
if (compare == 0) compare = c1.Name.CompareTo(c2.Name);
return compare;
});
loc1.Add(loc4);
}
loc1.Sort((t1, t2) => {
var ret = t1.Schema.CompareTo(t2.Schema);
if (ret == 0) ret = t1.Name.CompareTo(t2.Name);
return ret;
});
loc2.Clear();
loc3.Clear();
tables.AddRange(loc1);
}
return tables;
}
public List<DbEnumInfo> GetEnumsByDatabase(params string[] database) {
if (database == null || database.Length == 0) return new List<DbEnumInfo>();
var drs = _orm.Ado.Query<(string name, string label)>(CommandType.Text, _commonUtils.FormatSql(@"
select
ns.nspname || '.' || a.typname,
b.enumlabel
from pg_type a
inner join pg_enum b on b.enumtypid = a.oid
inner join pg_namespace ns on ns.oid = a.typnamespace
where a.typtype = 'e' and ns.nspname in (SELECT ""schema_name"" FROM information_schema.schemata where catalog_name in {0})", database));
var ret = new Dictionary<string, Dictionary<string, string>>();
foreach (var dr in drs) {
if (ret.TryGetValue(dr.name, out var labels) == false) ret.Add(dr.name, labels = new Dictionary<string, string>());
var key = dr.label;
if (Regex.IsMatch(key, @"^[\u0391-\uFFE5a-zA-Z_\$][\u0391-\uFFE5a-zA-Z_\$\d]*$") == false)
key = $"Unkown{ret[dr.name].Count + 1}";
if (labels.ContainsKey(key) == false) labels.Add(key, dr.label);
}
return ret.Select(a => new DbEnumInfo { Name = a.Key, Labels = a.Value }).ToList();
}
}
}

View File

@ -1,498 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace FreeSql.PostgreSQL {
class PostgreSQLExpression : CommonExpression {
public PostgreSQLExpression(CommonUtils common) : base(common) { }
internal override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
switch (exp.NodeType) {
case ExpressionType.Convert:
var operandExp = (exp as UnaryExpression)?.Operand;
var gentype = exp.Type.NullableTypeOrThis();
if (gentype != operandExp.Type.NullableTypeOrThis()) {
switch (exp.Type.NullableTypeOrThis().ToString()) {
case "System.Boolean": return $"(({getExp(operandExp)})::varchar not in ('0','false','f','no'))";
case "System.Byte": return $"({getExp(operandExp)})::int2";
case "System.Char": return $"substr(({getExp(operandExp)})::char, 1, 1)";
case "System.DateTime": return $"({getExp(operandExp)})::timestamp";
case "System.Decimal": return $"({getExp(operandExp)})::numeric";
case "System.Double": return $"({getExp(operandExp)})::float8";
case "System.Int16": return $"({getExp(operandExp)})::int2";
case "System.Int32": return $"({getExp(operandExp)})::int4";
case "System.Int64": return $"({getExp(operandExp)})::int8";
case "System.SByte": return $"({getExp(operandExp)})::int2";
case "System.Single": return $"({getExp(operandExp)})::float4";
case "System.String": return $"({getExp(operandExp)})::varchar";
case "System.UInt16": return $"({getExp(operandExp)})::int2";
case "System.UInt32": return $"({getExp(operandExp)})::int4";
case "System.UInt64": return $"({getExp(operandExp)})::int8";
case "System.Guid": return $"({getExp(operandExp)})::uuid";
}
}
break;
case ExpressionType.ArrayLength:
var arrOperExp = getExp((exp as UnaryExpression).Operand);
if (arrOperExp.StartsWith("(") || arrOperExp.EndsWith(")")) return $"array_length(array[{arrOperExp.TrimStart('(').TrimEnd(')')}],1)";
return $"case when {arrOperExp} is null then 0 else array_length({arrOperExp},1) end";
case ExpressionType.Call:
var callExp = exp as MethodCallExpression;
switch (callExp.Method.Name) {
case "Parse":
case "TryParse":
switch (callExp.Method.DeclaringType.NullableTypeOrThis().ToString()) {
case "System.Boolean": return $"(({getExp(callExp.Arguments[0])})::varchar not in ('0','false','f','no'))";
case "System.Byte": return $"({getExp(callExp.Arguments[0])})::int2";
case "System.Char": return $"substr(({getExp(callExp.Arguments[0])})::char, 1, 1)";
case "System.DateTime": return $"({getExp(callExp.Arguments[0])})::timestamp";
case "System.Decimal": return $"({getExp(callExp.Arguments[0])})::numeric";
case "System.Double": return $"({getExp(callExp.Arguments[0])})::float8";
case "System.Int16": return $"({getExp(callExp.Arguments[0])})::int2";
case "System.Int32": return $"({getExp(callExp.Arguments[0])})::int4";
case "System.Int64": return $"({getExp(callExp.Arguments[0])})::int8";
case "System.SByte": return $"({getExp(callExp.Arguments[0])})::int2";
case "System.Single": return $"({getExp(callExp.Arguments[0])})::float4";
case "System.UInt16": return $"({getExp(callExp.Arguments[0])})::int2";
case "System.UInt32": return $"({getExp(callExp.Arguments[0])})::int4";
case "System.UInt64": return $"({getExp(callExp.Arguments[0])})::int8";
case "System.Guid": return $"({getExp(callExp.Arguments[0])})::uuid";
}
break;
case "NewGuid":
break;
case "Next":
if (callExp.Object?.Type == typeof(Random)) return "(random()*1000000000)::int4";
break;
case "NextDouble":
if (callExp.Object?.Type == typeof(Random)) return "random()";
break;
case "Random":
if (callExp.Method.DeclaringType.IsNumberType()) return "random()";
break;
case "ToString":
if (callExp.Object != null) return $"({getExp(callExp.Object)})::varchar";
break;
}
var objExp = callExp.Object;
var objType = objExp?.Type;
if (objType?.FullName == "System.Byte[]") return null;
var argIndex = 0;
if (objType == null && callExp.Method.DeclaringType == typeof(Enumerable)) {
objExp = callExp.Arguments.FirstOrDefault();
objType = objExp?.Type;
argIndex++;
}
if (objType == null) objType = callExp.Method.DeclaringType;
if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) {
var left = objExp == null ? null : getExp(objExp);
switch (objType.FullName) {
case "Newtonsoft.Json.Linq.JToken":
case "Newtonsoft.Json.Linq.JObject":
case "Newtonsoft.Json.Linq.JArray":
switch (callExp.Method.Name) {
case "Any": return $"(jsonb_array_length(coalesce({left},'[]')) > 0)";
case "Contains":
var json = getExp(callExp.Arguments[argIndex]);
if (objType == typeof(JArray))
return $"(coalesce({left},'[]') ? ({json})::varchar)";
if (json.StartsWith("'") && json.EndsWith("'"))
return $"(coalesce({left},'{{}}') @> {_common.FormatSql("{0}", JToken.Parse(json.Trim('\'')))})";
return $"(coalesce({left},'{{}}') @> ({json})::jsonb)";
case "ContainsKey": return $"(coalesce({left},'{{}}') ? {getExp(callExp.Arguments[argIndex])})";
case "Concat":
var right2 = getExp(callExp.Arguments[argIndex]);
return $"(coalesce({left},'{{}}') || {right2})";
case "LongCount":
case "Count": return $"jsonb_array_length(coalesce({left},'[]'))";
case "Parse":
var json2 = getExp(callExp.Arguments[argIndex]);
if (json2.StartsWith("'") && json2.EndsWith("'")) return _common.FormatSql("{0}", JToken.Parse(json2.Trim('\'')));
return $"({json2})::jsonb";
}
break;
}
if (objType.FullName == typeof(Dictionary<string, string>).FullName) {
switch (callExp.Method.Name) {
case "Contains":
var right = getExp(callExp.Arguments[argIndex]);
return $"({left} @> ({right}))";
case "ContainsKey": return $"({left} ? {getExp(callExp.Arguments[argIndex])})";
case "Concat": return $"({left} || {getExp(callExp.Arguments[argIndex])})";
case "GetLength":
case "GetLongLength":
case "Count": return $"case when {left} is null then 0 else array_length(akeys({left}),1) end";
case "Keys": return $"akeys({left})";
case "Values": return $"avals({left})";
}
}
switch (callExp.Method.Name) {
case "Any":
if (left.StartsWith("(") || left.EndsWith(")")) left = $"array[{left.TrimStart('(').TrimEnd(')')}]";
return $"(case when {left} is null then 0 else array_length({left},1) end > 0)";
case "Contains":
//判断 in 或 array @> array
var right1 = getExp(callExp.Arguments[argIndex]);
if (left.StartsWith("array[") || left.EndsWith("]"))
return $"{right1} in ({left.Substring(6, left.Length - 7)})";
if (left.StartsWith("(") || left.EndsWith(")"))
return $"{right1} in {left}";
if (right1.StartsWith("(") || right1.EndsWith(")")) right1 = $"array[{right1.TrimStart('(').TrimEnd(')')}]";
return $"({left} @> array[{right1}])";
case "Concat":
if (left.StartsWith("(") || left.EndsWith(")")) left = $"array[{left.TrimStart('(').TrimEnd(')')}]";
var right2 = getExp(callExp.Arguments[argIndex]);
if (right2.StartsWith("(") || right2.EndsWith(")")) right2 = $"array[{right2.TrimStart('(').TrimEnd(')')}]";
return $"({left} || {right2})";
case "GetLength":
case "GetLongLength":
case "Length":
case "Count":
if (left.StartsWith("(") || left.EndsWith(")")) left = $"array[{left.TrimStart('(').TrimEnd(')')}]";
return $"case when {left} is null then 0 else array_length({left},1) end";
}
}
break;
case ExpressionType.MemberAccess:
var memExp = exp as MemberExpression;
var memParentExp = memExp.Expression?.Type;
if (memParentExp?.FullName == "System.Byte[]") return null;
if (memParentExp != null) {
if (memParentExp.IsArray == true) {
var left = getExp(memExp.Expression);
if (left.StartsWith("(") || left.EndsWith(")")) left = $"array[{left.TrimStart('(').TrimEnd(')')}]";
switch (memExp.Member.Name) {
case "Length":
case "Count": return $"case when {left} is null then 0 else array_length({left},1) end";
}
}
switch (memParentExp.FullName) {
case "Newtonsoft.Json.Linq.JToken":
case "Newtonsoft.Json.Linq.JObject":
case "Newtonsoft.Json.Linq.JArray":
var left = getExp(memExp.Expression);
switch (memExp.Member.Name) {
case "Count": return $"jsonb_array_length(coalesce({left},'[]'))";
}
break;
}
if (memParentExp.FullName == typeof(Dictionary<string, string>).FullName) {
var left = getExp(memExp.Expression);
switch (memExp.Member.Name) {
case "Count": return $"case when {left} is null then 0 else array_length(akeys({left}),1) end";
case "Keys": return $"akeys({left})";
case "Values": return $"avals({left})";
}
}
}
break;
case ExpressionType.NewArrayInit:
var arrExp = exp as NewArrayExpression;
var arrSb = new StringBuilder();
arrSb.Append("array[");
for (var a = 0; a < arrExp.Expressions.Count; a++) {
if (a > 0) arrSb.Append(",");
arrSb.Append(getExp(arrExp.Expressions[a]));
}
if (arrSb.Length == 1) arrSb.Append("NULL");
return arrSb.Append("]").ToString();
case ExpressionType.ListInit:
var listExp = exp as ListInitExpression;
var listSb = new StringBuilder();
listSb.Append("(");
for (var a = 0; a < listExp.Initializers.Count; a++) {
if (listExp.Initializers[a].Arguments.Any() == false) continue;
if (a > 0) listSb.Append(",");
listSb.Append(getExp(listExp.Initializers[a].Arguments.FirstOrDefault()));
}
if (listSb.Length == 1) listSb.Append("NULL");
return listSb.Append(")").ToString();
case ExpressionType.New:
var newExp = exp as NewExpression;
if (typeof(IList).IsAssignableFrom(newExp.Type)) {
if (newExp.Arguments.Count == 0) return "(NULL)";
if (typeof(IEnumerable).IsAssignableFrom(newExp.Arguments[0].Type) == false) return "(NULL)";
return getExp(newExp.Arguments[0]);
}
return null;
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Empty": return "''";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Length": return $"char_length({left})";
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Now": return "current_timestamp";
case "UtcNow": return "(current_timestamp at time zone 'UTC')";
case "Today": return "current_date";
case "MinValue": return "'0001/1/1 0:00:00'::timestamp";
case "MaxValue": return "'9999/12/31 23:59:59'::timestamp";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Date": return $"({left})::date";
case "TimeOfDay": return $"(extract(epoch from ({left})::time)*1000000)";
case "DayOfWeek": return $"extract(dow from ({left})::timestamp)";
case "Day": return $"extract(day from ({left})::timestamp)";
case "DayOfYear": return $"extract(doy from ({left})::timestamp)";
case "Month": return $"extract(month from ({left})::timestamp)";
case "Year": return $"extract(year from ({left})::timestamp)";
case "Hour": return $"extract(hour from ({left})::timestamp)";
case "Minute": return $"extract(minute from ({left})::timestamp)";
case "Second": return $"extract(second from ({left})::timestamp)";
case "Millisecond": return $"(extract(milliseconds from ({left})::timestamp)-extract(second from ({left})::timestamp)*1000)";
case "Ticks": return $"(extract(epoch from ({left})::timestamp)*10000000+621355968000000000)";
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Zero": return "0";
case "MinValue": return "-922337203685477580"; //微秒 Ticks / 10
case "MaxValue": return "922337203685477580";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Days": return $"floor(({left})/{(long)1000000 * 60 * 60 * 24})";
case "Hours": return $"floor(({left})/{(long)1000000 * 60 * 60}%24)";
case "Milliseconds": return $"(floor(({left})/1000)::int8%1000)";
case "Minutes": return $"(floor(({left})/{(long)1000000 * 60})::int8%60)";
case "Seconds": return $"(floor(({left})/1000000)::int8%60)";
case "Ticks": return $"(({left})*10)";
case "TotalDays": return $"(({left})/{(long)1000000 * 60 * 60 * 24})";
case "TotalHours": return $"(({left})/{(long)1000000 * 60 * 60})";
case "TotalMilliseconds": return $"(({left})/1000)";
case "TotalMinutes": return $"(({left})/{(long)1000000 * 60})";
case "TotalSeconds": return $"(({left})/1000000)";
}
return null;
}
internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "IsNullOrEmpty":
var arg1 = getExp(exp.Arguments[0]);
return $"({arg1} is null or {arg1} = '')";
case "Concat":
return _common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), null);
}
} else {
var left = getExp(exp.Object);
switch (exp.Method.Name) {
case "StartsWith":
case "EndsWith":
case "Contains":
var args0Value = getExp(exp.Arguments[0]);
if (args0Value == "NULL") return $"({left}) IS NULL";
var likeOpt = "LIKE";
if (exp.Arguments.Count > 1) {
if (exp.Arguments[1].Type == typeof(bool) ||
exp.Arguments[1].Type == typeof(StringComparison) && getExp(exp.Arguments[0]).Contains("IgnoreCase")) likeOpt = "ILIKE";
}
if (exp.Method.Name == "StartsWith") return $"({left}) {likeOpt} {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(({args0Value})::varchar || '%')")}";
if (exp.Method.Name == "EndsWith") return $"({left}) {likeOpt} {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%' || ({args0Value})::varchar)")}";
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) {likeOpt} {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
return $"({left}) {likeOpt} ('%' || ({args0Value})::varchar || '%')";
case "ToLower": return $"lower({left})";
case "ToUpper": return $"upper({left})";
case "Substring":
var substrArgs1 = getExp(exp.Arguments[0]);
if (long.TryParse(substrArgs1, out var testtrylng1)) substrArgs1 = (testtrylng1 + 1).ToString();
else substrArgs1 += "+1";
if (exp.Arguments.Count == 1) return $"substr({left}, {substrArgs1})";
return $"substr({left}, {substrArgs1}, {getExp(exp.Arguments[1])})";
case "IndexOf": return $"(strpos({left}, {getExp(exp.Arguments[0])})-1)";
case "PadLeft":
if (exp.Arguments.Count == 1) return $"lpad({left}, {getExp(exp.Arguments[0])})";
return $"lpad({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "PadRight":
if (exp.Arguments.Count == 1) return $"rpad({left}, {getExp(exp.Arguments[0])})";
return $"rpad({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "Trim":
case "TrimStart":
case "TrimEnd":
if (exp.Arguments.Count == 0) {
if (exp.Method.Name == "Trim") return $"trim({left})";
if (exp.Method.Name == "TrimStart") return $"ltrim({left})";
if (exp.Method.Name == "TrimEnd") return $"rtrim({left})";
}
var trimArg1 = "";
var trimArg2 = "";
foreach (var argsTrim02 in exp.Arguments) {
var argsTrim01s = new[] { argsTrim02 };
if (argsTrim02.NodeType == ExpressionType.NewArrayInit) {
var arritem = argsTrim02 as NewArrayExpression;
argsTrim01s = arritem.Expressions.ToArray();
}
foreach (var argsTrim01 in argsTrim01s) {
var trimChr = getExp(argsTrim01).Trim('\'');
if (trimChr.Length == 1) trimArg1 += trimChr;
else trimArg2 += $" || ({trimChr})";
}
}
if (exp.Method.Name == "Trim") left = $"trim({left}, {_common.FormatSql("{0}", trimArg1)}{trimArg2})";
if (exp.Method.Name == "TrimStart") left = $"ltrim({left}, {_common.FormatSql("{0}", trimArg1)}{trimArg2})";
if (exp.Method.Name == "TrimEnd") left = $"rtrim({left}, {_common.FormatSql("{0}", trimArg1)}{trimArg2})";
return left;
case "Replace": return $"replace({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "CompareTo": return $"case when {left} = {getExp(exp.Arguments[0])} then 0 when {left} > {getExp(exp.Arguments[0])} then 1 else -1 end";
case "Equals": return $"({left} = ({getExp(exp.Arguments[0])})::varchar)";
}
}
throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
switch (exp.Method.Name) {
case "Abs": return $"abs({getExp(exp.Arguments[0])})";
case "Sign": return $"sign({getExp(exp.Arguments[0])})";
case "Floor": return $"floor({getExp(exp.Arguments[0])})";
case "Ceiling": return $"ceiling({getExp(exp.Arguments[0])})";
case "Round":
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"round({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
return $"round({getExp(exp.Arguments[0])})";
case "Exp": return $"exp({getExp(exp.Arguments[0])})";
case "Log": return $"log({getExp(exp.Arguments[0])})";
case "Log10": return $"log10({getExp(exp.Arguments[0])})";
case "Pow": return $"pow({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "Sqrt": return $"sqrt({getExp(exp.Arguments[0])})";
case "Cos": return $"cos({getExp(exp.Arguments[0])})";
case "Sin": return $"sin({getExp(exp.Arguments[0])})";
case "Tan": return $"tan({getExp(exp.Arguments[0])})";
case "Acos": return $"acos({getExp(exp.Arguments[0])})";
case "Asin": return $"asin({getExp(exp.Arguments[0])})";
case "Atan": return $"atan({getExp(exp.Arguments[0])})";
case "Atan2": return $"atan2({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "Truncate": return $"trunc({getExp(exp.Arguments[0])}, 0)";
}
throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "Compare": return $"extract(epoch from ({getExp(exp.Arguments[0])})::timestamp-({getExp(exp.Arguments[1])})::timestamp)";
case "DaysInMonth": return $"extract(day from ({getExp(exp.Arguments[0])} || '-' || {getExp(exp.Arguments[1])} || '-01')::timestamp+'1 month'::interval-'1 day'::interval)";
case "Equals": return $"(({getExp(exp.Arguments[0])})::timestamp = ({getExp(exp.Arguments[1])})::timestamp)";
case "IsLeapYear":
var isLeapYearArgs1 = getExp(exp.Arguments[0]);
return $"(({isLeapYearArgs1})::int8%4=0 AND ({isLeapYearArgs1})::int8%100<>0 OR ({isLeapYearArgs1})::int8%400=0)";
case "Parse": return $"({getExp(exp.Arguments[0])})::timestamp";
case "ParseExact":
case "TryParse":
case "TryParseExact": return $"({getExp(exp.Arguments[0])})::timestamp";
}
} else {
var left = getExp(exp.Object);
var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]);
switch (exp.Method.Name) {
case "Add": return $"(({left})::timestamp+(({args1})||' microseconds')::interval)";
case "AddDays": return $"(({left})::timestamp+(({args1})||' day')::interval)";
case "AddHours": return $"(({left})::timestamp+(({args1})||' hour')::interval)";
case "AddMilliseconds": return $"(({left})::timestamp+(({args1})||' milliseconds')::interval)";
case "AddMinutes": return $"(({left})::timestamp+(({args1})||' minute')::interval)";
case "AddMonths": return $"(({left})::timestamp+(({args1})||' month')::interval)";
case "AddSeconds": return $"(({left})::timestamp+(({args1})||' second')::interval)";
case "AddTicks": return $"(({left})::timestamp+(({args1})/10||' microseconds')::interval)";
case "AddYears": return $"(({left})::timestamp+(({args1})||' year')::interval)";
case "Subtract":
switch ((exp.Arguments[0].Type.IsNullableType() ? exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault() : exp.Arguments[0].Type).FullName) {
case "System.DateTime": return $"(extract(epoch from ({left})::timestamp-({args1})::timestamp)*1000000)";
case "System.TimeSpan": return $"(({left})::timestamp-(({args1})||' microseconds')::interval)";
}
break;
case "Equals": return $"({left} = ({getExp(exp.Arguments[0])})::timestamp)";
case "CompareTo": return $"extract(epoch from ({left})::timestamp-({getExp(exp.Arguments[0])})::timestamp)";
case "ToString": return $"to_char({left}, 'YYYY-MM-DD HH24:MI:SS.US')";
}
}
throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "Compare": return $"({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])}))";
case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})";
case "FromDays": return $"(({getExp(exp.Arguments[0])})*{(long)1000000 * 60 * 60 * 24})";
case "FromHours": return $"(({getExp(exp.Arguments[0])})*{(long)1000000 * 60 * 60})";
case "FromMilliseconds": return $"(({getExp(exp.Arguments[0])})*1000)";
case "FromMinutes": return $"(({getExp(exp.Arguments[0])})*{(long)1000000 * 60})";
case "FromSeconds": return $"(({getExp(exp.Arguments[0])})*1000000)";
case "FromTicks": return $"(({getExp(exp.Arguments[0])})/10)";
case "Parse": return $"({getExp(exp.Arguments[0])})::int8";
case "ParseExact":
case "TryParse":
case "TryParseExact": return $"({getExp(exp.Arguments[0])})::int8";
}
} else {
var left = getExp(exp.Object);
var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]);
switch (exp.Method.Name) {
case "Add": return $"({left}+{args1})";
case "Subtract": return $"({left}-({args1}))";
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
case "CompareTo": return $"({left}-({getExp(exp.Arguments[0])}))";
case "ToString": return $"({left})::varchar";
}
}
throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "ToBoolean": return $"(({getExp(exp.Arguments[0])})::varchar not in ('0','false','f','no'))";
case "ToByte": return $"({getExp(exp.Arguments[0])})::int2";
case "ToChar": return $"substr(({getExp(exp.Arguments[0])})::char, 1, 1)";
case "ToDateTime": return $"({getExp(exp.Arguments[0])})::timestamp";
case "ToDecimal": return $"({getExp(exp.Arguments[0])})::numeric";
case "ToDouble": return $"({getExp(exp.Arguments[0])})::float8";
case "ToInt16": return $"({getExp(exp.Arguments[0])})::int2";
case "ToInt32": return $"({getExp(exp.Arguments[0])})::int4";
case "ToInt64": return $"({getExp(exp.Arguments[0])})::int8";
case "ToSByte": return $"({getExp(exp.Arguments[0])})::int2";
case "ToSingle": return $"({getExp(exp.Arguments[0])})::float4";
case "ToString": return $"({getExp(exp.Arguments[0])})::varchar";
case "ToUInt16": return $"({getExp(exp.Arguments[0])})::int2";
case "ToUInt32": return $"({getExp(exp.Arguments[0])})::int4";
case "ToUInt64": return $"({getExp(exp.Arguments[0])})::int8";
}
}
throw new Exception($"PostgreSQLExpression 未实现函数表达式 {exp} 解析");
}
}
}

View File

@ -1,11 +0,0 @@
public static partial class FreeSqlGlobalExtensions {
/// <summary>
/// 特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换
/// </summary>
/// <param name="that"></param>
/// <param name="args"></param>
/// <returns></returns>
public static string FormatPostgreSQL(this string that, params object[] args) => _postgresqlAdo.Addslashes(that, args);
static FreeSql.PostgreSQL.PostgreSQLAdo _postgresqlAdo = new FreeSql.PostgreSQL.PostgreSQLAdo();
}

View File

@ -1,98 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.CommonProvider;
using FreeSql.PostgreSQL.Curd;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using Npgsql.LegacyPostgis;
using NpgsqlTypes;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.Net;
using System.Net.NetworkInformation;
namespace FreeSql.PostgreSQL {
class PostgreSQLProvider<TMark> : IFreeSql<TMark> {
static PostgreSQLProvider() {
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(BitArray)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlPoint)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlLine)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlLSeg)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlBox)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlPath)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlPolygon)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlCircle)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof((IPAddress Address, int Subnet))] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(IPAddress)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PhysicalAddress)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlRange<int>)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlRange<long>)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlRange<decimal>)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlRange<DateTime>)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisPoint)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisLineString)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisPolygon)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisMultiPoint)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisMultiLineString)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisMultiPolygon)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisGeometry)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisGeometryCollection)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(Dictionary<string, string>)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(JToken)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(JObject)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(JArray)] = true;
}
public ISelect<T1> Select<T1>() where T1 : class => new PostgreSQLSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public ISelect<T1> Select<T1>(object dywhere) where T1 : class => new PostgreSQLSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsert<T1> Insert<T1>() where T1 : class => new PostgreSQLInsert<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IInsert<T1> Insert<T1>(T1 source) where T1 : class => this.Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(T1[] source) where T1 : class => this.Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(IEnumerable<T1> source) where T1 : class => this.Insert<T1>().AppendData(source);
public IUpdate<T1> Update<T1>() where T1 : class => new PostgreSQLUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new PostgreSQLUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new PostgreSQLDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new PostgreSQLDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IAdo Ado { get; }
public IAop Aop { get; }
public ICache Cache { get; }
public ICodeFirst CodeFirst { get; }
public IDbFirst DbFirst { get; }
public PostgreSQLProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) {
if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.PostgreSQL");
this.InternalCommonUtils = new PostgreSQLUtils(this);
this.InternalCommonExpression = new PostgreSQLExpression(this.InternalCommonUtils);
this.Cache = new CacheProvider(cache, log);
this.Ado = new PostgreSQLAdo(this.InternalCommonUtils, this.Cache, log, masterConnectionString, slaveConnectionString);
this.Aop = new AopProvider();
this.DbFirst = new PostgreSQLDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
this.CodeFirst = new PostgreSQLCodeFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
}
internal CommonUtils InternalCommonUtils { get; }
internal CommonExpression InternalCommonExpression { get; }
public void Transaction(Action handler) => Ado.Transaction(handler);
public void Transaction(Action handler, TimeSpan timeout) => Ado.Transaction(handler, timeout);
~PostgreSQLProvider() {
this.Dispose();
}
bool _isdisposed = false;
public void Dispose() {
if (_isdisposed) return;
(this.Ado as AdoProvider).Dispose();
(this.Cache as CacheProvider)?.Dispose();
}
}
}

View File

@ -1,168 +0,0 @@
using FreeSql.Internal;
using Newtonsoft.Json.Linq;
using Npgsql;
using Npgsql.LegacyPostgis;
using NpgsqlTypes;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Data.Common;
using System.Linq;
using System.Net;
using System.Text;
namespace FreeSql.PostgreSQL {
class PostgreSQLUtils : CommonUtils {
public PostgreSQLUtils(IFreeSql orm) : base(orm) {
}
static Array getParamterArrayValue(Type arrayType, object value, object defaultValue) {
var valueArr = value as Array;
var len = valueArr.GetLength(0);
var ret = Array.CreateInstance(arrayType, len);
for (var a = 0; a < len; a++) {
var item = valueArr.GetValue(a);
ret.SetValue(item == null ? defaultValue : getParamterValue(item.GetType(), item, 1), a);
}
return ret;
}
static Dictionary<string, Func<object, object>> dicGetParamterValue = new Dictionary<string, Func<object, object>> {
{ typeof(JToken).FullName, a => string.Concat(a) }, { typeof(JToken[]).FullName, a => getParamterArrayValue(typeof(string), a, null) },
{ typeof(JObject).FullName, a => string.Concat(a) }, { typeof(JObject[]).FullName, a => getParamterArrayValue(typeof(string), a, null) },
{ typeof(JArray).FullName, a => string.Concat(a) }, { typeof(JArray[]).FullName, a => getParamterArrayValue(typeof(string), a, null) },
{ typeof(uint).FullName, a => long.Parse(string.Concat(a)) }, { typeof(uint[]).FullName, a => getParamterArrayValue(typeof(long), a, 0) }, { typeof(uint?[]).FullName, a => getParamterArrayValue(typeof(long?), a, null) },
{ typeof(ulong).FullName, a => decimal.Parse(string.Concat(a)) }, { typeof(ulong[]).FullName, a => getParamterArrayValue(typeof(decimal), a, 0) }, { typeof(ulong?[]).FullName, a => getParamterArrayValue(typeof(decimal?), a, null) },
{ typeof(ushort).FullName, a => int.Parse(string.Concat(a)) }, { typeof(ushort[]).FullName, a => getParamterArrayValue(typeof(int), a, 0) }, { typeof(ushort?[]).FullName, a => getParamterArrayValue(typeof(int?), a, null) },
{ typeof(byte).FullName, a => short.Parse(string.Concat(a)) }, { typeof(byte[]).FullName, a => getParamterArrayValue(typeof(short), a, 0) }, { typeof(byte?[]).FullName, a => getParamterArrayValue(typeof(short?), a, null) },
{ typeof(sbyte).FullName, a => short.Parse(string.Concat(a)) }, { typeof(sbyte[]).FullName, a => getParamterArrayValue(typeof(short), a, 0) }, { typeof(sbyte?[]).FullName, a => getParamterArrayValue(typeof(short?), a, null) },
{ typeof(NpgsqlPath).FullName, a => {
var path = (NpgsqlPath)a;
try { int count = path.Count; return path; } catch { return new NpgsqlPath(new NpgsqlPoint(0, 0)); }
} }, { typeof(NpgsqlPath[]).FullName, a => getParamterArrayValue(typeof(NpgsqlPath), a, new NpgsqlPath(new NpgsqlPoint(0, 0))) }, { typeof(NpgsqlPath?[]).FullName, a => getParamterArrayValue(typeof(NpgsqlPath?), a, null) },
{ typeof(NpgsqlPolygon).FullName, a => {
var polygon = (NpgsqlPolygon)a;
try { int count = polygon.Count; return polygon; } catch { return new NpgsqlPolygon(new NpgsqlPoint(0, 0), new NpgsqlPoint(0, 0)); }
} }, { typeof(NpgsqlPolygon[]).FullName, a => getParamterArrayValue(typeof(NpgsqlPolygon), a, new NpgsqlPolygon(new NpgsqlPoint(0, 0), new NpgsqlPoint(0, 0))) }, { typeof(NpgsqlPolygon?[]).FullName, a => getParamterArrayValue(typeof(NpgsqlPolygon?), a, null) },
{ typeof((IPAddress Address, int Subnet)).FullName, a => {
var inet = ((IPAddress Address, int Subnet))a;
if (inet.Address == null) return (IPAddress.Any, inet.Subnet);
return inet;
} }, { typeof((IPAddress Address, int Subnet)[]).FullName, a => getParamterArrayValue(typeof((IPAddress Address, int Subnet)), a, (IPAddress.Any, 0)) }, { typeof((IPAddress Address, int Subnet)?[]).FullName, a => getParamterArrayValue(typeof((IPAddress Address, int Subnet)?), a, null) },
};
static object getParamterValue(Type type, object value, int level = 0) {
if (type.FullName == "System.Byte[]") return value;
if (type.IsArray && level == 0) {
var elementType = type.GetElementType();
Type enumType = null;
if (elementType.IsEnum) enumType = elementType;
else if (elementType.IsNullableType() && elementType.GenericTypeArguments.First().IsEnum) enumType = elementType.GenericTypeArguments.First();
if (enumType != null) return enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Any() ?
getParamterArrayValue(typeof(long), value, elementType.IsEnum ? null : Enum.GetValues(enumType).GetValue(0)) :
getParamterArrayValue(typeof(int), value, elementType.IsEnum ? null : Enum.GetValues(enumType).GetValue(0));
return dicGetParamterValue.TryGetValue(type.FullName, out var trydicarr) ? trydicarr(value) : value;
}
if (type.IsNullableType()) type = type.GenericTypeArguments.First();
if (type.IsEnum) return (int)value;
if (dicGetParamterValue.TryGetValue(type.FullName, out var trydic)) return trydic(value);
return value;
}
internal override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value) {
if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}";
if (value != null) value = getParamterValue(type, value);
var ret = new NpgsqlParameter { ParameterName = QuoteParamterName(parameterName), Value = value };
//if (value.GetType().IsEnum || value.GetType().GenericTypeArguments.FirstOrDefault()?.IsEnum == true) {
// ret.DataTypeName = "";
//} else {
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null) ret.NpgsqlDbType = (NpgsqlDbType)tp.Value;
//}
_params?.Add(ret);
return ret;
}
internal override DbParameter[] GetDbParamtersByObject(string sql, object obj) =>
Utils.GetDbParamtersByObject<NpgsqlParameter>(sql, obj, "@", (name, type, value) => {
if (value != null) value = getParamterValue(type, value);
var ret = new NpgsqlParameter { ParameterName = $"@{name}", Value = value };
//if (value.GetType().IsEnum || value.GetType().GenericTypeArguments.FirstOrDefault()?.IsEnum == true) {
// ret.DataTypeName = "";
//} else {
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null) ret.NpgsqlDbType = (NpgsqlDbType)tp.Value;
//}
return ret;
});
internal override string FormatSql(string sql, params object[] args) => sql?.FormatPostgreSQL(args);
internal override string QuoteSqlName(string name) {
var nametrim = name.Trim();
if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
return nametrim; //原生SQL
return $"\"{nametrim.Trim('"').Replace(".", "\".\"")}\"";
}
internal override string TrimQuoteSqlName(string name) {
var nametrim = name.Trim();
if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
return nametrim; //原生SQL
return $"{nametrim.Trim('"').Replace("\".\"", ".").Replace(".\"", ".")}";
}
internal override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
internal override string IsNull(string sql, object value) => $"coalesce({sql}, {value})";
internal override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}";
internal override string Mod(string left, string right, Type leftType, Type rightType) => $"{left} % {right}";
internal override string QuoteWriteParamter(Type type, string paramterName) => paramterName;
internal override string QuoteReadColumn(Type type, string columnName) => columnName;
static ConcurrentDictionary<Type, bool> _dicIsAssignableFromPostgisGeometry = new ConcurrentDictionary<Type, bool>();
internal override string GetNoneParamaterSqlValue(List<DbParameter> specialParams, Type type, object value) {
if (value == null) return "NULL";
if (_dicIsAssignableFromPostgisGeometry.GetOrAdd(type, t2 => typeof(PostgisGeometry).IsAssignableFrom(type.IsArray ? type.GetElementType() : type))) {
var pam = AppendParamter(specialParams, null, type, value);
return pam.ParameterName;
}
value = getParamterValue(type, value);
var type2 = value.GetType();
if (type2 == typeof(byte[])) {
var bytes = value as byte[];
var sb = new StringBuilder().Append("'\\x");
foreach (var vc in bytes) {
if (vc < 10) sb.Append("0");
sb.Append(vc.ToString("X"));
}
return sb.Append("'").ToString(); //val = Encoding.UTF8.GetString(val as byte[]);
} else if (type2 == typeof(TimeSpan) || type2 == typeof(TimeSpan?)) {
var ts = (TimeSpan)value;
return $"'{Math.Min(24, (int)Math.Floor(ts.TotalHours))}:{ts.Minutes}:{ts.Seconds}'";
} else if (value is Array) {
var valueArr = value as Array;
var eleType = type2.GetElementType();
var len = valueArr.GetLength(0);
var sb = new StringBuilder().Append("ARRAY[");
for (var a = 0; a < len; a++) {
var item = valueArr.GetValue(a);
if (a > 0) sb.Append(",");
sb.Append(GetNoneParamaterSqlValue(specialParams, eleType, item));
}
sb.Append("]");
var dbinfo = _orm.CodeFirst.GetDbInfo(type);
if (dbinfo.HasValue) sb.Append("::").Append(dbinfo.Value.dbtype);
return sb.ToString();
} else if (type2 == typeof(BitArray)) {
return $"'{(value as BitArray).To1010()}'";
} else if (type2 == typeof(NpgsqlLine) || type2 == typeof(NpgsqlLine?)) {
var line = value.ToString();
return line == "{0,0,0}" ? "'{0,-1,-1}'" : $"'{line}'";
} else if (type2 == typeof((IPAddress Address, int Subnet)) || type2 == typeof((IPAddress Address, int Subnet)?)) {
var cidr = ((IPAddress Address, int Subnet))value;
return $"'{cidr.Address}/{cidr.Subnet}'";
} else if (dicGetParamterValue.ContainsKey(type2.FullName)) {
value = string.Concat(value);
}
return FormatSql("{0}", value, 1);
}
}
}

View File

@ -1,88 +0,0 @@
using FreeSql.Internal;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.SqlServer.Curd {
class SqlServerDelete<T1> : Internal.CommonProvider.DeleteProvider<T1> where T1 : class {
public SqlServerDelete(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
: base(orm, commonUtils, commonExpression, dywhere) {
}
public override List<T1> ExecuteDeleted() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(" OUTPUT ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append("DELETED.").Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
var validx = sql.IndexOf(" WHERE ");
if (validx == -1) throw new ArgumentException("找不到 WHERE ");
sb.Insert(0, sql.Substring(0, validx));
sb.Append(sql.Substring(validx));
sql = sb.ToString();
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Delete, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
async public override Task<List<T1>> ExecuteDeletedAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(" OUTPUT ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append("DELETED.").Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
var validx = sql.IndexOf(" WHERE ");
if (validx == -1) throw new ArgumentException("找不到 WHERE ");
sb.Insert(0, sql.Substring(0, validx));
sb.Append(sql.Substring(validx));
sql = sb.ToString();
var dbParms = _params.ToArray();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Delete, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sql, dbParms);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
}
}

View File

@ -1,139 +0,0 @@
using FreeSql.Internal;
using SafeObjectPool;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.SqlServer.Curd {
class SqlServerInsert<T1> : Internal.CommonProvider.InsertProvider<T1> where T1 : class {
public SqlServerInsert(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression) {
}
public override int ExecuteAffrows() => base.SplitExecuteAffrows(1000, 2100);
public override Task<int> ExecuteAffrowsAsync() => base.SplitExecuteAffrowsAsync(1000, 2100);
public override long ExecuteIdentity() => base.SplitExecuteIdentity(1000, 2100);
public override Task<long> ExecuteIdentityAsync() => base.SplitExecuteIdentityAsync(1000, 2100);
public override List<T1> ExecuteInserted() => base.SplitExecuteInserted(1000, 2100);
public override Task<List<T1>> ExecuteInsertedAsync() => base.SplitExecuteInsertedAsync(1000, 2100);
internal override long RawExecuteIdentity() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
sql = string.Concat(sql, "; SELECT SCOPE_IDENTITY();");
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
long ret = 0;
Exception exception = null;
try {
long.TryParse(string.Concat(_orm.Ado.ExecuteScalar(_connection, _transaction, CommandType.Text, sql, _params)), out ret);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
async internal override Task<long> RawExecuteIdentityAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
sql = string.Concat(sql, "; SELECT SCOPE_IDENTITY();");
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
long ret = 0;
Exception exception = null;
try {
long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync(_connection, _transaction, CommandType.Text, sql, _params)), out ret);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
internal override List<T1> RawExecuteInserted() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(" OUTPUT ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
var validx = sql.IndexOf(") VALUES");
if (validx == -1) throw new ArgumentException("找不到 VALUES");
sb.Insert(0, sql.Substring(0, validx + 1));
sb.Append(sql.Substring(validx + 1));
sql = sb.ToString();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sql, _params);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
async internal override Task<List<T1>> RawExecuteInsertedAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(" OUTPUT ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
var validx = sql.IndexOf(") VALUES");
if (validx == -1) throw new ArgumentException("找不到 VALUES");
sb.Insert(0, sql.Substring(0, validx + 1));
sb.Append(sql.Substring(validx + 1));
sql = sb.ToString();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sql, _params);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
}
}

View File

@ -1,225 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace FreeSql.SqlServer.Curd {
class SqlServerSelect<T1> : FreeSql.Internal.CommonProvider.Select1Provider<T1> where T1 : class {
internal static string ToSqlStatic(CommonUtils _commonUtils, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables, Func<Type, string, string> tableRuleInvoke, IFreeSql _orm)
=> (_commonUtils as SqlServerUtils).IsSelectRowNumber ?
ToSqlStaticRowNumber(_commonUtils, _select, _distinct, field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, tableRuleInvoke, _orm) :
ToSqlStaticOffsetFetchNext(_commonUtils, _select, _distinct, field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, tableRuleInvoke, _orm);
#region SqlServer 2005 row_number
internal static string ToSqlStaticRowNumber(CommonUtils _commonUtils, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables, Func<Type, string, string> tableRuleInvoke, IFreeSql _orm) {
if (_orm.CodeFirst.IsAutoSyncStructure)
_orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray());
var sb = new StringBuilder();
var sbnav = new StringBuilder();
sb.Append(_select);
if (_distinct) sb.Append("DISTINCT ");
if (_limit > 0) sb.Append("TOP ").Append(_skip + _limit).Append(" ");
sb.Append(field);
if (_skip > 0) {
if (string.IsNullOrEmpty(_orderby)) {
var pktb = _tables.Where(a => a.Table.Primarys.Any()).FirstOrDefault();
if (pktb != null) _orderby = string.Concat(" \r\nORDER BY ", pktb.Alias, ".", _commonUtils.QuoteSqlName(pktb?.Table.Primarys.First().Attribute.Name));
else _orderby = string.Concat(" \r\nORDER BY ", _tables.First().Alias, ".", _commonUtils.QuoteSqlName(_tables.First().Table.Columns.First().Value.Attribute.Name));
}
sb.Append(", ROW_NUMBER() OVER(").Append(_orderby).Append(") AS __rownum__");
}
sb.Append(" \r\nFROM ");
var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray();
var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray();
for (var a = 0; a < tbsfrom.Length; a++) {
sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[a].Table.Type, tbsfrom[a].Table.DbName))).Append(" ").Append(tbsfrom[a].Alias);
if (tbsjoin.Length > 0) {
//如果存在 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(tableRuleInvoke(tbsfrom[b].Table.Type, tbsfrom[b].Table.DbName))).Append(" ").Append(tbsfrom[b].Alias);
if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On)) sb.Append(" ON 1 = 1");
else sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On);
}
break;
} else {
if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")");
if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")");
}
if (a < tbsfrom.Length - 1) sb.Append(", ");
}
foreach (var tb in tbsjoin) {
if (tb.Type == SelectTableInfoType.Parent) continue;
switch (tb.Type) {
case SelectTableInfoType.LeftJoin:
sb.Append(" \r\nLEFT JOIN ");
break;
case SelectTableInfoType.InnerJoin:
sb.Append(" \r\nINNER JOIN ");
break;
case SelectTableInfoType.RightJoin:
sb.Append(" \r\nRIGHT JOIN ");
break;
}
sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tb.Table.Type, tb.Table.DbName))).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition);
if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")");
}
if (_join.Length > 0) sb.Append(_join);
sbnav.Append(_where);
foreach (var tb in _tables) {
if (tb.Type == SelectTableInfoType.Parent) continue;
if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false)
sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")");
}
if (sbnav.Length > 0) {
sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5));
}
if (string.IsNullOrEmpty(_groupby) == false) {
sb.Append(_groupby);
if (string.IsNullOrEmpty(_having) == false)
sb.Append(" \r\nHAVING ").Append(_having.Substring(5));
}
if (_skip <= 0)
sb.Append(_orderby);
else
sb.Insert(0, "WITH t AS ( ").Append(" ) SELECT t.* FROM t where __rownum__ > ").Append(_skip);
sbnav.Clear();
return sb.ToString();
}
#endregion
#region SqlServer 2012+ offset feach next
internal static string ToSqlStaticOffsetFetchNext(CommonUtils _commonUtils, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables, Func<Type, string, string> tableRuleInvoke, IFreeSql _orm) {
if (_orm.CodeFirst.IsAutoSyncStructure)
_orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray());
var sb = new StringBuilder();
var sbnav = new StringBuilder();
sb.Append(_select);
if (_distinct) sb.Append("DISTINCT ");
if (_skip <= 0 && _limit > 0) sb.Append("TOP ").Append(_limit).Append(" ");
sb.Append(field);
sb.Append(" \r\nFROM ");
var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray();
var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray();
for (var a = 0; a < tbsfrom.Length; a++) {
sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[a].Table.Type, tbsfrom[a].Table.DbName))).Append(" ").Append(tbsfrom[a].Alias);
if (tbsjoin.Length > 0) {
//如果存在 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(tableRuleInvoke(tbsfrom[b].Table.Type, tbsfrom[b].Table.DbName))).Append(" ").Append(tbsfrom[b].Alias);
if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On)) sb.Append(" ON 1 = 1");
else sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On);
}
break;
} else {
if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")");
if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")");
}
if (a < tbsfrom.Length - 1) sb.Append(", ");
}
foreach (var tb in tbsjoin) {
if (tb.Type == SelectTableInfoType.Parent) continue;
switch (tb.Type) {
case SelectTableInfoType.LeftJoin:
sb.Append(" \r\nLEFT JOIN ");
break;
case SelectTableInfoType.InnerJoin:
sb.Append(" \r\nINNER JOIN ");
break;
case SelectTableInfoType.RightJoin:
sb.Append(" \r\nRIGHT JOIN ");
break;
}
sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tb.Table.Type, tb.Table.DbName))).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition);
if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")");
}
if (_join.Length > 0) sb.Append(_join);
sbnav.Append(_where);
foreach (var tb in _tables) {
if (tb.Type == SelectTableInfoType.Parent) continue;
if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false)
sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")");
}
if (sbnav.Length > 0) {
sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5));
}
if (string.IsNullOrEmpty(_groupby) == false) {
sb.Append(_groupby);
if (string.IsNullOrEmpty(_having) == false)
sb.Append(" \r\nHAVING ").Append(_having.Substring(5));
}
if (_skip > 0) {
if (string.IsNullOrEmpty(_orderby)) {
var pktb = _tables.Where(a => a.Table.Primarys.Any()).FirstOrDefault();
if (pktb != null) _orderby = string.Concat(" \r\nORDER BY ", pktb.Alias, ".", _commonUtils.QuoteSqlName(pktb?.Table.Primarys.First().Attribute.Name));
else _orderby = string.Concat(" \r\nORDER BY ", _tables.First().Alias, ".", _commonUtils.QuoteSqlName(_tables.First().Table.Columns.First().Value.Attribute.Name));
}
sb.Append(_orderby).Append($" \r\nOFFSET {_skip} ROW");
if (_limit > 0) sb.Append($" \r\nFETCH NEXT {_limit} ROW ONLY");
} else {
sb.Append(_orderby);
}
sbnav.Clear();
return sb.ToString();
}
#endregion
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override ISelect<T1, T2> From<T2>(Expression<Func<ISelectFromExpression<T1>, T2, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqlServerSelect<T1, T2>(_orm, _commonUtils, _commonExpression, null); SqlServerSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3> From<T2, T3>(Expression<Func<ISelectFromExpression<T1>, T2, T3, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqlServerSelect<T1, T2, T3>(_orm, _commonUtils, _commonExpression, null); SqlServerSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4> From<T2, T3, T4>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqlServerSelect<T1, T2, T3, T4>(_orm, _commonUtils, _commonExpression, null); SqlServerSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5> From<T2, T3, T4, T5>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqlServerSelect<T1, T2, T3, T4, T5>(_orm, _commonUtils, _commonExpression, null); SqlServerSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6> From<T2, T3, T4, T5, T6>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqlServerSelect<T1, T2, T3, T4, T5, T6>(_orm, _commonUtils, _commonExpression, null); SqlServerSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7> From<T2, T3, T4, T5, T6, T7>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqlServerSelect<T1, T2, T3, T4, T5, T6, T7>(_orm, _commonUtils, _commonExpression, null); SqlServerSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8> From<T2, T3, T4, T5, T6, T7, T8>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqlServerSelect<T1, T2, T3, T4, T5, T6, T7, T8>(_orm, _commonUtils, _commonExpression, null); SqlServerSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> From<T2, T3, T4, T5, T6, T7, T8, T9>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqlServerSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>(_orm, _commonUtils, _commonExpression, null); SqlServerSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqlServerSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); SqlServerSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqlServerSelect<T1, T2> : FreeSql.Internal.CommonProvider.Select2Provider<T1, T2> where T1 : class where T2 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqlServerSelect<T1, T2, T3> : FreeSql.Internal.CommonProvider.Select3Provider<T1, T2, T3> where T1 : class where T2 : class where T3 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqlServerSelect<T1, T2, T3, T4> : FreeSql.Internal.CommonProvider.Select4Provider<T1, T2, T3, T4> where T1 : class where T2 : class where T3 : class where T4 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqlServerSelect<T1, T2, T3, T4, T5> : FreeSql.Internal.CommonProvider.Select5Provider<T1, T2, T3, T4, T5> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqlServerSelect<T1, T2, T3, T4, T5, T6> : FreeSql.Internal.CommonProvider.Select6Provider<T1, T2, T3, T4, T5, T6> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqlServerSelect<T1, T2, T3, T4, T5, T6, T7> : FreeSql.Internal.CommonProvider.Select7Provider<T1, T2, T3, T4, T5, T6, T7> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqlServerSelect<T1, T2, T3, T4, T5, T6, T7, T8> : FreeSql.Internal.CommonProvider.Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqlServerSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> : FreeSql.Internal.CommonProvider.Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqlServerSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : FreeSql.Internal.CommonProvider.Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class {
public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqlServerSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
}

View File

@ -1,127 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.SqlServer.Curd {
class SqlServerUpdate<T1> : Internal.CommonProvider.UpdateProvider<T1> where T1 : class {
public SqlServerUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
: base(orm, commonUtils, commonExpression, dywhere) {
}
public override int ExecuteAffrows() => base.SplitExecuteAffrows(500, 2100);
public override Task<int> ExecuteAffrowsAsync() => base.SplitExecuteAffrowsAsync(500, 2100);
public override List<T1> ExecuteUpdated() => base.SplitExecuteUpdated(500, 2100);
public override Task<List<T1>> ExecuteUpdatedAsync() => base.SplitExecuteUpdatedAsync(500, 2100);
internal override List<T1> RawExecuteUpdated() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(" OUTPUT ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
var validx = sql.IndexOf(" WHERE ");
if (validx == -1) throw new ArgumentException("找不到 WHERE ");
sb.Insert(0, sql.Substring(0, validx));
sb.Append(sql.Substring(validx));
sql = sb.ToString();
var dbParms = _params.Concat(_paramsSource).ToArray();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Update, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = _orm.Ado.Query<T1>(_connection, _transaction, CommandType.Text, sql, dbParms);
ValidateVersionAndThrow(ret.Count);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
async internal override Task<List<T1>> RawExecuteUpdatedAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
var sb = new StringBuilder();
sb.Append(" OUTPUT ");
var colidx = 0;
foreach (var col in _table.Columns.Values) {
if (colidx > 0) sb.Append(", ");
sb.Append(_commonUtils.QuoteReadColumn(col.Attribute.MapType, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
++colidx;
}
var validx = sql.IndexOf(" WHERE ");
if (validx == -1) throw new ArgumentException("找不到 WHERE ");
sb.Insert(0, sql.Substring(0, validx));
sb.Append(sql.Substring(validx));
sql = sb.ToString();
var dbParms = _params.Concat(_paramsSource).ToArray();
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Update, sql, dbParms);
_orm.Aop.CurdBefore?.Invoke(this, before);
var ret = new List<T1>();
Exception exception = null;
try {
ret = await _orm.Ado.QueryAsync<T1>(_connection, _transaction, CommandType.Text, sql, dbParms);
ValidateVersionAndThrow(ret.Count);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
if (_table.Primarys.Length == 1) {
caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().Attribute.MapType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
return;
}
caseWhen.Append("(");
var pkidx = 0;
foreach (var pk in _table.Primarys) {
if (pkidx > 0) caseWhen.Append(", ");
caseWhen.Append("cast(").Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name))).Append(" as varchar)");
++pkidx;
}
caseWhen.Append(")");
}
protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
if (_table.Primarys.Length == 1) {
sb.Append(_commonUtils.FormatSql("{0}", _table.Primarys.First().GetMapValue(d)));
return;
}
var pkidx = 0;
foreach (var pk in _table.Primarys) {
if (pkidx > 0) sb.Append(", ");
sb.Append("cast(").Append(_commonUtils.FormatSql("{0}", pk.GetMapValue(d))).Append(" as varchar)");
++pkidx;
}
}
}
}

View File

@ -1,66 +0,0 @@
using FreeSql.Internal;
using Microsoft.Extensions.Logging;
using SafeObjectPool;
using System;
using System.Collections;
using System.Data.Common;
using System.Data.SqlClient;
using System.Text;
using System.Threading;
namespace FreeSql.SqlServer {
class SqlServerAdo : FreeSql.Internal.CommonProvider.AdoProvider {
public SqlServerAdo() : base(null, null, DataType.SqlServer) { }
public SqlServerAdo(CommonUtils util, ICache cache, ILogger log, string masterConnectionString, string[] slaveConnectionStrings) : base(cache, log, DataType.SqlServer) {
base._util = util;
if (!string.IsNullOrEmpty(masterConnectionString))
MasterPool = new SqlServerConnectionPool("主库", masterConnectionString, null, null);
if (slaveConnectionStrings != null) {
foreach (var slaveConnectionString in slaveConnectionStrings) {
var slavePool = new SqlServerConnectionPool($"从库{SlavePools.Count + 1}", slaveConnectionString, () => Interlocked.Decrement(ref slaveUnavailables), () => Interlocked.Increment(ref slaveUnavailables));
SlavePools.Add(slavePool);
}
}
}
static DateTime dt1970 = new DateTime(1970, 1, 1);
public override object AddslashesProcessParam(object param, Type mapType) {
if (param == null) return "NULL";
if (mapType != null && mapType != param.GetType())
param = Utils.GetDataReaderValue(mapType, param);
if (param is bool || param is bool?)
return (bool)param ? 1 : 0;
else if (param is string || param is char)
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
else if (param is Enum)
return ((Enum)param).ToInt64();
else if (decimal.TryParse(string.Concat(param), out var trydec))
return param;
else if (param is DateTime || param is DateTime?) {
if (param.Equals(DateTime.MinValue) == true) param = new DateTime(1970, 1, 1);
return string.Concat("'", ((DateTime)param).ToString("yyyy-MM-dd HH:mm:ss.fff"), "'");
} else if (param is DateTimeOffset || param is DateTimeOffset?) {
if (param.Equals(DateTimeOffset.MinValue) == true) param = new DateTimeOffset(new DateTime(1970, 1, 1), TimeSpan.Zero);
return string.Concat("'", ((DateTimeOffset)param).ToString("yyyy-MM-dd HH:mm:ss.fff zzzz"), "'");
} else if (param is TimeSpan || param is TimeSpan?)
return ((TimeSpan)param).TotalSeconds;
else if (param is IEnumerable) {
var sb = new StringBuilder();
var ie = param as IEnumerable;
foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType));
return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
}
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
//if (param is string) return string.Concat('N', nparms[a]);
}
protected override DbCommand CreateCommand() {
return new SqlCommand();
}
protected override void ReturnConnection(ObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex) {
(pool as SqlServerConnectionPool).Return(conn, ex);
}
protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj);
}
}

View File

@ -1,181 +0,0 @@
using SafeObjectPool;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace FreeSql.SqlServer {
class SqlServerConnectionPool : ObjectPool<DbConnection> {
internal Action availableHandler;
internal Action unavailableHandler;
public SqlServerConnectionPool(string name, string connectionString, Action availableHandler, Action unavailableHandler) : base(null) {
var policy = new SqlServerConnectionPoolPolicy {
_pool = this,
Name = name
};
this.Policy = policy;
policy.ConnectionString = connectionString;
this.availableHandler = availableHandler;
this.unavailableHandler = unavailableHandler;
}
public void Return(Object<DbConnection> obj, Exception exception, bool isRecreate = false) {
if (exception != null && exception is SqlException) {
if (obj.Value.Ping() == false) {
base.SetUnavailable(exception);
}
}
base.Return(obj, isRecreate);
}
}
class SqlServerConnectionPoolPolicy : IPolicy<DbConnection> {
internal SqlServerConnectionPool _pool;
public string Name { get; set; } = "SqlServer SqlConnection 对象池";
public int PoolSize { get; set; } = 100;
public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
public TimeSpan IdleTimeout { get; set; } = TimeSpan.Zero;
public int AsyncGetCapacity { get; set; } = 10000;
public bool IsThrowGetTimeoutException { get; set; } = true;
public int CheckAvailableInterval { get; set; } = 5;
static ConcurrentDictionary<string, int> dicConnStrIncr = new ConcurrentDictionary<string, int>(StringComparer.CurrentCultureIgnoreCase);
private string _connectionString;
public string ConnectionString {
get => _connectionString;
set {
_connectionString = value ?? "";
var pattern = @"Max\s*pool\s*size\s*=\s*(\d+)";
Match m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success == false || int.TryParse(m.Groups[1].Value, out var poolsize) == false || poolsize <= 0) poolsize = 100;
var connStrIncr = dicConnStrIncr.AddOrUpdate(_connectionString, 1, (oldkey, oldval) => oldval + 1);
PoolSize = poolsize + connStrIncr;
_connectionString = m.Success ?
Regex.Replace(_connectionString, pattern, $"Max pool size={PoolSize}", RegexOptions.IgnoreCase) :
$"{_connectionString};Max pool size={PoolSize}";
pattern = @"Connection\s*LifeTime\s*=\s*(\d+)";
m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success) {
IdleTimeout = TimeSpan.FromSeconds(int.Parse(m.Groups[1].Value));
_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase);
}
var minPoolSize = 0;
pattern = @"Min\s*pool\s*size\s*=\s*(\d+)";
m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success) {
minPoolSize = int.Parse(m.Groups[1].Value);
_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase);
}
FreeUtil.PrevReheatConnectionPool(_pool, minPoolSize);
}
}
public bool OnCheckAvailable(Object<DbConnection> obj) {
if (obj.Value.State == ConnectionState.Closed) obj.Value.Open();
return obj.Value.Ping(true);
}
public DbConnection OnCreate() {
var conn = new SqlConnection(_connectionString);
return conn;
}
public void OnDestroy(DbConnection obj) {
if (obj.State != ConnectionState.Closed) obj.Close();
obj.Dispose();
}
public void OnGet(Object<DbConnection> obj) {
if (_pool.IsAvailable) {
if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && obj.Value.Ping() == false) {
try {
obj.Value.Open();
} catch (Exception ex) {
if (_pool.SetUnavailable(ex) == true)
throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}");
}
}
}
}
async public Task OnGetAsync(Object<DbConnection> obj) {
if (_pool.IsAvailable) {
if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && (await obj.Value.PingAsync()) == false) {
try {
await obj.Value.OpenAsync();
} catch (Exception ex) {
if (_pool.SetUnavailable(ex) == true)
throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}");
}
}
}
}
public void OnGetTimeout() {
}
public void OnReturn(Object<DbConnection> obj) {
if (obj.Value.State != ConnectionState.Closed) try { obj.Value.Close(); } catch { }
}
public void OnAvailable() {
_pool.availableHandler?.Invoke();
}
public void OnUnavailable() {
_pool.unavailableHandler?.Invoke();
}
}
static class DbConnectionExtensions {
static DbCommand PingCommand(DbConnection conn) {
var cmd = conn.CreateCommand();
cmd.CommandTimeout = 5;
cmd.CommandText = "select 1";
return cmd;
}
public static bool Ping(this DbConnection that, bool isThrow = false) {
try {
PingCommand(that).ExecuteNonQuery();
return true;
} catch {
if (that.State != ConnectionState.Closed) try { that.Close(); } catch { }
if (isThrow) throw;
return false;
}
}
async public static Task<bool> PingAsync(this DbConnection that, bool isThrow = false) {
try {
await PingCommand(that).ExecuteNonQueryAsync();
return true;
} catch {
if (that.State != ConnectionState.Closed) try { that.Close(); } catch { }
if (isThrow) throw;
return false;
}
}
}
}

View File

@ -1,366 +0,0 @@
using FreeSql.DataAnnotations;
using FreeSql.DatabaseModel;
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace FreeSql.SqlServer {
class SqlServerCodeFirst : ICodeFirst {
IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
public SqlServerCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) {
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
}
public bool IsAutoSyncStructure { get; set; } = false;
public bool IsSyncStructureToLower { get; set; } = false;
public bool IsSyncStructureToUpper { get; set; } = false;
public bool IsConfigEntityFromDbFirst { get; set; } = false;
public bool IsNoneCommandParameter { get; set; } = false;
public bool IsLazyLoading { get; set; } = false;
static object _dicCsToDbLock = new object();
static Dictionary<string, (SqlDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)> _dicCsToDb = new Dictionary<string, (SqlDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)>() {
{ typeof(bool).FullName, (SqlDbType.Bit, "bit","bit NOT NULL", null, false, false) },{ typeof(bool?).FullName, (SqlDbType.Bit, "bit","bit", null, true, null) },
{ typeof(sbyte).FullName, (SqlDbType.SmallInt, "smallint", "smallint NOT NULL", false, false, 0) },{ typeof(sbyte?).FullName, (SqlDbType.SmallInt, "smallint", "smallint", false, true, null) },
{ typeof(short).FullName, (SqlDbType.SmallInt, "smallint","smallint NOT NULL", false, false, 0) },{ typeof(short?).FullName, (SqlDbType.SmallInt, "smallint", "smallint", false, true, null) },
{ typeof(int).FullName, (SqlDbType.Int, "int", "int NOT NULL", false, false, 0) },{ typeof(int?).FullName, (SqlDbType.Int, "int", "int", false, true, null) },
{ typeof(long).FullName, (SqlDbType.BigInt, "bigint","bigint NOT NULL", false, false, 0) },{ typeof(long?).FullName, (SqlDbType.BigInt, "bigint","bigint", false, true, null) },
{ typeof(byte).FullName, (SqlDbType.TinyInt, "tinyint","tinyint NOT NULL", true, false, 0) },{ typeof(byte?).FullName, (SqlDbType.TinyInt, "tinyint","tinyint", true, true, null) },
{ typeof(ushort).FullName, (SqlDbType.Int, "int","int NOT NULL", true, false, 0) },{ typeof(ushort?).FullName, (SqlDbType.Int, "int", "int", true, true, null) },
{ typeof(uint).FullName, (SqlDbType.BigInt, "bigint", "bigint NOT NULL", true, false, 0) },{ typeof(uint?).FullName, (SqlDbType.BigInt, "bigint", "bigint", true, true, null) },
{ typeof(ulong).FullName, (SqlDbType.Decimal, "decimal", "decimal(20,0) NOT NULL", true, false, 0) },{ typeof(ulong?).FullName, (SqlDbType.Decimal, "decimal", "decimal(20,0)", true, true, null) },
{ typeof(double).FullName, (SqlDbType.Float, "float", "float NOT NULL", false, false, 0) },{ typeof(double?).FullName, (SqlDbType.Float, "float", "float", false, true, null) },
{ typeof(float).FullName, (SqlDbType.Real, "real","real NOT NULL", false, false, 0) },{ typeof(float?).FullName, (SqlDbType.Real, "real","real", false, true, null) },
{ typeof(decimal).FullName, (SqlDbType.Decimal, "decimal", "decimal(10,2) NOT NULL", false, false, 0) },{ typeof(decimal?).FullName, (SqlDbType.Decimal, "decimal", "decimal(10,2)", false, true, null) },
{ typeof(TimeSpan).FullName, (SqlDbType.Time, "time","time NOT NULL", false, false, 0) },{ typeof(TimeSpan?).FullName, (SqlDbType.Time, "time", "time",false, true, null) },
{ typeof(DateTime).FullName, (SqlDbType.DateTime, "datetime", "datetime NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, (SqlDbType.DateTime, "datetime", "datetime", false, true, null) },
{ typeof(DateTimeOffset).FullName, (SqlDbType.DateTimeOffset, "datetimeoffset", "datetimeoffset NOT NULL", false, false, new DateTimeOffset(new DateTime(1970,1,1), TimeSpan.Zero)) },{ typeof(DateTimeOffset?).FullName, (SqlDbType.DateTimeOffset, "datetimeoffset", "datetimeoffset", false, true, null) },
{ typeof(byte[]).FullName, (SqlDbType.VarBinary, "varbinary", "varbinary(255)", false, null, new byte[0]) },
{ typeof(string).FullName, (SqlDbType.NVarChar, "nvarchar", "nvarchar(255)", false, null, "") },
{ typeof(Guid).FullName, (SqlDbType.UniqueIdentifier, "uniqueidentifier", "uniqueidentifier NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName, (SqlDbType.UniqueIdentifier, "uniqueidentifier", "uniqueidentifier", false, true, null) },
};
public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) {
if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (int, string, string, bool?, object)?(((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue));
if (type.IsArray) return null;
var enumType = type.IsEnum ? type : null;
if (enumType == null && type.IsNullableType() && type.GenericTypeArguments.Length == 1 && type.GenericTypeArguments.First().IsEnum) enumType = type.GenericTypeArguments.First();
if (enumType != null) {
var newItem = enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Any() ?
(SqlDbType.BigInt, "bigint", $"bigint{(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0)) :
(SqlDbType.Int, "int", $"int{(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0));
if (_dicCsToDb.ContainsKey(type.FullName) == false) {
lock (_dicCsToDbLock) {
if (_dicCsToDb.ContainsKey(type.FullName) == false)
_dicCsToDb.Add(type.FullName, newItem);
}
}
return ((int)newItem.Item1, newItem.Item2, newItem.Item3, newItem.Item5, newItem.Item6);
}
return null;
}
public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity));
public string GetComparisonDDLStatements(params Type[] entityTypes) {
var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5));
var database = conn.Value.Database;
Func<string, string, object> ExecuteScalar = (db, sql) => {
if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db);
try {
using (var cmd = conn.Value.CreateCommand()) {
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
return cmd.ExecuteScalar();
}
} finally {
if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database);
}
};
var sb = new StringBuilder();
try {
foreach (var entityType in entityTypes) {
if (sb.Length > 0) sb.Append("\r\n");
var tb = _commonUtils.GetTableByEntity(entityType);
if (tb == null) throw new Exception($"类型 {entityType.FullName} 不可迁移");
if (tb.Columns.Any() == false) throw new Exception($"类型 {entityType.FullName} 不可迁移可迁移属性0个");
var tbname = tb.DbName.Split(new[] { '.' }, 3);
if (tbname?.Length == 1) tbname = new[] { database, "dbo", tbname[0] };
if (tbname?.Length == 2) tbname = new[] { database, tbname[0], tbname[1] };
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 3); //旧表名
if (tboldname?.Length == 1) tboldname = new[] { database, "dbo", tboldname[0] };
if (tboldname?.Length == 2) tboldname = new[] { database, tboldname[0], tboldname[1] };
if (string.Compare(tbname[0], database, true) != 0 && ExecuteScalar(database, $" select 1 from sys.databases where name='{tbname[0]}'") == null) //创建数据库
ExecuteScalar(database, $"if not exists(select 1 from sys.databases where name='{tbname[0]}')\r\n\tcreate database [{tbname[0]}];");
if (string.Compare(tbname[1], "dbo", true) != 0 && ExecuteScalar(tbname[0], $" select 1 from sys.schemas where name='{tbname[1]}'") == null) //创建模式
ExecuteScalar(tbname[0], $"create schema [{tbname[1]}] authorization [dbo]");
var sbalter = new StringBuilder();
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
if (ExecuteScalar(tbname[0], $" select 1 from dbo.sysobjects where id = object_id(N'[{tbname[1]}].[{tbname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null) { //表不存在
if (tboldname != null) {
if (string.Compare(tboldname[0], tbname[0], true) != 0 && ExecuteScalar(database, $" select 1 from sys.databases where name='{tboldname[0]}'") == null ||
string.Compare(tboldname[1], tbname[1], true) != 0 && ExecuteScalar(tboldname[0], $" select 1 from sys.schemas where name='{tboldname[1]}'") == null ||
ExecuteScalar(tboldname[0], $" select 1 from dbo.sysobjects where id = object_id(N'[{tboldname[1]}].[{tboldname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null)
//数据库或模式或表不存在
tboldname = null;
}
if (tboldname == null) {
//创建新表
sb.Append("use ").Append(_commonUtils.QuoteSqlName(tbname[0])).Append(";\r\nCREATE TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[1]}.{tbname[2]}")).Append(" ( ");
var pkidx = 0;
foreach (var tbcol in tb.Columns.Values) {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ");
sb.Append(tbcol.Attribute.DbType);
if (tbcol.Attribute.IsIdentity == true && tbcol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" identity(1,1)");
if (tbcol.Attribute.IsPrimary == true) {
if (tb.Primarys.Length > 1) {
if (pkidx == tb.Primarys.Length - 1)
sb.Append(" primary key (").Append(string.Join(", ", tb.Primarys.Select(a => _commonUtils.QuoteSqlName(a.Attribute.Name)))).Append(")");
} else
sb.Append(" primary key");
pkidx++;
}
sb.Append(",");
}
foreach (var uk in tb.Uniques) {
sb.Append(" \r\n CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(" UNIQUE(");
foreach (var tbcol in uk.Value) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
sb.Remove(sb.Length - 1, 1).Append("\r\n);\r\n");
continue;
}
//如果新表,旧表在一个数据库和模式下,直接修改表名
if (string.Compare(tbname[0], tboldname[0], true) == 0 &&
string.Compare(tbname[1], tboldname[1], true) == 0)
sbalter.Append("use ").Append(_commonUtils.QuoteSqlName(tbname[0])).Append(_commonUtils.FormatSql(";\r\nEXEC sp_rename {0}, {1};\r\n", _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}.{tboldname[2]}"), tbname[2]));
else {
//如果新表,旧表不在一起,创建新表,导入数据,删除旧表
istmpatler = true;
}
} else
tboldname = null; //如果新表已经存在,不走改表名逻辑
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
var sql = string.Format(@"
use [{0}];
select
a.name 'Column'
,b.name + case
when b.name in ('Char', 'VarChar', 'NChar', 'NVarChar', 'Binary', 'VarBinary') then '(' +
case when a.max_length = -1 then 'MAX'
when b.name in ('NChar', 'NVarchar') then cast(a.max_length / 2 as varchar)
else cast(a.max_length as varchar) end + ')'
when b.name in ('Numeric', 'Decimal') then '(' + cast(a.precision as varchar) + ',' + cast(a.scale as varchar) + ')'
else '' end as 'SqlType'
,case when a.is_nullable = 1 then '1' else '0' end 'IsNullable'
,case when a.is_identity = 1 then '1' else '0' end 'IsIdentity'
from sys.columns a
inner join sys.types b on b.user_type_id = a.user_type_id
left join sys.extended_properties AS c ON c.major_id = a.object_id AND c.minor_id = a.column_id
left join sys.tables d on d.object_id = a.object_id
left join sys.schemas e on e.schema_id = d.schema_id
where a.object_id in (object_id(N'[{1}].[{2}]'));
use " + database, tboldname ?? tbname);
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => new {
column = string.Concat(a[0]),
sqlType = string.Concat(a[1]),
is_nullable = string.Concat(a[2]) == "1",
is_identity = string.Concat(a[3]) == "1"
}, StringComparer.CurrentCultureIgnoreCase);
if (istmpatler == false) {
foreach (var tbcol in tb.Columns.Values) {
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false ||
tbcol.Attribute.IsNullable != tbstructcol.is_nullable ||
tbcol.Attribute.IsIdentity != tbstructcol.is_identity) {
istmpatler = true;
break;
}
if (tbstructcol.column == tbcol.Attribute.OldName) {
//修改列名
sbalter.Append(_commonUtils.FormatSql("EXEC sp_rename {0}, {1}, 'COLUMN';\r\n", $"{tbname[0]}.{tbname[1]}.{tbname[2]}.{tbcol.Attribute.OldName}", tbcol.Attribute.Name));
}
continue;
}
//添加列
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbname[2]}")).Append(" ADD ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType);
if (tbcol.Attribute.IsIdentity == true && tbcol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sbalter.Append(" identity(1,1)");
if (tbcol.Attribute.IsNullable == false) {
var addcoldbdefault = tbcol.Attribute.DbDefautValue;
if (addcoldbdefault != null) sbalter.Append(_commonUtils.FormatSql(" default({0})", addcoldbdefault));
}
sbalter.Append(";\r\n");
}
var dsuksql = string.Format(@"
use [{0}];
select
c.name
,d.name
from sys.index_columns a
inner join sys.indexes b on b.object_id = a.object_id and b.index_id = a.index_id
left join sys.columns c on c.object_id = a.object_id and c.column_id = a.column_id
left join sys.key_constraints d on d.parent_object_id = b.object_id and d.unique_index_id = b.index_id
where a.object_id in (object_id(N'[{1}].[{2}]')) and b.is_unique = 1;
use " + database, tboldname ?? tbname);
var dsuk = _orm.Ado.ExecuteArray(CommandType.Text, dsuksql).Select(a => new[] { string.Concat(a[0]), string.Concat(a[1]) });
foreach (var uk in tb.Uniques) {
if (string.IsNullOrEmpty(uk.Key) || uk.Value.Any() == false) continue;
var dsukfind1 = dsuk.Where(a => string.Compare(a[1], uk.Key, true) == 0).ToArray();
if (dsukfind1.Any() == false || dsukfind1.Length != uk.Value.Count || dsukfind1.Where(a => uk.Value.Where(b => string.Compare(b.Attribute.Name, a[0], true) == 0).Any()).Count() != uk.Value.Count) {
if (dsukfind1.Any()) sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbname[2]}")).Append(" DROP CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(";\r\n");
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbname[2]}")).Append(" ADD CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(" UNIQUE(");
foreach (var tbcol in uk.Value) sbalter.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sbalter.Remove(sbalter.Length - 2, 2).Append(");\r\n");
}
}
}
if (istmpatler == false) {
sb.Append(sbalter).Append("\r\nuse " + database);
continue;
}
//创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名
bool idents = false;
var tablename = tboldname == null ? _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbname[2]}") : _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}.{tboldname[2]}");
var tmptablename = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.FreeSqlTmp_{tbname[2]}");
sb.Append("BEGIN TRANSACTION\r\n")
.Append("SET QUOTED_IDENTIFIER ON\r\n")
.Append("SET ARITHABORT ON\r\n")
.Append("SET NUMERIC_ROUNDABORT OFF\r\n")
.Append("SET CONCAT_NULL_YIELDS_NULL ON\r\n")
.Append("SET ANSI_NULLS ON\r\n")
.Append("SET ANSI_PADDING ON\r\n")
.Append("SET ANSI_WARNINGS ON\r\n")
.Append("COMMIT\r\n");
sb.Append("BEGIN TRANSACTION;\r\n");
//创建临时表
sb.Append("CREATE TABLE ").Append(tmptablename).Append(" ( ");
var pkidx2 = 0;
foreach (var tbcol in tb.Columns.Values) {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ");
sb.Append(tbcol.Attribute.DbType);
if (tbcol.Attribute.IsIdentity == true && tbcol.Attribute.DbType.IndexOf("identity", StringComparison.CurrentCultureIgnoreCase) == -1) sb.Append(" identity(1,1)");
if (tbcol.Attribute.IsPrimary == true) {
if (tb.Primarys.Length > 1) {
if (pkidx2 == tb.Primarys.Length - 1)
sb.Append(" primary key (").Append(string.Join(", ", tb.Primarys.Select(a => _commonUtils.QuoteSqlName(a.Attribute.Name)))).Append(")");
} else
sb.Append(" primary key");
pkidx2++;
}
sb.Append(",");
idents = idents || tbcol.Attribute.IsIdentity == true;
}
foreach (var uk in tb.Uniques) {
sb.Append(" \r\n CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(" UNIQUE(");
foreach (var tbcol in uk.Value) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
sb.Remove(sb.Length - 1, 1).Append("\r\n);\r\n");
sb.Append("ALTER TABLE ").Append(tmptablename).Append(" SET (LOCK_ESCALATION = TABLE);\r\n");
if (idents) sb.Append("SET IDENTITY_INSERT ").Append(tmptablename).Append(" ON;\r\n");
sb.Append("IF EXISTS(SELECT 1 FROM ").Append(tablename).Append(")\r\n");
sb.Append("\tEXEC('INSERT INTO ").Append(tmptablename).Append(" (");
foreach (var tbcol in tb.Columns.Values)
sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append(")\r\n\t\tSELECT ");
foreach (var tbcol in tb.Columns.Values) {
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)) {
insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column);
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 = $"isnull({insertvalue},{_commonUtils.FormatSql("{0}", GetTransferDbDefaultValue(tbcol))})";
} else if (tbcol.Attribute.IsNullable == false)
insertvalue = _commonUtils.FormatSql("{0}", GetTransferDbDefaultValue(tbcol));
sb.Append(insertvalue.Replace("'", "''")).Append(", ");
}
sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append(" WITH (HOLDLOCK TABLOCKX)');\r\n");
if (idents) sb.Append("SET IDENTITY_INSERT ").Append(tmptablename).Append(" OFF;\r\n");
sb.Append("DROP TABLE ").Append(tablename).Append(";\r\n");
sb.Append("EXECUTE sp_rename N'").Append(tmptablename).Append("', N'").Append(tbname[2]).Append("', 'OBJECT';\r\n");
sb.Append("COMMIT;\r\n");
}
return sb.Length == 0 ? null : sb.ToString();
} finally {
try {
conn.Value.ChangeDatabase(database);
_orm.Ado.MasterPool.Return(conn);
} catch {
_orm.Ado.MasterPool.Return(conn, true);
}
}
}
object GetTransferDbDefaultValue(ColumnInfo col) {
var ddv = col.Attribute.DbDefautValue;
if (ddv == null) return ddv;
if (ddv is DateTime || ddv is DateTime?) {
var dt = (DateTime)ddv;
if (col.Attribute.DbType.Contains("SMALLDATETIME") && dt < new DateTime(1900, 1, 1)) ddv = new DateTime(1900, 1, 1);
else if (col.Attribute.DbType.Contains("DATETIME") && dt < new DateTime(1753, 1, 1)) ddv = new DateTime(1753, 1, 1);
else if (col.Attribute.DbType.Contains("DATE") && dt < new DateTime(0001, 1, 1)) ddv = new DateTime(0001, 1, 1);
}
return ddv;
}
static object syncStructureLock = new object();
ConcurrentDictionary<string, bool> dicSyced = new ConcurrentDictionary<string, bool>();
public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity));
public bool SyncStructure(params Type[] entityTypes) {
if (entityTypes == null) return true;
var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray();
if (syncTypes.Any() == false) return true;
var before = new Aop.SyncStructureBeforeEventArgs(entityTypes);
_orm.Aop.SyncStructureBefore?.Invoke(this, before);
Exception exception = null;
string ddl = null;
try {
lock (syncStructureLock) {
ddl = this.GetComparisonDDLStatements(syncTypes);
if (string.IsNullOrEmpty(ddl)) {
foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true);
return true;
}
var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl);
foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true);
return affrows > 0;
}
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception);
_orm.Aop.SyncStructureAfter?.Invoke(this, after);
}
}
public ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) => _commonUtils.ConfigEntity(entity);
public ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) => _commonUtils.ConfigEntity(type, entity);
public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type);
public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type);
}
}

View File

@ -1,418 +0,0 @@
using FreeSql.DatabaseModel;
using FreeSql.Internal;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text.RegularExpressions;
namespace FreeSql.SqlServer {
class SqlServerDbFirst : IDbFirst {
IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
public SqlServerDbFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) {
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
}
public int GetDbType(DbColumnInfo column) => (int)GetSqlDbType(column);
SqlDbType GetSqlDbType(DbColumnInfo column) {
switch (column.DbTypeText.ToLower()) {
case "bit": return SqlDbType.Bit;
case "tinyint": return SqlDbType.TinyInt;
case "smallint": return SqlDbType.SmallInt;
case "int": return SqlDbType.Int;
case "bigint": return SqlDbType.BigInt;
case "numeric":
case "decimal": return SqlDbType.Decimal;
case "smallmoney": return SqlDbType.SmallMoney;
case "money": return SqlDbType.Money;
case "float": return SqlDbType.Float;
case "real": return SqlDbType.Real;
case "date": return SqlDbType.Date;
case "datetime":
case "datetime2": return SqlDbType.DateTime;
case "datetimeoffset": return SqlDbType.DateTimeOffset;
case "smalldatetime": return SqlDbType.SmallDateTime;
case "time": return SqlDbType.Time;
case "char": return SqlDbType.Char;
case "varchar": return SqlDbType.VarChar;
case "text": return SqlDbType.Text;
case "nchar": return SqlDbType.NChar;
case "nvarchar": return SqlDbType.NVarChar;
case "ntext": return SqlDbType.NText;
case "binary": return SqlDbType.Binary;
case "varbinary": return SqlDbType.VarBinary;
case "image": return SqlDbType.Image;
case "timestamp": return SqlDbType.Timestamp;
case "uniqueidentifier": return SqlDbType.UniqueIdentifier;
default: return SqlDbType.Variant;
}
}
static readonly Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)> _dicDbToCs = new Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)>() {
{ (int)SqlDbType.Bit, ("(bool?)", "{0} == \"1\"", "{0} == true ? \"1\" : \"0\"", "bool?", typeof(bool), typeof(bool?), "{0}.Value", "GetBoolean") },
{ (int)SqlDbType.TinyInt, ("(byte?)", "byte.Parse({0})", "{0}.ToString()", "byte?", typeof(byte), typeof(byte?), "{0}.Value", "GetByte") },
{ (int)SqlDbType.SmallInt, ("(short?)", "short.Parse({0})", "{0}.ToString()", "short?", typeof(short), typeof(short?), "{0}.Value", "GetInt16") },
{ (int)SqlDbType.Int, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
{ (int)SqlDbType.BigInt, ("(long?)", "long.Parse({0})", "{0}.ToString()", "long?", typeof(long), typeof(long?), "{0}.Value", "GetInt64") },
{ (int)SqlDbType.SmallMoney, ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") },
{ (int)SqlDbType.Money, ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") },
{ (int)SqlDbType.Decimal, ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") },
{ (int)SqlDbType.Float, ("(double?)", "double.Parse({0})", "{0}.ToString()", "double?", typeof(double), typeof(double?), "{0}.Value", "GetDouble") },
{ (int)SqlDbType.Real, ("(float?)", "float.Parse({0})", "{0}.ToString()", "float?", typeof(float), typeof(float?), "{0}.Value", "GetFloat") },
{ (int)SqlDbType.Time, ("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") },
{ (int)SqlDbType.Date, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
{ (int)SqlDbType.DateTime, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
{ (int)SqlDbType.DateTime2, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
{ (int)SqlDbType.SmallDateTime, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
{ (int)SqlDbType.DateTimeOffset, ("(DateTimeOffset?)", "new DateTimeOffset(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTimeOffset), typeof(DateTimeOffset?), "{0}.Value", "GetDateTimeOffset") },
{ (int)SqlDbType.Binary, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
{ (int)SqlDbType.VarBinary, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
{ (int)SqlDbType.Image, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
{ (int)SqlDbType.Timestamp, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
{ (int)SqlDbType.Char, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)SqlDbType.VarChar, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)SqlDbType.Text, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)SqlDbType.NChar, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)SqlDbType.NVarChar, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)SqlDbType.NText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
{ (int)SqlDbType.UniqueIdentifier, ("(Guid?)", "Guid.Parse({0})", "{0}.ToString()", "Guid?", typeof(Guid), typeof(Guid?), "{0}.Value", "GetGuid") },
};
public string GetCsConvert(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? (column.IsNullable ? trydc.csConvert : trydc.csConvert.Replace("?", "")) : null;
public string GetCsParse(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csParse : null;
public string GetCsStringify(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csStringify : null;
public string GetCsType(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? (column.IsNullable ? trydc.csType : trydc.csType.Replace("?", "")) : null;
public Type GetCsTypeInfo(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csTypeInfo : null;
public string GetCsTypeValue(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csTypeValue : null;
public string GetDataReaderMethod(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.dataReaderMethod : null;
public List<string> GetDatabases() {
var sql = @" select name from sys.databases where name not in ('master','tempdb','model','msdb')";
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList();
}
public List<DbTableInfo> GetTablesByDatabase(params string[] database) {
var olddatabase = "";
using (var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5))) {
olddatabase = conn.Value.Database;
}
var dbs = database == null || database.Any() == false ? new[] { olddatabase } : database;
var tables = new List<DbTableInfo>();
foreach (var db in dbs) {
if (string.IsNullOrEmpty(db)) continue;
var loc1 = new List<DbTableInfo>();
var loc2 = new Dictionary<int, DbTableInfo>();
var loc3 = new Dictionary<int, Dictionary<string, DbColumnInfo>>();
var sql = $@"
use [{db}];
select
a.Object_id
,b.name 'Owner'
,a.name 'Name'
,c.value
,'TABLE' type
from sys.tables a
inner join sys.schemas b on b.schema_id = a.schema_id
left join sys.extended_properties AS c ON c.major_id = a.object_id AND c.minor_id = 0 AND c.name = 'MS_Description'
where not(b.name = 'dbo' and a.name = 'sysdiagrams')
union all
select
a.Object_id
,b.name 'Owner'
,a.name 'Name'
,c.value
,'VIEW' type
from sys.views a
inner join sys.schemas b on b.schema_id = a.schema_id
left join sys.extended_properties AS c ON c.major_id = a.object_id AND c.minor_id = 0 AND c.name = 'MS_Description'
union all
select
a.Object_id
,b.name 'Owner'
,a.name 'Name'
,c.value
,'StoreProcedure' type
from sys.procedures a
inner join sys.schemas b on b.schema_id = a.schema_id
left join sys.extended_properties AS c ON c.major_id = a.object_id AND c.minor_id = 0 AND c.name = 'MS_Description'
where a.type = 'P' and charindex('diagram', a.name) = 0
order by type desc, b.name, a.name
;
use [{olddatabase}];
";
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var loc6 = new List<int>();
var loc66 = new List<int>();
foreach (object[] row in ds) {
int object_id = int.Parse(string.Concat(row[0]));
var owner = string.Concat(row[1]);
var table = string.Concat(row[2]);
var comment = string.Concat(row[3]);
Enum.TryParse<DbTableType>(string.Concat(row[4]), out var type);
loc2.Add(object_id, new DbTableInfo { Id = object_id.ToString(), Schema = owner, Name = table, Comment = comment, Type = type });
loc3.Add(object_id, new Dictionary<string, DbColumnInfo>());
switch (type) {
case DbTableType.VIEW:
case DbTableType.TABLE:
loc6.Add(object_id);
break;
case DbTableType.StoreProcedure:
loc66.Add(object_id);
break;
}
}
if (loc6.Count == 0) return loc1;
var loc8 = string.Join(",", loc6.Select(a => string.Concat(a)));
var loc88 = string.Join(",", loc66.Select(a => string.Concat(a)));
var tsql_place = @"
select
isnull(e.name,'') + '.' + isnull(d.name,'')
,a.Object_id
,a.name 'Column'
,b.name 'Type'
,case
when b.name in ('Text', 'NText', 'Image') then -1
when b.name in ('NChar', 'NVarchar') then a.max_length / 2
else a.max_length end 'Length'
,b.name + case
when b.name in ('Char', 'VarChar', 'NChar', 'NVarChar', 'Binary', 'VarBinary') then '(' +
case when a.max_length = -1 then 'MAX'
when b.name in ('NChar', 'NVarchar') then cast(a.max_length / 2 as varchar)
else cast(a.max_length as varchar) end + ')'
when b.name in ('Numeric', 'Decimal') then '(' + cast(a.precision as varchar) + ',' + cast(a.scale as varchar) + ')'
else '' end as 'SqlType'
,c.value
{0} a
inner join sys.types b on b.user_type_id = a.user_type_id
left join sys.extended_properties AS c ON c.major_id = a.object_id AND c.minor_id = a.column_id
left join sys.tables d on d.object_id = a.object_id
left join sys.schemas e on e.schema_id = d.schema_id
where a.object_id in ({1})
";
sql = string.Format(tsql_place, @"
,a.is_nullable 'IsNullable'
,a.is_identity 'IsIdentity'
from sys.columns", loc8);
if (loc88.Length > 0) {
sql += "union all" +
string.Format(tsql_place.Replace(
"left join sys.extended_properties AS c ON c.major_id = a.object_id AND c.minor_id = a.column_id",
"left join sys.extended_properties AS c ON c.major_id = a.object_id AND c.minor_id = a.parameter_id"), @"
,cast(0 as bit) 'IsNullable'
,a.is_output 'IsIdentity'
from sys.parameters", loc88);
}
sql = $"use [{db}];{sql};use [{olddatabase}]; ";
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
foreach (object[] row in ds) {
var table_id = string.Concat(row[0]);
var object_id = int.Parse(string.Concat(row[1]));
var column = string.Concat(row[2]);
var type = string.Concat(row[3]);
var max_length = int.Parse(string.Concat(row[4]));
var sqlType = string.Concat(row[5]);
var comment = string.Concat(row[6]);
var is_nullable = bool.Parse(string.Concat(row[7]));
var is_identity = bool.Parse(string.Concat(row[8]));
if (max_length == 0) max_length = -1;
loc3[object_id].Add(column, new DbColumnInfo {
Name = column,
MaxLength = max_length,
IsIdentity = is_identity,
IsNullable = is_nullable,
IsPrimary = false,
DbTypeText = type,
DbTypeTextFull = sqlType,
Table = loc2[object_id],
Coment = comment
});
loc3[object_id][column].DbType = this.GetDbType(loc3[object_id][column]);
loc3[object_id][column].CsType = this.GetCsTypeInfo(loc3[object_id][column]);
}
sql = $@"
use [{db}];
select
a.object_id 'Object_id'
,c.name 'Column'
,d.name 'Index_id'
,b.is_unique 'IsUnique'
,b.is_primary_key 'IsPrimaryKey'
,cast(case when b.type_desc = 'CLUSTERED' then 1 else 0 end as bit) 'IsClustered'
,case when a.is_descending_key = 1 then 2 when a.is_descending_key = 0 then 1 else 0 end 'IsDesc'
from sys.index_columns a
inner join sys.indexes b on b.object_id = a.object_id and b.index_id = a.index_id
left join sys.columns c on c.object_id = a.object_id and c.column_id = a.column_id
left join sys.key_constraints d on d.parent_object_id = b.object_id and d.unique_index_id = b.index_id
where a.object_id in ({loc8})
;
use [{olddatabase}];
";
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var indexColumns = new Dictionary<int, Dictionary<string, List<DbColumnInfo>>>();
var uniqueColumns = new Dictionary<int, Dictionary<string, List<DbColumnInfo>>>();
foreach (object[] row in ds) {
int object_id = int.Parse(string.Concat(row[0]));
string column = string.Concat(row[1]);
string index_id = string.Concat(row[2]);
bool is_unique = bool.Parse(string.Concat(row[3]));
bool is_primary_key = bool.Parse(string.Concat(row[4]));
bool is_clustered = bool.Parse(string.Concat(row[5]));
int is_desc = int.Parse(string.Concat(row[6]));
if (loc3.ContainsKey(object_id) == false || loc3[object_id].ContainsKey(column) == false) continue;
DbColumnInfo loc9 = loc3[object_id][column];
if (loc9.IsPrimary == false && is_primary_key) loc9.IsPrimary = is_primary_key;
Dictionary<string, List<DbColumnInfo>> loc10 = null;
List<DbColumnInfo> loc11 = null;
if (!indexColumns.TryGetValue(object_id, out loc10))
indexColumns.Add(object_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
if (!loc10.TryGetValue(index_id, out loc11))
loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
loc11.Add(loc9);
if (is_unique && !is_primary_key) {
if (!uniqueColumns.TryGetValue(object_id, out loc10))
uniqueColumns.Add(object_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
if (!loc10.TryGetValue(index_id, out loc11))
loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
loc11.Add(loc9);
}
}
foreach (var object_id in indexColumns.Keys) {
foreach (var column in indexColumns[object_id])
loc2[object_id].IndexesDict.Add(column.Key, column.Value);
}
foreach (var object_id in uniqueColumns.Keys) {
foreach (var column in uniqueColumns[object_id]) {
column.Value.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
loc2[object_id].UniquesDict.Add(column.Key, column.Value);
}
}
sql = $@"
use [{db}];
select
b.object_id 'Object_id'
,c.name 'Column'
,e.name 'FKId'
,a.referenced_object_id
,cast(1 as bit) 'IsForeignKey'
,d.name 'Referenced_Column'
,null 'Referenced_Sln'
,null 'Referenced_Table'
from sys.foreign_key_columns a
inner join sys.tables b on b.object_id = a.parent_object_id
inner join sys.columns c on c.object_id = a.parent_object_id and c.column_id = a.parent_column_id
inner join sys.columns d on d.object_id = a.referenced_object_id and d.column_id = a.referenced_column_id
left join sys.foreign_keys e on e.object_id = a.constraint_object_id
where b.object_id in ({loc8})
;
use [{olddatabase}];
";
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var fkColumns = new Dictionary<int, Dictionary<string, DbForeignInfo>>();
foreach (object[] row in ds) {
int object_id, referenced_object_id;
int.TryParse(string.Concat(row[0]), out object_id);
var column = string.Concat(row[1]);
string fk_id = string.Concat(row[2]);
int.TryParse(string.Concat(row[3]), out referenced_object_id);
var is_foreign_key = bool.Parse(string.Concat(row[4]));
var referenced_column = string.Concat(row[5]);
var referenced_db = string.Concat(row[6]);
var referenced_table = string.Concat(row[7]);
DbColumnInfo loc9 = loc3[object_id][column];
DbTableInfo loc10 = null;
DbColumnInfo loc11 = null;
bool isThisSln = referenced_object_id != 0;
if (isThisSln) {
loc10 = loc2[referenced_object_id];
loc11 = loc3[referenced_object_id][referenced_column];
} else {
}
Dictionary<string, DbForeignInfo> loc12 = null;
DbForeignInfo loc13 = null;
if (!fkColumns.TryGetValue(object_id, out loc12))
fkColumns.Add(object_id, loc12 = new Dictionary<string, DbForeignInfo>());
if (!loc12.TryGetValue(fk_id, out loc13))
loc12.Add(fk_id, loc13 = new DbForeignInfo { Table = loc2[object_id], ReferencedTable = loc10 });
loc13.Columns.Add(loc9);
loc13.ReferencedColumns.Add(loc11);
}
foreach (var table_id in fkColumns.Keys)
foreach (var fk in fkColumns[table_id])
loc2[table_id].ForeignsDict.Add(fk.Key, fk.Value);
foreach (var table_id in loc3.Keys) {
foreach (var loc5 in loc3[table_id].Values) {
loc2[table_id].Columns.Add(loc5);
if (loc5.IsIdentity) loc2[table_id].Identitys.Add(loc5);
if (loc5.IsPrimary) loc2[table_id].Primarys.Add(loc5);
}
}
foreach (var loc4 in loc2.Values) {
if (loc4.Primarys.Count == 0 && loc4.UniquesDict.Count > 0) {
foreach (var loc5 in loc4.UniquesDict.First().Value) {
loc5.IsPrimary = true;
loc4.Primarys.Add(loc5);
}
}
loc4.Primarys.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
loc4.Columns.Sort((c1, c2) => {
int compare = c2.IsPrimary.CompareTo(c1.IsPrimary);
if (compare == 0) {
bool b1 = loc4.ForeignsDict.Values.Where(fk => fk.Columns.Where(c3 => c3.Name == c1.Name).Any()).Any();
bool b2 = loc4.ForeignsDict.Values.Where(fk => fk.Columns.Where(c3 => c3.Name == c2.Name).Any()).Any();
compare = b2.CompareTo(b1);
}
if (compare == 0) compare = c1.Name.CompareTo(c2.Name);
return compare;
});
loc1.Add(loc4);
}
loc1.Sort((t1, t2) => {
var ret = t1.Schema.CompareTo(t2.Schema);
if (ret == 0) ret = t1.Name.CompareTo(t2.Name);
return ret;
});
loc2.Clear();
loc3.Clear();
tables.AddRange(loc1);
}
return tables;
}
public List<DbEnumInfo> GetEnumsByDatabase(params string[] database) {
return new List<DbEnumInfo>();
}
}
}

View File

@ -1,383 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace FreeSql.SqlServer {
class SqlServerExpression : CommonExpression {
public SqlServerExpression(CommonUtils common) : base(common) { }
internal override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
switch (exp.NodeType) {
case ExpressionType.Convert:
var operandExp = (exp as UnaryExpression)?.Operand;
var gentype = exp.Type.NullableTypeOrThis();
if (gentype != operandExp.Type.NullableTypeOrThis()) {
switch (gentype.ToString()) {
case "System.Boolean": return $"(cast({getExp(operandExp)} as varchar) not in ('0','false'))";
case "System.Byte": return $"cast({getExp(operandExp)} as tinyint)";
case "System.Char": return $"substring(cast({getExp(operandExp)} as nvarchar),1,1)";
case "System.DateTime": return $"cast({getExp(operandExp)} as datetime)";
case "System.Decimal": return $"cast({getExp(operandExp)} as decimal(36,18))";
case "System.Double": return $"cast({getExp(operandExp)} as decimal(32,16))";
case "System.Int16": return $"cast({getExp(operandExp)} as smallint)";
case "System.Int32": return $"cast({getExp(operandExp)} as int)";
case "System.Int64": return $"cast({getExp(operandExp)} as bigint)";
case "System.SByte": return $"cast({getExp(operandExp)} as tinyint)";
case "System.Single": return $"cast({getExp(operandExp)} as decimal(14,7))";
case "System.String": return operandExp.Type.NullableTypeOrThis() == typeof(Guid) ? $"cast({getExp(operandExp)} as varchar(36))" : $"cast({getExp(operandExp)} as nvarchar)";
case "System.UInt16": return $"cast({getExp(operandExp)} as smallint)";
case "System.UInt32": return $"cast({getExp(operandExp)} as int)";
case "System.UInt64": return $"cast({getExp(operandExp)} as bigint)";
case "System.Guid": return $"cast({getExp(operandExp)} as uniqueidentifier)";
}
}
break;
case ExpressionType.Call:
var callExp = exp as MethodCallExpression;
switch(callExp.Method.Name) {
case "Parse":
case "TryParse":
switch (callExp.Method.DeclaringType.NullableTypeOrThis().ToString()) {
case "System.Boolean": return $"(cast({getExp(callExp.Arguments[0])} as varchar) not in ('0','false'))";
case "System.Byte": return $"cast({getExp(callExp.Arguments[0])} as tinyint)";
case "System.Char": return $"substring(cast({getExp(callExp.Arguments[0])} as nvarchar),1,1)";
case "System.DateTime": return $"cast({getExp(callExp.Arguments[0])} as datetime)";
case "System.Decimal": return $"cast({getExp(callExp.Arguments[0])} as decimal(36,18))";
case "System.Double": return $"cast({getExp(callExp.Arguments[0])} as decimal(32,16))";
case "System.Int16": return $"cast({getExp(callExp.Arguments[0])} as smallint)";
case "System.Int32": return $"cast({getExp(callExp.Arguments[0])} as int)";
case "System.Int64": return $"cast({getExp(callExp.Arguments[0])} as bigint)";
case "System.SByte": return $"cast({getExp(callExp.Arguments[0])} as tinyint)";
case "System.Single": return $"cast({getExp(callExp.Arguments[0])} as decimal(14,7))";
case "System.UInt16": return $"cast({getExp(callExp.Arguments[0])} as smallint)";
case "System.UInt32": return $"cast({getExp(callExp.Arguments[0])} as int)";
case "System.UInt64": return $"cast({getExp(callExp.Arguments[0])} as bigint)";
case "System.Guid": return $"cast({getExp(callExp.Arguments[0])} as uniqueidentifier)";
}
break;
case "NewGuid":
switch (callExp.Method.DeclaringType.NullableTypeOrThis().ToString()) {
case "System.Guid": return $"newid()";
}
break;
case "Next":
if (callExp.Object?.Type == typeof(Random)) return "cast(rand()*1000000000 as int)";
break;
case "NextDouble":
if (callExp.Object?.Type == typeof(Random)) return "rand()";
break;
case "Random":
if (callExp.Method.DeclaringType.IsNumberType()) return "rand()";
break;
case "ToString":
if (callExp.Object != null) return callExp.Object.Type.NullableTypeOrThis() == typeof(Guid) ? $"cast({getExp(callExp.Object)} as varchar(36))" : $"cast({getExp(callExp.Object)} as nvarchar)";
break;
}
var objExp = callExp.Object;
var objType = objExp?.Type;
if (objType?.FullName == "System.Byte[]") return null;
var argIndex = 0;
if (objType == null && callExp.Method.DeclaringType == typeof(Enumerable)) {
objExp = callExp.Arguments.FirstOrDefault();
objType = objExp?.Type;
argIndex++;
}
if (objType == null) objType = callExp.Method.DeclaringType;
if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) {
var left = objExp == null ? null : getExp(objExp);
switch (callExp.Method.Name) {
case "Contains":
//判断 in
return $"({getExp(callExp.Arguments[argIndex])}) in {left}";
}
}
break;
case ExpressionType.NewArrayInit:
var arrExp = exp as NewArrayExpression;
var arrSb = new StringBuilder();
arrSb.Append("(");
for (var a = 0; a < arrExp.Expressions.Count; a++) {
if (a > 0) arrSb.Append(",");
arrSb.Append(getExp(arrExp.Expressions[a]));
}
if (arrSb.Length == 1) arrSb.Append("NULL");
return arrSb.Append(")").ToString();
case ExpressionType.ListInit:
var listExp = exp as ListInitExpression;
var listSb = new StringBuilder();
listSb.Append("(");
for (var a = 0; a < listExp.Initializers.Count; a++) {
if (listExp.Initializers[a].Arguments.Any() == false) continue;
if (a > 0) listSb.Append(",");
listSb.Append(getExp(listExp.Initializers[a].Arguments.FirstOrDefault()));
}
if (listSb.Length == 1) listSb.Append("NULL");
return listSb.Append(")").ToString();
case ExpressionType.New:
var newExp = exp as NewExpression;
if (typeof(IList).IsAssignableFrom(newExp.Type)) {
if (newExp.Arguments.Count == 0) return "(NULL)";
if (typeof(IEnumerable).IsAssignableFrom(newExp.Arguments[0].Type) == false) return "(NULL)";
return getExp(newExp.Arguments[0]);
}
return null;
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Empty": return "''";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Length": return $"len({left})";
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Now": return "getdate()";
case "UtcNow": return "getutcdate()";
case "Today": return "convert(char(10),getdate(),120)";
case "MinValue": return "'1753/1/1 0:00:00'";
case "MaxValue": return "'9999/12/31 23:59:59'";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Date": return $"convert(char(10),{left},120)";
case "TimeOfDay": return $"datediff(second, convert(char(10),{left},120), {left})";
case "DayOfWeek": return $"(datepart(weekday, {left})-1)";
case "Day": return $"datepart(day, {left})";
case "DayOfYear": return $"datepart(dayofyear, {left})";
case "Month": return $"datepart(month, {left})";
case "Year": return $"datepart(year, {left})";
case "Hour": return $"datepart(hour, {left})";
case "Minute": return $"datepart(minute, {left})";
case "Second": return $"datepart(second, {left})";
case "Millisecond": return $"(datepart(millisecond, {left})/1000)";
case "Ticks": return $"(cast(datediff(second, '1970-1-1', {left}) as bigint)*10000000+621355968000000000)";
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Zero": return "0";
case "MinValue": return "-922337203685477580"; //微秒 Ticks / 10
case "MaxValue": return "922337203685477580";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Days": return $"floor(({left})/{60 * 60 * 24})";
case "Hours": return $"floor(({left})/{60 * 60}%24)";
case "Milliseconds": return $"(cast({left} as bigint)*1000)";
case "Minutes": return $"floor(({left})/60%60)";
case "Seconds": return $"(({left})%60)";
case "Ticks": return $"(cast({left} as bigint)*10000000)";
case "TotalDays": return $"(({left})/{60 * 60 * 24})";
case "TotalHours": return $"(({left})/{60 * 60})";
case "TotalMilliseconds": return $"(cast({left} as bigint)*1000)";
case "TotalMinutes": return $"(({left})/60)";
case "TotalSeconds": return $"({left})";
}
return null;
}
internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "IsNullOrEmpty":
var arg1 = getExp(exp.Arguments[0]);
return $"({arg1} is null or {arg1} = '')";
case "Concat":
return _common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), exp.Arguments.Select(a => a.Type).ToArray());
}
} else {
var left = getExp(exp.Object);
switch (exp.Method.Name) {
case "StartsWith":
case "EndsWith":
case "Contains":
var args0Value = getExp(exp.Arguments[0]);
if (args0Value == "NULL") return $"({left}) IS NULL";
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(cast({args0Value} as nvarchar)+'%')")}";
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%'+cast({args0Value} as nvarchar))")}";
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
return $"({left}) LIKE ('%'+cast({args0Value} as nvarchar)+'%')";
case "ToLower": return $"lower({left})";
case "ToUpper": return $"upper({left})";
case "Substring":
var substrArgs1 = getExp(exp.Arguments[0]);
if (long.TryParse(substrArgs1, out var testtrylng1)) substrArgs1 = (testtrylng1 + 1).ToString();
else substrArgs1 += "+1";
if (exp.Arguments.Count == 1) return $"left({left}, {substrArgs1})";
return $"substring({left}, {substrArgs1}, {getExp(exp.Arguments[1])})";
case "IndexOf":
var indexOfFindStr = getExp(exp.Arguments[0]);
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") {
var locateArgs1 = getExp(exp.Arguments[1]);
if (long.TryParse(locateArgs1, out var testtrylng2)) locateArgs1 = (testtrylng2 + 1).ToString();
else locateArgs1 += "+1";
return $"(charindex({left}, {indexOfFindStr}, {locateArgs1})-1)";
}
return $"(charindex({left}, {indexOfFindStr})-1)";
case "PadLeft":
if (exp.Arguments.Count == 1) return $"lpad({left}, {getExp(exp.Arguments[0])})";
return $"lpad({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "PadRight":
if (exp.Arguments.Count == 1) return $"rpad({left}, {getExp(exp.Arguments[0])})";
return $"rpad({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "Trim": return $"ltrim(rtrim({left}))";
case "TrimStart": return $"ltrim({left})";
case "TrimEnd": return $"rtrim({left})";
case "Replace": return $"replace({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "CompareTo": return $"({left} - {getExp(exp.Arguments[0])})";
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
}
}
throw new Exception($"SqlServerExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
switch (exp.Method.Name) {
case "Abs": return $"abs({getExp(exp.Arguments[0])})";
case "Sign": return $"sign({getExp(exp.Arguments[0])})";
case "Floor": return $"floor({getExp(exp.Arguments[0])})";
case "Ceiling": return $"ceiling({getExp(exp.Arguments[0])})";
case "Round":
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"round({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
return $"round({getExp(exp.Arguments[0])}, 0)";
case "Exp": return $"exp({getExp(exp.Arguments[0])})";
case "Log": return $"log({getExp(exp.Arguments[0])})";
case "Log10": return $"log10({getExp(exp.Arguments[0])})";
case "Pow": return $"power({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "Sqrt": return $"sqrt({getExp(exp.Arguments[0])})";
case "Cos": return $"cos({getExp(exp.Arguments[0])})";
case "Sin": return $"sin({getExp(exp.Arguments[0])})";
case "Tan": return $"tan({getExp(exp.Arguments[0])})";
case "Acos": return $"acos({getExp(exp.Arguments[0])})";
case "Asin": return $"asin({getExp(exp.Arguments[0])})";
case "Atan": return $"atan({getExp(exp.Arguments[0])})";
case "Atan2": return $"atan2({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "Truncate": return $"floor({getExp(exp.Arguments[0])})";
}
throw new Exception($"SqlServerExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "Compare": return $"({getExp(exp.Arguments[0])} - ({getExp(exp.Arguments[1])}))";
case "DaysInMonth": return $"datepart(day, dateadd(day, -1, dateadd(month, 1, cast({getExp(exp.Arguments[0])} as varchar) + '-' + cast({getExp(exp.Arguments[1])} as varchar) + '-1')))";
case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})";
case "IsLeapYear":
var isLeapYearArgs1 = getExp(exp.Arguments[0]);
return $"(({isLeapYearArgs1})%4=0 AND ({isLeapYearArgs1})%100<>0 OR ({isLeapYearArgs1})%400=0)";
case "Parse": return $"cast({getExp(exp.Arguments[0])} as datetime)";
case "ParseExact":
case "TryParse":
case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as datetime)";
}
} else {
var left = getExp(exp.Object);
var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]);
switch (exp.Method.Name) {
case "Add": return $"dateadd(second, {args1}, {left})";
case "AddDays": return $"dateadd(day, {args1}, {left})";
case "AddHours": return $"dateadd(hour, {args1}, {left})";
case "AddMilliseconds": return $"dateadd(second, ({args1})/1000, {left})";
case "AddMinutes": return $"dateadd(minute, {args1}, {left})";
case "AddMonths": return $"dateadd(month, {args1}, {left})";
case "AddSeconds": return $"dateadd(second, {args1}, {left})";
case "AddTicks": return $"dateadd(second, ({args1})/10000000, {left})";
case "AddYears": return $"dateadd(year, {args1}, {left})";
case "Subtract":
switch ((exp.Arguments[0].Type.IsNullableType() ? exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault() : exp.Arguments[0].Type).FullName) {
case "System.DateTime": return $"datediff(second, {args1}, {left})";
case "System.TimeSpan": return $"dateadd(second, {args1}*-1, {left})";
}
break;
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
case "CompareTo": return $"datediff(second,{getExp(exp.Arguments[0])},{left})";
case "ToString": return $"convert(varchar, {left}, 121)";
}
}
throw new Exception($"SqlServerExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "Compare": return $"({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])}))";
case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})";
case "FromDays": return $"(({getExp(exp.Arguments[0])})*{60 * 60 * 24})";
case "FromHours": return $"(({getExp(exp.Arguments[0])})*{60 * 60})";
case "FromMilliseconds": return $"(({getExp(exp.Arguments[0])})/1000)";
case "FromMinutes": return $"(({getExp(exp.Arguments[0])})*60)";
case "FromSeconds": return $"({getExp(exp.Arguments[0])})";
case "FromTicks": return $"(({getExp(exp.Arguments[0])})/10000000)";
case "Parse": return $"cast({getExp(exp.Arguments[0])} as bigint)";
case "ParseExact":
case "TryParse":
case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as bigint)";
}
} else {
var left = getExp(exp.Object);
var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]);
switch (exp.Method.Name) {
case "Add": return $"({left}+{args1})";
case "Subtract": return $"({left}-({args1}))";
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
case "CompareTo": return $"({left}-({getExp(exp.Arguments[0])}))";
case "ToString": return $"cast({left} as varchar)";
}
}
throw new Exception($"SqlServerExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "ToBoolean": return $"(cast({getExp(exp.Arguments[0])} as varchar) not in ('0','false'))";
case "ToByte": return $"cast({getExp(exp.Arguments[0])} as tinyint)";
case "ToChar": return $"substring(cast({getExp(exp.Arguments[0])} as nvarchar),1,1)";
case "ToDateTime": return $"cast({getExp(exp.Arguments[0])} as datetime)";
case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as decimal(36,18))";
case "ToDouble": return $"cast({getExp(exp.Arguments[0])} as decimal(32,16))";
case "ToInt16": return $"cast({getExp(exp.Arguments[0])} as smallint)";
case "ToInt32": return $"cast({getExp(exp.Arguments[0])} as int)";
case "ToInt64": return $"cast({getExp(exp.Arguments[0])} as bigint)";
case "ToSByte": return $"cast({getExp(exp.Arguments[0])} as tinyint)";
case "ToSingle": return $"cast({getExp(exp.Arguments[0])} as decimal(14,7))";
case "ToString": return exp.Arguments[0].Type.NullableTypeOrThis() == typeof(Guid) ? $"cast({getExp(exp.Arguments[0])} as varchar(36))" : $"cast({getExp(exp.Arguments[0])} as nvarchar)";
case "ToUInt16": return $"cast({getExp(exp.Arguments[0])} as smallint)";
case "ToUInt32": return $"cast({getExp(exp.Arguments[0])} as int)";
case "ToUInt64": return $"cast({getExp(exp.Arguments[0])} as bigint)";
}
}
throw new Exception($"SqlServerExpression 未实现函数表达式 {exp} 解析");
}
}
}

View File

@ -1,11 +0,0 @@
public static partial class FreeSqlGlobalExtensions {
/// <summary>
/// 特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换
/// </summary>
/// <param name="that"></param>
/// <param name="args"></param>
/// <returns></returns>
public static string FormatSqlServer(this string that, params object[] args) => _sqlserverAdo.Addslashes(that, args);
static FreeSql.SqlServer.SqlServerAdo _sqlserverAdo = new FreeSql.SqlServer.SqlServerAdo();
}

View File

@ -1,69 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.CommonProvider;
using FreeSql.SqlServer.Curd;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
namespace FreeSql.SqlServer {
class SqlServerProvider<TMark> : IFreeSql<TMark> {
public ISelect<T1> Select<T1>() where T1 : class => new SqlServerSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public ISelect<T1> Select<T1>(object dywhere) where T1 : class => new SqlServerSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsert<T1> Insert<T1>() where T1 : class => new SqlServerInsert<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IInsert<T1> Insert<T1>(T1 source) where T1 : class => this.Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(T1[] source) where T1 : class => this.Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(IEnumerable<T1> source) where T1 : class => this.Insert<T1>().AppendData(source);
public IUpdate<T1> Update<T1>() where T1 : class => new SqlServerUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new SqlServerUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new SqlServerDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new SqlServerDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IAdo Ado { get; }
public IAop Aop { get; }
public ICache Cache { get; }
public ICodeFirst CodeFirst { get; }
public IDbFirst DbFirst { get; }
public SqlServerProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) {
if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.SqlServer");
this.InternalCommonUtils = new SqlServerUtils(this);
this.InternalCommonExpression = new SqlServerExpression(this.InternalCommonUtils);
this.Cache = new CacheProvider(cache, log);
this.Ado = new SqlServerAdo(this.InternalCommonUtils, this.Cache, log, masterConnectionString, slaveConnectionString);
this.Aop = new AopProvider();
this.DbFirst = new SqlServerDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
this.CodeFirst = new SqlServerCodeFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
if (this.Ado.MasterPool != null)
using (var conn = this.Ado.MasterPool.Get()) {
try {
(this.InternalCommonUtils as SqlServerUtils).IsSelectRowNumber = int.Parse(conn.Value.ServerVersion.Split('.')[0]) <= 10;
} catch {
}
}
}
internal CommonUtils InternalCommonUtils { get; }
internal CommonExpression InternalCommonExpression { get; }
public void Transaction(Action handler) => Ado.Transaction(handler);
public void Transaction(Action handler, TimeSpan timeout) => Ado.Transaction(handler, timeout);
~SqlServerProvider() {
this.Dispose();
}
bool _isdisposed = false;
public void Dispose() {
if (_isdisposed) return;
(this.Ado as AdoProvider).Dispose();
(this.Cache as CacheProvider)?.Dispose();
}
}
}

View File

@ -1,81 +0,0 @@
using FreeSql.Internal;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
namespace FreeSql.SqlServer {
class SqlServerUtils : CommonUtils {
public SqlServerUtils(IFreeSql orm) : base(orm) {
}
internal bool IsSelectRowNumber = true;
internal override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value) {
if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}";
if (value?.Equals(DateTime.MinValue) == true) value = new DateTime(1970, 1, 1);
var ret = new SqlParameter { ParameterName = QuoteParamterName(parameterName), Value = value };
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null) ret.SqlDbType = (SqlDbType)tp.Value;
_params?.Add(ret);
return ret;
}
internal override DbParameter[] GetDbParamtersByObject(string sql, object obj) =>
Utils.GetDbParamtersByObject<SqlParameter>(sql, obj, "@", (name, type, value) => {
if (value?.Equals(DateTime.MinValue) == true) value = new DateTime(1970, 1, 1);
var ret = new SqlParameter { ParameterName = $"@{name}", Value = value };
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
if (tp != null) ret.SqlDbType = (SqlDbType)tp.Value;
return ret;
});
internal override string FormatSql(string sql, params object[] args) => sql?.FormatSqlServer(args);
internal override string QuoteSqlName(string name) {
var nametrim = name.Trim();
if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
return nametrim; //原生SQL
return $"[{nametrim.TrimStart('[').TrimEnd(']').Replace(".", "].[")}]";
}
internal override string TrimQuoteSqlName(string name) {
var nametrim = name.Trim();
if (nametrim.StartsWith("(") && nametrim.EndsWith(")"))
return nametrim; //原生SQL
return $"{nametrim.TrimStart('[').TrimEnd(']').Replace("].[", ".").Replace(".[", ".")}";
}
internal override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
internal override string IsNull(string sql, object value) => $"isnull({sql}, {value})";
internal override string StringConcat(string[] objs, Type[] types) {
var sb = new StringBuilder();
var news = new string[objs.Length];
for (var a = 0; a < objs.Length; a++)
news[a] = types[a] == typeof(string) ? objs[a] : $"cast({objs[a]} as nvarchar)";
return string.Join(" + ", news);
}
internal override string Mod(string left, string right, Type leftType, Type rightType) => $"{left} % {right}";
internal override string QuoteWriteParamter(Type type, string paramterName) => paramterName;
internal override string QuoteReadColumn(Type type, string columnName) => columnName;
internal override string GetNoneParamaterSqlValue(List<DbParameter> specialParams, Type type, object value) {
if (value == null) return "NULL";
if (type == typeof(byte[])) {
var bytes = value as byte[];
var sb = new StringBuilder().Append("0x");
foreach (var vc in bytes) {
if (vc < 10) sb.Append("0");
sb.Append(vc.ToString("X"));
}
return sb.ToString();
} else if (type == typeof(TimeSpan) || type == typeof(TimeSpan?)) {
var ts = (TimeSpan)value;
value = $"{ts.Hours}:{ts.Minutes}:{ts.Seconds}.{ts.Milliseconds}";
}
return FormatSql("{0}", value, 1);
}
}
}

View File

@ -1,22 +0,0 @@
using FreeSql.Internal;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.Sqlite.Curd {
class SqliteDelete<T1> : Internal.CommonProvider.DeleteProvider<T1> where T1 : class {
public SqliteDelete(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
: base(orm, commonUtils, commonExpression, dywhere) {
}
public override List<T1> ExecuteDeleted() {
throw new NotImplementedException();
}
public override Task<List<T1>> ExecuteDeletedAsync() {
throw new NotImplementedException();
}
}
}

View File

@ -1,81 +0,0 @@
using FreeSql.Internal;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.Sqlite.Curd {
class SqliteInsert<T1> : Internal.CommonProvider.InsertProvider<T1> where T1 : class {
public SqliteInsert(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression) {
}
public override int ExecuteAffrows() => base.SplitExecuteAffrows(5000, 999);
public override Task<int> ExecuteAffrowsAsync() => base.SplitExecuteAffrowsAsync(5000, 999);
public override long ExecuteIdentity() => base.SplitExecuteIdentity(5000, 999);
public override Task<long> ExecuteIdentityAsync() => base.SplitExecuteIdentityAsync(5000, 999);
public override List<T1> ExecuteInserted() => base.SplitExecuteInserted(5000, 999);
public override Task<List<T1>> ExecuteInsertedAsync() => base.SplitExecuteInsertedAsync(5000, 999);
internal override long RawExecuteIdentity() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
sql = string.Concat(sql, "; SELECT last_insert_rowid();");
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
long ret = 0;
Exception exception = null;
try {
long.TryParse(string.Concat(_orm.Ado.ExecuteScalar(_connection, _transaction, CommandType.Text, sql, _params)), out ret);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
async internal override Task<long> RawExecuteIdentityAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
sql = string.Concat(sql, "; SELECT last_insert_rowid();");
var before = new Aop.CurdBeforeEventArgs(_table.Type, Aop.CurdType.Insert, sql, _params);
_orm.Aop.CurdBefore?.Invoke(this, before);
long ret = 0;
Exception exception = null;
try {
long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync(_connection, _transaction, CommandType.Text, sql, _params)), out ret);
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.CurdAfterEventArgs(before, exception, ret);
_orm.Aop.CurdAfter?.Invoke(this, after);
}
this.ClearData();
return ret;
}
internal override List<T1> RawExecuteInserted() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
this.RawExecuteAffrows();
return _source;
}
async internal override Task<List<T1>> RawExecuteInsertedAsync() {
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return new List<T1>();
await this.RawExecuteAffrowsAsync();
return _source;
}
}
}

View File

@ -1,128 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace FreeSql.Sqlite.Curd {
class SqliteSelect<T1> : FreeSql.Internal.CommonProvider.Select1Provider<T1> where T1 : class {
internal static string ToSqlStatic(CommonUtils _commonUtils, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables, Func<Type, string, string> tableRuleInvoke, IFreeSql _orm) {
if (_orm.CodeFirst.IsAutoSyncStructure)
_orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray());
var sb = new StringBuilder();
var sbnav = new StringBuilder();
sb.Append(_select);
if (_distinct) sb.Append("DISTINCT ");
sb.Append(field).Append(" \r\nFROM ");
var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray();
var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray();
for (var a = 0; a < tbsfrom.Length; a++) {
sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[a].Table.Type, tbsfrom[a].Table.DbName))).Append(" ").Append(tbsfrom[a].Alias);
if (tbsjoin.Length > 0) {
//如果存在 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(tableRuleInvoke(tbsfrom[b].Table.Type, tbsfrom[b].Table.DbName))).Append(" ").Append(tbsfrom[b].Alias);
if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On)) sb.Append(" ON 1 = 1");
else sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On);
}
break;
} else {
if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")");
if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")");
}
if (a < tbsfrom.Length - 1) sb.Append(", ");
}
foreach (var tb in tbsjoin) {
if (tb.Type == SelectTableInfoType.Parent) continue;
switch (tb.Type) {
case SelectTableInfoType.LeftJoin:
sb.Append(" \r\nLEFT JOIN ");
break;
case SelectTableInfoType.InnerJoin:
sb.Append(" \r\nINNER JOIN ");
break;
case SelectTableInfoType.RightJoin:
sb.Append(" \r\nRIGHT JOIN ");
break;
}
sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tb.Table.Type, tb.Table.DbName))).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition);
if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")");
}
if (_join.Length > 0) sb.Append(_join);
sbnav.Append(_where);
foreach (var tb in _tables) {
if (tb.Type == SelectTableInfoType.Parent) continue;
if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false)
sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")");
}
if (sbnav.Length > 0) {
sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5));
}
if (string.IsNullOrEmpty(_groupby) == false) {
sb.Append(_groupby);
if (string.IsNullOrEmpty(_having) == false)
sb.Append(" \r\nHAVING ").Append(_having.Substring(5));
}
sb.Append(_orderby);
if (_skip > 0 || _limit > 0)
sb.Append(" \r\nlimit ").Append(Math.Max(0, _skip)).Append(",").Append(_limit > 0 ? _limit : -1);
sbnav.Clear();
return sb.ToString();
}
public SqliteSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override ISelect<T1, T2> From<T2>(Expression<Func<ISelectFromExpression<T1>, T2, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqliteSelect<T1, T2>(_orm, _commonUtils, _commonExpression, null); SqliteSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3> From<T2, T3>(Expression<Func<ISelectFromExpression<T1>, T2, T3, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqliteSelect<T1, T2, T3>(_orm, _commonUtils, _commonExpression, null); SqliteSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4> From<T2, T3, T4>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqliteSelect<T1, T2, T3, T4>(_orm, _commonUtils, _commonExpression, null); SqliteSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5> From<T2, T3, T4, T5>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqliteSelect<T1, T2, T3, T4, T5>(_orm, _commonUtils, _commonExpression, null); SqliteSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6> From<T2, T3, T4, T5, T6>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqliteSelect<T1, T2, T3, T4, T5, T6>(_orm, _commonUtils, _commonExpression, null); SqliteSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7> From<T2, T3, T4, T5, T6, T7>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqliteSelect<T1, T2, T3, T4, T5, T6, T7>(_orm, _commonUtils, _commonExpression, null); SqliteSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8> From<T2, T3, T4, T5, T6, T7, T8>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqliteSelect<T1, T2, T3, T4, T5, T6, T7, T8>(_orm, _commonUtils, _commonExpression, null); SqliteSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> From<T2, T3, T4, T5, T6, T7, T8, T9>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqliteSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>(_orm, _commonUtils, _commonExpression, null); SqliteSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new SqliteSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); SqliteSelect<T1>.CopyData(this, ret, exp?.Parameters); return ret; }
public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqliteSelect<T1, T2> : FreeSql.Internal.CommonProvider.Select2Provider<T1, T2> where T1 : class where T2 : class {
public SqliteSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqliteSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqliteSelect<T1, T2, T3> : FreeSql.Internal.CommonProvider.Select3Provider<T1, T2, T3> where T1 : class where T2 : class where T3 : class {
public SqliteSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqliteSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqliteSelect<T1, T2, T3, T4> : FreeSql.Internal.CommonProvider.Select4Provider<T1, T2, T3, T4> where T1 : class where T2 : class where T3 : class where T4 : class {
public SqliteSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqliteSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqliteSelect<T1, T2, T3, T4, T5> : FreeSql.Internal.CommonProvider.Select5Provider<T1, T2, T3, T4, T5> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class {
public SqliteSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqliteSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqliteSelect<T1, T2, T3, T4, T5, T6> : FreeSql.Internal.CommonProvider.Select6Provider<T1, T2, T3, T4, T5, T6> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class {
public SqliteSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqliteSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqliteSelect<T1, T2, T3, T4, T5, T6, T7> : FreeSql.Internal.CommonProvider.Select7Provider<T1, T2, T3, T4, T5, T6, T7> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class {
public SqliteSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqliteSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqliteSelect<T1, T2, T3, T4, T5, T6, T7, T8> : FreeSql.Internal.CommonProvider.Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class {
public SqliteSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqliteSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqliteSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> : FreeSql.Internal.CommonProvider.Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class {
public SqliteSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqliteSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
class SqliteSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : FreeSql.Internal.CommonProvider.Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class {
public SqliteSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
public override string ToSql(string field = null) => SqliteSelect<T1>.ToSqlStatic(_commonUtils, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, TableRuleInvoke, _orm);
}
}

View File

@ -1,61 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.Sqlite.Curd {
class SqliteUpdate<T1> : Internal.CommonProvider.UpdateProvider<T1> where T1 : class {
public SqliteUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
: base(orm, commonUtils, commonExpression, dywhere) {
}
public override int ExecuteAffrows() => base.SplitExecuteAffrows(200, 999);
public override Task<int> ExecuteAffrowsAsync() => base.SplitExecuteAffrowsAsync(200, 999);
public override List<T1> ExecuteUpdated() => base.SplitExecuteUpdated(200, 999);
public override Task<List<T1>> ExecuteUpdatedAsync() => base.SplitExecuteUpdatedAsync(200, 999);
internal override List<T1> RawExecuteUpdated() {
throw new NotImplementedException();
}
internal override Task<List<T1>> RawExecuteUpdatedAsync() {
throw new NotImplementedException();
}
protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
if (_table.Primarys.Length == 1) {
caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().Attribute.MapType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
return;
}
caseWhen.Append("CONCAT(");
var pkidx = 0;
foreach (var pk in _table.Primarys) {
if (pkidx > 0) caseWhen.Append(", ");
caseWhen.Append(_commonUtils.QuoteReadColumn(pk.Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name)));
++pkidx;
}
caseWhen.Append(")");
}
protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
if (_table.Primarys.Length == 1) {
sb.Append(_commonUtils.FormatSql("{0}", _table.Primarys.First().GetMapValue(d)));
return;
}
sb.Append("CONCAT(");
var pkidx = 0;
foreach (var pk in _table.Primarys) {
if (pkidx > 0) sb.Append(", ");
sb.Append(_commonUtils.FormatSql("{0}", pk.GetMapValue(d)));
++pkidx;
}
sb.Append(")");
}
}
}

View File

@ -1,61 +0,0 @@
using FreeSql.Internal;
using Microsoft.Extensions.Logging;
using SafeObjectPool;
using System;
using System.Collections;
using System.Data.Common;
using System.Data.SQLite;
using System.Text;
using System.Threading;
namespace FreeSql.Sqlite {
class SqliteAdo : FreeSql.Internal.CommonProvider.AdoProvider {
public SqliteAdo() : base(null, null, DataType.Sqlite) { }
public SqliteAdo(CommonUtils util, ICache cache, ILogger log, string masterConnectionString, string[] slaveConnectionStrings) : base(cache, log, DataType.Sqlite) {
base._util = util;
if (!string.IsNullOrEmpty(masterConnectionString))
MasterPool = new SqliteConnectionPool("主库", masterConnectionString, null, null);
if (slaveConnectionStrings != null) {
foreach (var slaveConnectionString in slaveConnectionStrings) {
var slavePool = new SqliteConnectionPool($"从库{SlavePools.Count + 1}", slaveConnectionString, () => Interlocked.Decrement(ref slaveUnavailables), () => Interlocked.Increment(ref slaveUnavailables));
SlavePools.Add(slavePool);
}
}
}
static DateTime dt1970 = new DateTime(1970, 1, 1);
public override object AddslashesProcessParam(object param, Type mapType) {
if (param == null) return "NULL";
if (mapType != null && mapType != param.GetType())
param = Utils.GetDataReaderValue(mapType, param);
if (param is bool || param is bool?)
return (bool)param ? 1 : 0;
else if (param is string || param is char)
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
else if (param is Enum)
return ((Enum)param).ToInt64();
else if (decimal.TryParse(string.Concat(param), out var trydec))
return param;
else if (param is DateTime || param is DateTime?)
return string.Concat("'", ((DateTime)param).ToString("yyyy-MM-dd HH:mm:ss"), "'");
else if (param is TimeSpan || param is TimeSpan?)
return ((TimeSpan)param).Ticks / 10000;
else if (param is IEnumerable) {
var sb = new StringBuilder();
var ie = param as IEnumerable;
foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z, mapType));
return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
}
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
}
protected override DbCommand CreateCommand() {
return new SQLiteCommand();
}
protected override void ReturnConnection(ObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex) {
(pool as SqliteConnectionPool).Return(conn, ex);
}
protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj);
}
}

View File

@ -1,214 +0,0 @@
using SafeObjectPool;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SQLite;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace FreeSql.Sqlite {
class SqliteConnectionPool : ObjectPool<DbConnection> {
internal Action availableHandler;
internal Action unavailableHandler;
public SqliteConnectionPool(string name, string connectionString, Action availableHandler, Action unavailableHandler) : base(null) {
policy = new SqliteConnectionPoolPolicy {
_pool = this,
Name = name
};
this.Policy = policy;
policy.ConnectionString = connectionString;
this.availableHandler = availableHandler;
this.unavailableHandler = unavailableHandler;
}
public void Return(Object<DbConnection> obj, Exception exception, bool isRecreate = false) {
if (exception != null && exception is SQLiteException) {
try { if (obj.Value.Ping() == false) obj.Value.OpenAndAttach(policy.Attaches); } catch { base.SetUnavailable(exception); }
}
base.Return(obj, isRecreate);
}
internal SqliteConnectionPoolPolicy policy;
}
class SqliteConnectionPoolPolicy : IPolicy<DbConnection> {
internal SqliteConnectionPool _pool;
public string Name { get; set; } = "Sqlite SQLiteConnection 对象池";
public int PoolSize { get; set; } = 100;
public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
public TimeSpan IdleTimeout { get; set; } = TimeSpan.Zero;
public int AsyncGetCapacity { get; set; } = 10000;
public bool IsThrowGetTimeoutException { get; set; } = true;
public int CheckAvailableInterval { get; set; } = 5;
public string[] Attaches = new string[0];
static ConcurrentDictionary<string, int> dicConnStrIncr = new ConcurrentDictionary<string, int>(StringComparer.CurrentCultureIgnoreCase);
private string _connectionString;
public string ConnectionString {
get => _connectionString;
set {
_connectionString = value ?? "";
var pattern = @"Max\s*pool\s*size\s*=\s*(\d+)";
Match m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success == false || int.TryParse(m.Groups[1].Value, out var poolsize) == false || poolsize <= 0) poolsize = 100;
var connStrIncr = dicConnStrIncr.AddOrUpdate(_connectionString, 1, (oldkey, oldval) => oldval + 1);
PoolSize = poolsize + connStrIncr;
_connectionString = m.Success ?
Regex.Replace(_connectionString, pattern, $"Max pool size={PoolSize}", RegexOptions.IgnoreCase) :
$"{_connectionString};Max pool size={PoolSize}";
pattern = @"Connection\s*LifeTime\s*=\s*(\d+)";
m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success) {
IdleTimeout = TimeSpan.FromSeconds(int.Parse(m.Groups[1].Value));
_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase);
}
var minPoolSize = 0;
pattern = @"Min\s*pool\s*size\s*=\s*(\d+)";
m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase);
if (m.Success) {
minPoolSize = int.Parse(m.Groups[1].Value);
_connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase);
}
var att = Regex.Split(_connectionString, @"Attachs\s*=\s*", RegexOptions.IgnoreCase);
if (att.Length == 2) {
var idx = att[1].IndexOf(';');
Attaches = (idx == -1 ? att[1] : att[1].Substring(0, idx)).Split(',');
}
FreeUtil.PrevReheatConnectionPool(_pool, minPoolSize);
}
}
public bool OnCheckAvailable(Object<DbConnection> obj) {
if (obj.Value.State == ConnectionState.Closed) obj.Value.OpenAndAttach(Attaches);
return obj.Value.Ping(true);
}
public DbConnection OnCreate() {
var conn = new SQLiteConnection(_connectionString);
return conn;
}
public void OnDestroy(DbConnection obj) {
if (obj.State != ConnectionState.Closed) obj.Close();
obj.Dispose();
}
public void OnGet(Object<DbConnection> obj) {
if (_pool.IsAvailable) {
if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && obj.Value.Ping() == false) {
try {
obj.Value.OpenAndAttach(Attaches);
} catch (Exception ex) {
if (_pool.SetUnavailable(ex) == true)
throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}");
}
}
}
}
async public Task OnGetAsync(Object<DbConnection> obj) {
if (_pool.IsAvailable) {
if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && (await obj.Value.PingAsync()) == false) {
try {
await obj.Value.OpenAndAttachAsync(Attaches);
} catch (Exception ex) {
if (_pool.SetUnavailable(ex) == true)
throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}");
}
}
}
}
public void OnGetTimeout() {
}
public void OnReturn(Object<DbConnection> obj) {
}
public void OnAvailable() {
_pool.availableHandler?.Invoke();
}
public void OnUnavailable() {
_pool.unavailableHandler?.Invoke();
}
}
static class DbConnectionExtensions {
static DbCommand PingCommand(DbConnection conn) {
var cmd = conn.CreateCommand();
cmd.CommandTimeout = 5;
cmd.CommandText = "select 1";
return cmd;
}
public static bool Ping(this DbConnection that, bool isThrow = false) {
try {
PingCommand(that).ExecuteNonQuery();
return true;
} catch {
if (that.State != ConnectionState.Closed) try { that.Close(); } catch { }
if (isThrow) throw;
return false;
}
}
async public static Task<bool> PingAsync(this DbConnection that, bool isThrow = false) {
try {
await PingCommand(that).ExecuteNonQueryAsync();
return true;
} catch {
if (that.State != ConnectionState.Closed) try { that.Close(); } catch { }
if (isThrow) throw;
return false;
}
}
public static void OpenAndAttach(this DbConnection that, string[] attach) {
that.Open();
if (attach?.Any() == true) {
var sb = new StringBuilder();
foreach(var att in attach)
sb.Append($"attach database [{att}] as [{att.Split('.').First()}];\r\n");
var cmd = that.CreateCommand();
cmd.CommandText = sb.ToString();
cmd.ExecuteNonQuery();
}
}
async public static Task OpenAndAttachAsync(this DbConnection that, string[] attach) {
await that.OpenAsync();
if (attach?.Any() == true) {
var sb = new StringBuilder();
foreach (var att in attach)
sb.Append($"attach database [{att}] as [{att.Split('.').First()}];\r\n");
var cmd = that.CreateCommand();
cmd.CommandText = sb.ToString();
await cmd.ExecuteNonQueryAsync();
}
}
}
}

View File

@ -1,289 +0,0 @@
using FreeSql.DataAnnotations;
using FreeSql.DatabaseModel;
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace FreeSql.Sqlite {
class SqliteCodeFirst : ICodeFirst {
IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
public SqliteCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) {
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
}
public bool IsAutoSyncStructure { get; set; } = false;
public bool IsSyncStructureToLower { get; set; } = false;
public bool IsSyncStructureToUpper { get; set; } = false;
public bool IsConfigEntityFromDbFirst { get; set; } = false;
public bool IsNoneCommandParameter { get; set; } = false;
public bool IsLazyLoading { get; set; } = false;
static object _dicCsToDbLock = new object();
static Dictionary<string, (DbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)> _dicCsToDb = new Dictionary<string, (DbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)>() {
{ typeof(bool).FullName, (DbType.Boolean, "boolean","boolean NOT NULL", null, false, false) },{ typeof(bool?).FullName, (DbType.Boolean, "boolean","boolean", null, true, null) },
{ typeof(sbyte).FullName, (DbType.SByte, "smallint", "smallint NOT NULL", false, false, 0) },{ typeof(sbyte?).FullName, (DbType.SByte, "smallint", "smallint", false, true, null) },
{ typeof(short).FullName, (DbType.Int16, "smallint","smallint NOT NULL", false, false, 0) },{ typeof(short?).FullName, (DbType.Int16, "smallint", "smallint", false, true, null) },
{ typeof(int).FullName, (DbType.Int32, "integer", "integer NOT NULL", false, false, 0) },{ typeof(int?).FullName, (DbType.Int32, "integer", "integer", false, true, null) },
{ typeof(long).FullName, (DbType.Int64, "integer","integer NOT NULL", false, false, 0) },{ typeof(long?).FullName, (DbType.Int64, "integer","integer", false, true, null) },
{ typeof(byte).FullName, (DbType.Byte, "int2","int2 NOT NULL", true, false, 0) },{ typeof(byte?).FullName, (DbType.Byte, "int2","int2", true, true, null) },
{ typeof(ushort).FullName, (DbType.UInt16, "unsigned","unsigned NOT NULL", true, false, 0) },{ typeof(ushort?).FullName, (DbType.UInt16, "unsigned", "unsigned", true, true, null) },
{ typeof(uint).FullName, (DbType.Decimal, "decimal(10,0)", "decimal(10,0) NOT NULL", true, false, 0) },{ typeof(uint?).FullName, (DbType.Decimal, "decimal(10,0)", "decimal(10,0)", true, true, null) },
{ typeof(ulong).FullName, (DbType.Decimal, "decimal(21,0)", "decimal(21,0) NOT NULL", true, false, 0) },{ typeof(ulong?).FullName, (DbType.Decimal, "decimal(21,0)", "decimal(21,0)", true, true, null) },
{ typeof(double).FullName, (DbType.Double, "double", "double NOT NULL", false, false, 0) },{ typeof(double?).FullName, (DbType.Double, "double", "double", false, true, null) },
{ typeof(float).FullName, (DbType.Single, "float","float NOT NULL", false, false, 0) },{ typeof(float?).FullName, (DbType.Single, "float","float", false, true, null) },
{ typeof(decimal).FullName, (DbType.Decimal, "decimal", "decimal(10,2) NOT NULL", false, false, 0) },{ typeof(decimal?).FullName, (DbType.Decimal, "decimal", "decimal(10,2)", false, true, null) },
{ typeof(TimeSpan).FullName, (DbType.Time, "bigint","bigint NOT NULL", false, false, 0) },{ typeof(TimeSpan?).FullName, (DbType.Time, "bigint", "bigint",false, true, null) },
{ typeof(DateTime).FullName, (DbType.DateTime, "datetime", "datetime NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, (DbType.DateTime, "datetime", "datetime", false, true, null) },
{ typeof(byte[]).FullName, (DbType.Binary, "blob", "blob", false, null, new byte[0]) },
{ typeof(string).FullName, (DbType.String, "nvarchar", "nvarchar(255)", false, null, "") },
{ typeof(Guid).FullName, (DbType.Guid, "character", "character(36) NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName, (DbType.Guid, "character", "character(36)", false, true, null) },
};
public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) {
if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (int, string, string, bool?, object)?(((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue));
if (type.IsArray) return null;
var enumType = type.IsEnum ? type : null;
if (enumType == null && type.IsNullableType() && type.GenericTypeArguments.Length == 1 && type.GenericTypeArguments.First().IsEnum) enumType = type.GenericTypeArguments.First();
if (enumType != null) {
var newItem = enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Any() ?
(DbType.Int64, "bigint", $"bigint{(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0)) :
(DbType.Int32, "mediumint", $"mediumint{(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0));
if (_dicCsToDb.ContainsKey(type.FullName) == false) {
lock (_dicCsToDbLock) {
if (_dicCsToDb.ContainsKey(type.FullName) == false)
_dicCsToDb.Add(type.FullName, newItem);
}
}
return ((int)newItem.Item1, newItem.Item2, newItem.Item3, newItem.Item5, newItem.Item6);
}
return null;
}
public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity));
public string GetComparisonDDLStatements(params Type[] entityTypes) {
var sb = new StringBuilder();
var sbDeclare = new StringBuilder();
foreach (var entityType in entityTypes) {
if (sb.Length > 0) sb.Append("\r\n");
var tb = _commonUtils.GetTableByEntity(entityType);
if (tb == null) throw new Exception($"类型 {entityType.FullName} 不可迁移");
if (tb.Columns.Any() == false) throw new Exception($"类型 {entityType.FullName} 不可迁移可迁移属性0个");
var tbname = tb.DbName.Split(new[] { '.' }, 2);
if (tbname?.Length == 1) tbname = new[] { "main", tbname[0] };
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //旧表名
if (tboldname?.Length == 1) tboldname = new[] { "main", tboldname[0] };
var sbalter = new StringBuilder();
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
var isIndent = false;
if (_orm.Ado.ExecuteScalar(CommandType.Text, $" select 1 from {tbname[0]}.sqlite_master where type='table' and name='{tbname[1]}'") == null) { //表不存在
if (tboldname != null) {
if (_orm.Ado.ExecuteScalar(CommandType.Text, $" select 1 from {tboldname[0]}.sqlite_master where type='table' and name='{tboldname[1]}'") == null)
//模式或表不存在
tboldname = null;
}
if (tboldname == null) {
//创建表
sb.Append("CREATE TABLE IF NOT EXISTS ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ( ");
foreach (var tbcol in tb.Columns.Values) {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ");
sb.Append(tbcol.Attribute.DbType);
if (tbcol.Attribute.IsIdentity == true && tbcol.Attribute.DbType.IndexOf("AUTOINCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) {
isIndent = true;
sb.Append(" PRIMARY KEY AUTOINCREMENT");
}
sb.Append(",");
}
if (isIndent == false && tb.Primarys.Any()) {
sb.Append(" \r\n PRIMARY KEY (");
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
foreach (var uk in tb.Uniques) {
sb.Append(" \r\n CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(" UNIQUE(");
foreach (var tbcol in uk.Value) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
sb.Remove(sb.Length - 1, 1);
sb.Append("\r\n) \r\n;\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[1]}")).Append(";\r\n");
else {
//如果新表,旧表不在一起,创建新表,导入数据,删除旧表
istmpatler = true;
}
} else
tboldname = null; //如果新表已经存在,不走改表名逻辑
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
var tbtmp = tboldname ?? tbname;
var dsql = _orm.Ado.ExecuteScalar(CommandType.Text, $" select sql from {tbtmp[0]}.sqlite_master where type='table' and name='{tbtmp[1]}'")?.ToString();
var ds = _orm.Ado.ExecuteArray(CommandType.Text, $"PRAGMA {_commonUtils.QuoteSqlName(tbtmp[0])}.table_info({_commonUtils.QuoteSqlName(tbtmp[1])})");
var tbstruct = ds.ToDictionary(a => string.Concat(a[1]), a => {
var is_identity = false;
var dsqlIdx = dsql?.IndexOf($"\"{a[1]}\" ");
if (dsqlIdx > 0) {
var dsqlLastIdx = dsql.IndexOf('\n', dsqlIdx.Value);
if (dsqlLastIdx > 0) is_identity = dsql.Substring(dsqlIdx.Value, dsqlLastIdx - dsqlIdx.Value).Contains("AUTOINCREMENT");
}
return new {
column = string.Concat(a[1]),
sqlType = string.Concat(a[2]).ToUpper(),
is_nullable = string.Concat(a[3]) == "0",
is_identity
};
}, StringComparer.CurrentCultureIgnoreCase);
if (istmpatler == false) {
foreach (var tbcol in tb.Columns.Values) {
var dbtypeNoneNotNull = Regex.Replace(tbcol.Attribute.DbType, @"NOT\s+NULL", "NULL");
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false)
istmpatler = true;
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable)
istmpatler = true;
if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity)
istmpatler = true;
if (tbstructcol.column == tbcol.Attribute.OldName)
//修改列名
istmpatler = true;
continue;
}
//添加列
istmpatler = true;
}
var dsukMatches = _regexUK.Matches(dsql);
var dsuk = new List<string[]>();
foreach (Match dsukm in dsukMatches) {
var dbsukmg2 = dsukm.Groups[2].Value.Split(',');
if (dbsukmg2.Any() == false) continue;
foreach (var dbfield in dbsukmg2) {
dsuk.Add(new[] { Regex.Match(dbfield, @"""([^""]+)""").Groups[1].Value, dsukm.Groups[1].Value });
}
}
foreach (var uk in tb.Uniques) {
if (string.IsNullOrEmpty(uk.Key) || uk.Value.Any() == false) continue;
var dsukfind1 = dsuk.Where(a => string.Compare(a[1], uk.Key, true) == 0).ToArray();
if (dsukfind1.Any() == false || dsukfind1.Length != uk.Value.Count || dsukfind1.Where(a => uk.Value.Where(b => string.Compare(b.Attribute.Name, a[0], true) == 0).Any()).Count() != uk.Value.Count) {
istmpatler = true;
}
}
}
if (istmpatler == false) {
sb.Append(sbalter);
continue;
}
//创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名
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]}");
//创建临时表
//创建表
isIndent = false;
sb.Append("CREATE TABLE IF NOT EXISTS ").Append(tmptablename).Append(" ( ");
foreach (var tbcol in tb.Columns.Values) {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ");
sb.Append(tbcol.Attribute.DbType);
if (tbcol.Attribute.IsIdentity == true && tbcol.Attribute.DbType.IndexOf("AUTOINCREMENT", StringComparison.CurrentCultureIgnoreCase) == -1) {
isIndent = true;
sb.Append(" PRIMARY KEY AUTOINCREMENT");
}
sb.Append(",");
}
if (isIndent == false && tb.Primarys.Any()) {
sb.Append(" \r\n PRIMARY KEY (");
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
foreach (var uk in tb.Uniques) {
sb.Append(" \r\n CONSTRAINT ").Append(_commonUtils.QuoteSqlName(uk.Key)).Append(" UNIQUE(");
foreach (var tbcol in uk.Value) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),");
}
sb.Remove(sb.Length - 1, 1);
sb.Append("\r\n) \r\n;\r\n");
sb.Append("INSERT INTO ").Append(tmptablename).Append(" (");
foreach (var tbcol in tb.Columns.Values)
sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append(")\r\nSELECT ");
foreach (var tbcol in tb.Columns.Values) {
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)) {
insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column);
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) {
var dbtypeNoneNotNull = Regex.Replace(tbcol.Attribute.DbType, @"(NOT\s+)?NULL", "");
insertvalue = $"cast({insertvalue} as {dbtypeNoneNotNull})";
}
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable)
insertvalue = $"ifnull({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue)})";
} else if (tbcol.Attribute.IsNullable == false)
insertvalue = _commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue);
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("ALTER TABLE ").Append(tmptablename).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[1]}")).Append(";\r\n");
}
return sb.Length == 0 ? null : sb.ToString();
}
static Regex _regexUK = new Regex(@"CONSTRAINT\s*""([^""]+)""\s*UNIQUE\s*\(([^\)]+)\)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
static object syncStructureLock = new object();
ConcurrentDictionary<string, bool> dicSyced = new ConcurrentDictionary<string, bool>();
public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity));
public bool SyncStructure(params Type[] entityTypes) {
if (entityTypes == null) return true;
var syncTypes = entityTypes.Where(a => a.IsAnonymousType() == false && dicSyced.ContainsKey(a.FullName) == false).ToArray();
if (syncTypes.Any() == false) return true;
var before = new Aop.SyncStructureBeforeEventArgs(entityTypes);
_orm.Aop.SyncStructureBefore?.Invoke(this, before);
Exception exception = null;
string ddl = null;
try {
lock (syncStructureLock) {
ddl = this.GetComparisonDDLStatements(syncTypes);
if (string.IsNullOrEmpty(ddl)) {
foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true);
return true;
}
var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl);
foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true);
return affrows > 0;
}
} catch (Exception ex) {
exception = ex;
throw ex;
} finally {
var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception);
_orm.Aop.SyncStructureAfter?.Invoke(this, after);
}
}
public ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) => _commonUtils.ConfigEntity(entity);
public ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) => _commonUtils.ConfigEntity(type, entity);
public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type);
public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type);
}
}

View File

@ -1,403 +0,0 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace FreeSql.Sqlite {
class SqliteExpression : CommonExpression {
public SqliteExpression(CommonUtils common) : base(common) { }
internal override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
switch (exp.NodeType) {
case ExpressionType.Convert:
var operandExp = (exp as UnaryExpression)?.Operand;
var gentype = exp.Type.NullableTypeOrThis();
if (gentype != operandExp.Type.NullableTypeOrThis()) {
switch (exp.Type.NullableTypeOrThis().ToString()) {
case "System.Boolean": return $"({getExp(operandExp)} not in ('0','false'))";
case "System.Byte": return $"cast({getExp(operandExp)} as int2)";
case "System.Char": return $"substr(cast({getExp(operandExp)} as character), 1, 1)";
case "System.DateTime": return $"datetime({getExp(operandExp)})";
case "System.Decimal": return $"cast({getExp(operandExp)} as decimal(36,18))";
case "System.Double": return $"cast({getExp(operandExp)} as double)";
case "System.Int16":
case "System.Int32":
case "System.Int64":
case "System.SByte": return $"cast({getExp(operandExp)} as smallint)";
case "System.Single": return $"cast({getExp(operandExp)} as float)";
case "System.String": return $"cast({getExp(operandExp)} as character)";
case "System.UInt16": return $"cast({getExp(operandExp)} as unsigned)";
case "System.UInt32": return $"cast({getExp(operandExp)} as decimal(10,0))";
case "System.UInt64": return $"cast({getExp(operandExp)} as decimal(21,0))";
case "System.Guid": return $"substr(cast({getExp(operandExp)} as character), 1, 36)";
}
}
break;
case ExpressionType.Call:
var callExp = exp as MethodCallExpression;
switch (callExp.Method.Name) {
case "Parse":
case "TryParse":
switch (callExp.Method.DeclaringType.NullableTypeOrThis().ToString()) {
case "System.Boolean": return $"({getExp(callExp.Arguments[0])} not in ('0','false'))";
case "System.Byte": return $"cast({getExp(callExp.Arguments[0])} as int2)";
case "System.Char": return $"substr(cast({getExp(callExp.Arguments[0])} as character), 1, 1)";
case "System.DateTime": return $"datetime({getExp(callExp.Arguments[0])})";
case "System.Decimal": return $"cast({getExp(callExp.Arguments[0])} as decimal(36,18))";
case "System.Double": return $"cast({getExp(callExp.Arguments[0])} as double)";
case "System.Int16":
case "System.Int32":
case "System.Int64":
case "System.SByte": return $"cast({getExp(callExp.Arguments[0])} as smallint)";
case "System.Single": return $"cast({getExp(callExp.Arguments[0])} as float)";
case "System.UInt16": return $"cast({getExp(callExp.Arguments[0])} as unsigned)";
case "System.UInt32": return $"cast({getExp(callExp.Arguments[0])} as decimal(10,0))";
case "System.UInt64": return $"cast({getExp(callExp.Arguments[0])} as decimal(21,0))";
case "System.Guid": return $"substr(cast({getExp(callExp.Arguments[0])} as character), 1, 36)";
}
break;
case "NewGuid":
break;
case "Next":
if (callExp.Object?.Type == typeof(Random)) return "cast(random()*1000000000 as int)";
break;
case "NextDouble":
if (callExp.Object?.Type == typeof(Random)) return "random()";
break;
case "Random":
if (callExp.Method.DeclaringType.IsNumberType()) return "random()";
break;
case "ToString":
if (callExp.Object != null) return $"cast({getExp(callExp.Object)} as character)";
break;
}
var objExp = callExp.Object;
var objType = objExp?.Type;
if (objType?.FullName == "System.Byte[]") return null;
var argIndex = 0;
if (objType == null && callExp.Method.DeclaringType == typeof(Enumerable)) {
objExp = callExp.Arguments.FirstOrDefault();
objType = objExp?.Type;
argIndex++;
}
if (objType == null) objType = callExp.Method.DeclaringType;
if (objType != null || objType.IsArray || typeof(IList).IsAssignableFrom(callExp.Method.DeclaringType)) {
var left = objExp == null ? null : getExp(objExp);
switch (callExp.Method.Name) {
case "Contains":
//判断 in
return $"({getExp(callExp.Arguments[argIndex])}) in {left}";
}
}
break;
case ExpressionType.NewArrayInit:
var arrExp = exp as NewArrayExpression;
var arrSb = new StringBuilder();
arrSb.Append("(");
for (var a = 0; a < arrExp.Expressions.Count; a++) {
if (a > 0) arrSb.Append(",");
arrSb.Append(getExp(arrExp.Expressions[a]));
}
if (arrSb.Length == 1) arrSb.Append("NULL");
return arrSb.Append(")").ToString();
case ExpressionType.ListInit:
var listExp = exp as ListInitExpression;
var listSb = new StringBuilder();
listSb.Append("(");
for (var a = 0; a < listExp.Initializers.Count; a++) {
if (listExp.Initializers[a].Arguments.Any() == false) continue;
if (a > 0) listSb.Append(",");
listSb.Append(getExp(listExp.Initializers[a].Arguments.FirstOrDefault()));
}
if (listSb.Length == 1) listSb.Append("NULL");
return listSb.Append(")").ToString();
case ExpressionType.New:
var newExp = exp as NewExpression;
if (typeof(IList).IsAssignableFrom(newExp.Type)) {
if (newExp.Arguments.Count == 0) return "(NULL)";
if (typeof(IEnumerable).IsAssignableFrom(newExp.Arguments[0].Type) == false) return "(NULL)";
return getExp(newExp.Arguments[0]);
}
return null;
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Empty": return "''";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Length": return $"length({left})";
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Now": return "datetime(current_timestamp,'localtime')";
case "UtcNow": return "current_timestamp";
case "Today": return "date(current_timestamp,'localtime')";
case "MinValue": return "datetime('0001-01-01 00:00:00.000')";
case "MaxValue": return "datetime('9999-12-31 23:59:59.999')";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Date": return $"date({left})";
case "TimeOfDay": return $"strftime('%s',{left})";
case "DayOfWeek": return $"strftime('%w',{left})";
case "Day": return $"strftime('%d',{left})";
case "DayOfYear": return $"strftime('%j',{left})";
case "Month": return $"strftime('%m',{left})";
case "Year": return $"strftime('%Y',{left})";
case "Hour": return $"strftime('%H',{left})";
case "Minute": return $"strftime('%M',{left})";
case "Second": return $"strftime('%S',{left})";
case "Millisecond": return $"(strftime('%f',{left})-strftime('%S',{left}))";
case "Ticks": return $"(strftime('%s',{left})*10000000+621355968000000000)";
}
return null;
}
internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) {
if (exp.Expression == null) {
switch (exp.Member.Name) {
case "Zero": return "0";
case "MinValue": return "-922337203685.477580"; //秒 Ticks / 1000,000,0
case "MaxValue": return "922337203685.477580";
}
return null;
}
var left = ExpressionLambdaToSql(exp.Expression, tsc);
switch (exp.Member.Name) {
case "Days": return $"floor(({left})/{60 * 60 * 24})";
case "Hours": return $"floor(({left})/{60 * 60}%24)";
case "Milliseconds": return $"(cast({left} as bigint)*1000)";
case "Minutes": return $"floor(({left})/60%60)";
case "Seconds": return $"(({left})%60)";
case "Ticks": return $"(cast({left} as bigint)*10000000)";
case "TotalDays": return $"(({left})/{60 * 60 * 24})";
case "TotalHours": return $"(({left})/{60 * 60})";
case "TotalMilliseconds": return $"(cast({left} as bigint)*1000)";
case "TotalMinutes": return $"(({left})/60)";
case "TotalSeconds": return $"({left})";
}
return null;
}
internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "IsNullOrEmpty":
var arg1 = getExp(exp.Arguments[0]);
return $"({arg1} is null or {arg1} = '')";
case "Concat":
return _common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), null);
}
} else {
var left = getExp(exp.Object);
switch (exp.Method.Name) {
case "StartsWith":
case "EndsWith":
case "Contains":
var args0Value = getExp(exp.Arguments[0]);
if (args0Value == "NULL") return $"({left}) IS NULL";
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"({args0Value})||'%'")}";
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"'%'||({args0Value})")}";
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
return $"({left}) LIKE '%'||({args0Value})||'%'";
case "ToLower": return $"lower({left})";
case "ToUpper": return $"upper({left})";
case "Substring":
var substrArgs1 = getExp(exp.Arguments[0]);
if (long.TryParse(substrArgs1, out var testtrylng1)) substrArgs1 = (testtrylng1 + 1).ToString();
else substrArgs1 += "+1";
if (exp.Arguments.Count == 1) return $"substr({left}, {substrArgs1})";
return $"substr({left}, {substrArgs1}, {getExp(exp.Arguments[1])})";
case "IndexOf":
var indexOfFindStr = getExp(exp.Arguments[0]);
//if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") {
// var locateArgs1 = getExp(exp.Arguments[1]);
// if (long.TryParse(locateArgs1, out var testtrylng2)) locateArgs1 = (testtrylng2 + 1).ToString();
// else locateArgs1 += "+1";
// return $"(instr({left}, {indexOfFindStr}, {locateArgs1})-1)";
//}
return $"(instr({left}, {indexOfFindStr})-1)";
case "PadLeft":
if (exp.Arguments.Count == 1) return $"lpad({left}, {getExp(exp.Arguments[0])})";
return $"lpad({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "PadRight":
if (exp.Arguments.Count == 1) return $"rpad({left}, {getExp(exp.Arguments[0])})";
return $"rpad({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "Trim":
case "TrimStart":
case "TrimEnd":
if (exp.Arguments.Count == 0) {
if (exp.Method.Name == "Trim") return $"trim({left})";
if (exp.Method.Name == "TrimStart") return $"ltrim({left})";
if (exp.Method.Name == "TrimEnd") return $"rtrim({left})";
}
var trimArg1 = "";
var trimArg2 = "";
foreach (var argsTrim02 in exp.Arguments) {
var argsTrim01s = new[] { argsTrim02 };
if (argsTrim02.NodeType == ExpressionType.NewArrayInit) {
var arritem = argsTrim02 as NewArrayExpression;
argsTrim01s = arritem.Expressions.ToArray();
}
foreach (var argsTrim01 in argsTrim01s) {
var trimChr = getExp(argsTrim01).Trim('\'');
if (trimChr.Length == 1) trimArg1 += trimChr;
else trimArg2 += $" || ({trimChr})";
}
}
if (exp.Method.Name == "Trim") left = $"trim({left}, {_common.FormatSql("{0}", trimArg1)}{trimArg2})";
if (exp.Method.Name == "TrimStart") left = $"ltrim({left}, {_common.FormatSql("{0}", trimArg1)}{trimArg2})";
if (exp.Method.Name == "TrimEnd") left = $"rtrim({left}, {_common.FormatSql("{0}", trimArg1)}{trimArg2})";
return left;
case "Replace": return $"replace({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "CompareTo": return $"case when {left} = {getExp(exp.Arguments[0])} then 0 when {left} > {getExp(exp.Arguments[0])} then 1 else -1 end";
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
}
}
throw new Exception($"SqliteExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
switch (exp.Method.Name) {
case "Abs": return $"abs({getExp(exp.Arguments[0])})";
case "Sign": return $"sign({getExp(exp.Arguments[0])})";
case "Floor": return $"floor({getExp(exp.Arguments[0])})";
case "Ceiling": return $"ceiling({getExp(exp.Arguments[0])})";
case "Round":
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"round({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
return $"round({getExp(exp.Arguments[0])})";
case "Exp": return $"exp({getExp(exp.Arguments[0])})";
case "Log": return $"log({getExp(exp.Arguments[0])})";
case "Log10": return $"log10({getExp(exp.Arguments[0])})";
case "Pow": return $"power({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
case "Sqrt": return $"sqrt({getExp(exp.Arguments[0])})";
case "Cos": return $"cos({getExp(exp.Arguments[0])})";
case "Sin": return $"sin({getExp(exp.Arguments[0])})";
case "Tan": return $"tan({getExp(exp.Arguments[0])})";
case "Acos": return $"acos({getExp(exp.Arguments[0])})";
case "Asin": return $"asin({getExp(exp.Arguments[0])})";
case "Atan": return $"atan({getExp(exp.Arguments[0])})";
case "Atan2": return $"atan2({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
//case "Truncate": return $"truncate({getExp(exp.Arguments[0])}, 0)";
}
throw new Exception($"SqliteExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "Compare": return $"(strftime('%s',{getExp(exp.Arguments[0])}) -strftime('%s',{getExp(exp.Arguments[1])}))";
case "DaysInMonth": return $"strftime('%d',date({getExp(exp.Arguments[0])}||'-01-01',{getExp(exp.Arguments[1])}||' months','-1 days'))";
case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})";
case "IsLeapYear":
var isLeapYearArgs1 = getExp(exp.Arguments[0]);
return $"(({isLeapYearArgs1})%4=0 AND ({isLeapYearArgs1})%100<>0 OR ({isLeapYearArgs1})%400=0)";
case "Parse": return $"datetime({getExp(exp.Arguments[0])})";
case "ParseExact":
case "TryParse":
case "TryParseExact": return $"datetime({getExp(exp.Arguments[0])})";
}
} else {
var left = getExp(exp.Object);
var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]);
switch (exp.Method.Name) {
case "Add": return $"datetime({left},({args1})||' seconds')";
case "AddDays": return $"datetime({left},({args1})||' days')";
case "AddHours": return $"datetime({left},({args1})||' hours')";
case "AddMilliseconds": return $"datetime({left},(({args1})/1000)||' seconds')";
case "AddMinutes": return $"datetime({left},({args1})||' seconds')";
case "AddMonths": return $"datetime({left},({args1})||' months')";
case "AddSeconds": return $"datetime({left},({args1})||' seconds')";
case "AddTicks": return $"datetime({left},(({args1})/10000000)||' seconds')";
case "AddYears": return $"datetime({left},({args1})||' years')";
case "Subtract":
switch ((exp.Arguments[0].Type.IsNullableType() ? exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault() : exp.Arguments[0].Type).FullName) {
case "System.DateTime": return $"(strftime('%s',{left})-strftime('%s',{args1}))";
case "System.TimeSpan": return $"datetime({left},(-{args1})||' seconds')";
}
break;
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
case "CompareTo": return $"(strftime('%s',{left})-strftime('%s',{args1}))";
case "ToString": return $"strftime('%Y-%m-%d %H:%M.%f',{left})";
}
}
throw new Exception($"SqliteExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "Compare": return $"({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])}))";
case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})";
case "FromDays": return $"(({getExp(exp.Arguments[0])})*{60 * 60 * 24})";
case "FromHours": return $"(({getExp(exp.Arguments[0])})*{60 * 60})";
case "FromMilliseconds": return $"(({getExp(exp.Arguments[0])})/1000)";
case "FromMinutes": return $"(({getExp(exp.Arguments[0])})*60)";
case "FromSeconds": return $"(({getExp(exp.Arguments[0])}))";
case "FromTicks": return $"(({getExp(exp.Arguments[0])})/10000000)";
case "Parse": return $"cast({getExp(exp.Arguments[0])} as bigint)";
case "ParseExact":
case "TryParse":
case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as bigint)";
}
} else {
var left = getExp(exp.Object);
var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]);
switch (exp.Method.Name) {
case "Add": return $"({left}+{args1})";
case "Subtract": return $"({left}-({args1}))";
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
case "CompareTo": return $"({left}-({getExp(exp.Arguments[0])}))";
case "ToString": return $"cast({left} as character)";
}
}
throw new Exception($"SqliteExpression 未实现函数表达式 {exp} 解析");
}
internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) {
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);
if (exp.Object == null) {
switch (exp.Method.Name) {
case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))";
case "ToByte": return $"cast({getExp(exp.Arguments[0])} as int2)";
case "ToChar": return $"substr(cast({getExp(exp.Arguments[0])} as character), 1, 1)";
case "ToDateTime": return $"datetime({getExp(exp.Arguments[0])})";
case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as decimal(36,18))";
case "ToDouble": return $"cast({getExp(exp.Arguments[0])} as double)";
case "ToInt16":
case "ToInt32":
case "ToInt64":
case "ToSByte": return $"cast({getExp(exp.Arguments[0])} as smallint)";
case "ToSingle": return $"cast({getExp(exp.Arguments[0])} as float)";
case "ToString": return $"cast({getExp(exp.Arguments[0])} as character)";
case "ToUInt16": return $"cast({getExp(exp.Arguments[0])} as unsigned)";
case "ToUInt32": return $"cast({getExp(exp.Arguments[0])} as decimal(10,0))";
case "ToUInt64": return $"cast({getExp(exp.Arguments[0])} as decimal(21,0))";
}
}
throw new Exception($"SqliteExpression 未实现函数表达式 {exp} 解析");
}
}
}

Some files were not shown because too many files have changed in this diff Show More