- 增加 延时属性编译错误信息;
- 优化 FreeSql.Repository Autofac 泛型注入;
This commit is contained in:
2881099 2019-03-10 21:23:06 +08:00
parent 428220e754
commit ec2fcfb419
11 changed files with 277 additions and 87 deletions

View File

@ -1,5 +1,6 @@
using Autofac; using Autofac;
using Autofac.Extensions.DependencyInjection; using Autofac.Extensions.DependencyInjection;
using FreeSql.DataAnnotations;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
@ -11,6 +12,77 @@ using System;
using System.Text; using System.Text;
namespace repository_01 { namespace repository_01 {
public interface IBaseModel<TKey> {
TKey Id { get; set; }
}
/// <summary>
/// 用户密码信息
/// </summary>
public class SysUserLogOn : IBaseModel<Guid> {
[Column(IsPrimary = true)]
public Guid Id { get; set; } = Guid.NewGuid();
public Guid SysUserId { get; set; }
public string UserPassword { get; set; }
[Column(DbType = "varchar(100)")]
public string UserSecretkey { get; set; }
public DateTime PreviousVisitTime { get; set; } = DateTime.Now;
public DateTime LastVisitTime { get; set; } = DateTime.Now;
public int LogOnCount { get; set; }
public virtual SysUser SysUser { get; set; }
}
public class SysUser : IBaseModel<Guid> {
[Column(IsPrimary = true)]
public Guid Id { get; set; } = Guid.NewGuid();
[Column(DbType = "varchar(50)")]
public string AccountName { get; set; }
[Column(DbType = "varchar(50)")]
public string Name { get; set; }
public string HeadIcon { get; set; }
public Gender Gender { get; set; } = Gender.Man;
public DateTime Birthday { get; set; } = DateTime.MinValue;
[Column(DbType = "varchar(100)")]
public string MobilePhone { get; set; }
public string Email { get; set; }
public string WeChat { get; set; }
public string Description { get; set; }
public DateTime CreationTime { get; set; } = DateTime.Now;
public Guid? CreateUserId { get; set; }
public DateTime LastModifyTime { get; set; } = DateTime.Now;
public Guid? LastModifyUserId { get; set; }
public AccountState State { get; set; } = AccountState.Normal;
}
public enum Gender {
Man = 1,
Woman = 2,
}
public enum AccountState {
/// <summary>
/// 正常
/// </summary>
Normal = 1,
/// <summary>
/// 被禁用
/// </summary>
Disabled = 2,
/// <summary>
/// 已注销
/// </summary>
Closed = 3
}
public class Startup { public class Startup {
public Startup(IConfiguration configuration, ILoggerFactory loggerFactory) { public Startup(IConfiguration configuration, ILoggerFactory loggerFactory) {
Configuration = configuration; Configuration = configuration;
@ -19,7 +91,14 @@ namespace repository_01 {
.UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Pooling=true;Max Pool Size=10") .UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Pooling=true;Max Pool Size=10")
.UseLogger(loggerFactory.CreateLogger<IFreeSql>()) .UseLogger(loggerFactory.CreateLogger<IFreeSql>())
.UseAutoSyncStructure(true) .UseAutoSyncStructure(true)
.UseLazyLoading(true)
.Build(); .Build();
var sysu = new SysUser { };
Fsql.Insert<SysUser>().AppendData(sysu).ExecuteAffrows();
Fsql.Insert<SysUserLogOn>().AppendData(new SysUserLogOn { SysUserId = sysu.Id }).ExecuteAffrows();
var a = Fsql.Select<SysUserLogOn>().ToList();
var b = Fsql.Select<SysUserLogOn>().Any();
} }
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
@ -41,8 +120,8 @@ namespace repository_01 {
var builder = new ContainerBuilder(); var builder = new ContainerBuilder();
builder.RegisterFreeRepository<Song>(a => a.Id == 1); builder.RegisterFreeRepositoryAddFilter<Song>(() => a => a.Title == DateTime.Now.ToString() + System.Threading.Thread.CurrentThread.ManagedThreadId);
builder.RegisterFreeGuidRepository<Song>(a => a.Id == 1, oldname => $"{oldname}_{DateTime.Now.Year}"); //builder.RegisterFreeGuidRepository<Song>(a => a.Id == 1, oldname => $"{oldname}_{DateTime.Now.Year}");
builder.Populate(services); builder.Populate(services);
var container = builder.Build(); var container = builder.Build();

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel> <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup> </PropertyGroup>

View File

@ -8,62 +8,123 @@ using System.Reflection;
public static class FreeSqlRepositoryAutofacDependencyInjection { public static class FreeSqlRepositoryAutofacDependencyInjection {
public static void RegisterFreeGuidRepository<TEntity>(this ContainerBuilder builder, Expression<Func<TEntity, bool>> filter, Func<string, string> asTable) => public static void RegisterFreeRepository(this ContainerBuilder builder) => RegisterFreeRepositoryPrivate<bool>(builder, null, null);
builder.RegisterRepository<TEntity>(filter, asTable, 1); public static void RegisterFreeRepositoryAddFilter<TEntity>(this ContainerBuilder builder, Func<Expression<Func<TEntity, bool>>> filterHandler) => RegisterFreeRepositoryPrivate<TEntity>(builder, filterHandler, null);
public static void RegisterFreeRepository<TEntity>(this ContainerBuilder builder, Expression<Func<TEntity, bool>> filter) =>
builder.RegisterRepository<TEntity>(filter, null, 2);
static void RegisterRepository<TEntity>(this ContainerBuilder builder, Expression<Func<TEntity, bool>> filter, Func<string, string> asTable, int regType) { static ConcurrentDictionary<Type, Delegate> _dicRegisterFreeRepositorySetFilterFunc = new ConcurrentDictionary<Type, Delegate>();
static ConcurrentDictionary<Type, Delegate> _dicRegisterFreeRepositorySetAsTableFunc = new ConcurrentDictionary<Type, Delegate>();
static void RegisterFreeRepositoryPrivate<TEntity>(ContainerBuilder builder, Func<Expression<Func<TEntity, bool>>> filterHandler, Func<string, string> asTableHandler) {
Func<Type, LambdaExpression> reposFunc = type => { Func<Type, Delegate> setFilterFunc = reposType => _dicRegisterFreeRepositorySetFilterFunc.GetOrAdd(reposType, type => {
var reposParameter = Expression.Parameter(type);
var fitlerParameter = Expression.Parameter(typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(type.GenericTypeArguments[0], typeof(bool))));
return Expression.Lambda(
Expression.Block(
Expression.Call(reposParameter, type.GetMethod("set_Filter", BindingFlags.Instance | BindingFlags.NonPublic), fitlerParameter)
),
new[] {
reposParameter, fitlerParameter
}
).Compile();
});
Func<Type, LambdaExpression> convertFilter = type => {
var filter = filterHandler?.Invoke();
if (filter == null) return null;
var entityType = type.GenericTypeArguments[0]; var entityType = type.GenericTypeArguments[0];
var filterParameter1 = Expression.Parameter(entityType, filter.Parameters[0].Name); var filterParameter1 = Expression.Parameter(entityType, filter.Parameters[0].Name);
var convertFilter = Expression.Lambda( try {
typeof(Func<,>).MakeGenericType(entityType, typeof(bool)), return Expression.Lambda(
new ReplaceVisitor<TEntity>().Modify(filter.Body, filterParameter1), typeof(Func<,>).MakeGenericType(entityType, typeof(bool)),
filterParameter1 new ReplaceVisitor<TEntity>().Modify(filter.Body, filterParameter1),
); filterParameter1
var repos = Expression.Parameter(type); );
var blocks = new List<Expression>(); } catch {
if (filter != null) blocks.Add(Expression.Call(repos, type.GetMethod("set_Filter", BindingFlags.Instance | BindingFlags.NonPublic), Expression.Constant(convertFilter))); return null;
if (asTable != null) blocks.Add(Expression.Call(repos, type.GetMethod("set_AsTable", BindingFlags.Instance | BindingFlags.NonPublic), Expression.Constant(asTable))); }
return Expression.Lambda(
//Expression.New(
// typeof(GuidRepository<>).MakeGenericType(type.GenericTypeArguments).GetConstructors()[1],
// Expression.Constant(a.Context.Resolve<IFreeSql>()),
// Expression.Constant(convertFilter),
// Expression.Constant(asTable)
//)
Expression.Block(blocks),
repos
);
}; };
if (regType == 1) builder.RegisterGeneric(typeof(GuidRepository<>)).As(
builder.RegisterGeneric(typeof(GuidRepository<>)).As( typeof(GuidRepository<>),
typeof(GuidRepository<>), typeof(BaseRepository<>),
typeof(BaseRepository<>), typeof(BaseRepository<,>), typeof(IBasicRepository<>),
typeof(IBasicRepository<>), typeof(IBasicRepository<,>), typeof(IReadOnlyRepository<>)
typeof(IReadOnlyRepository<>), typeof(IReadOnlyRepository<,>) ).OnActivating(a => {
).OnActivating(a => { if (filterHandler != null) {
if (filter != null) var type = a.Instance.GetType();
_dicAddGuidRepositoryFunc.GetOrAdd(a.Instance.GetType(), t => reposFunc(t).Compile()).DynamicInvoke(a.Instance); setFilterFunc(type)?.DynamicInvoke(a.Instance, convertFilter(type));
}).InstancePerDependency(); }
}).InstancePerDependency();
builder.RegisterGeneric(typeof(DefaultRepository<,>)).As(
if (regType == 2) typeof(DefaultRepository<,>),
builder.RegisterGeneric(typeof(DefaultRepository<,>)).As( typeof(BaseRepository<,>),
typeof(DefaultRepository<,>), typeof(IBasicRepository<,>),
typeof(BaseRepository<,>), typeof(IReadOnlyRepository<,>)
typeof(IBasicRepository<,>), ).OnActivating(a => {
typeof(IReadOnlyRepository<,>) if (filterHandler != null) {
).OnActivating(a => { var type = a.Instance.GetType();
if (filter != null) setFilterFunc(type)?.DynamicInvoke(a.Instance, convertFilter(type));
_dicAddGuidRepositoryFunc.GetOrAdd(a.Instance.GetType(), t => reposFunc(t).Compile()).DynamicInvoke(a.Instance); }
}).InstancePerDependency(); }).InstancePerDependency();
} }
static ConcurrentDictionary<Type, Delegate> _dicAddGuidRepositoryFunc = new ConcurrentDictionary<Type, Delegate>(); //static void RegisterRepository<TEntity>(this ContainerBuilder builder, Expression<Func<TEntity, bool>> filter, Func<string, string> asTable, int regType) {
// Func<Type, LambdaExpression> reposFunc = type => {
// var entityType = type.GenericTypeArguments[0];
// var filterParameter1 = Expression.Parameter(entityType, filter.Parameters[0].Name);
// var convertFilter = Expression.Lambda(
// typeof(Func<,>).MakeGenericType(entityType, typeof(bool)),
// new ReplaceVisitor<TEntity>().Modify(filter.Body, filterParameter1),
// filterParameter1
// );
// var repos = Expression.Parameter(type);
// var blocks = new List<Expression>();
// if (filter != null) blocks.Add(Expression.Call(repos, type.GetMethod("set_Filter", BindingFlags.Instance | BindingFlags.NonPublic), Expression.Constant(convertFilter)));
// if (asTable != null) blocks.Add(Expression.Call(repos, type.GetMethod("set_AsTable", BindingFlags.Instance | BindingFlags.NonPublic), Expression.Constant(asTable)));
// return Expression.Lambda(
// //Expression.New(
// // typeof(GuidRepository<>).MakeGenericType(type.GenericTypeArguments).GetConstructors()[1],
// // Expression.Constant(a.Context.Resolve<IFreeSql>()),
// // Expression.Constant(convertFilter),
// // Expression.Constant(asTable)
// //)
// Expression.Block(blocks),
// repos
// );
// };
// if (regType == 1)
// builder.RegisterGeneric(typeof(GuidRepository<>)).As(
// typeof(GuidRepository<>),
// typeof(BaseRepository<>), typeof(BaseRepository<,>),
// typeof(IBasicRepository<>), typeof(IBasicRepository<,>),
// typeof(IReadOnlyRepository<>), typeof(IReadOnlyRepository<,>)
// ).OnActivating(a => {
// if (filter != null)
// _dicAddGuidRepositoryFunc.GetOrAdd(a.Instance.GetType(), t => {
// try { reposFunc(t).Compile(); } catch { }
// return null;
// })?.DynamicInvoke(a.Instance);
// }).InstancePerDependency();
// if (regType == 2)
// builder.RegisterGeneric(typeof(DefaultRepository<,>)).As(
// typeof(DefaultRepository<,>),
// typeof(BaseRepository<,>),
// typeof(IBasicRepository<,>),
// typeof(IReadOnlyRepository<,>)
// ).OnActivating(a => {
// if (filter != null)
// _dicAddGuidRepositoryFunc.GetOrAdd(a.Instance.GetType(), t => {
// try { reposFunc(t).Compile(); } catch { }
// return null;
// })?.DynamicInvoke(a.Instance);
// }).InstancePerDependency();
//}
//static ConcurrentDictionary<Type, Delegate> _dicAddGuidRepositoryFunc = new ConcurrentDictionary<Type, Delegate>();
class ReplaceVisitor<TEntity1> : ExpressionVisitor { class ReplaceVisitor<TEntity1> : ExpressionVisitor {
private ParameterExpression parameter; private ParameterExpression parameter;

View File

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<Version>0.1.13</Version> <Version>0.1.14</Version>
<Authors>YeXiangQin</Authors> <Authors>YeXiangQin</Authors>
<Description>FreeSql 通用仓库层实现,支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite读写分离、分表分库。</Description> <Description>FreeSql 通用仓库层实现,支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite读写分离、分表分库。</Description>
<PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl> <PackageProjectUrl>https://github.com/2881099/FreeSql</PackageProjectUrl>

View File

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<Version>0.1.13</Version> <Version>0.1.14</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>YeXiangQin</Authors> <Authors>YeXiangQin</Authors>
<Description>打造 .NETCore 最方便的 ORMDbFirst 与 CodeFirst 混合使用,提供从实体同步数据库,或者从数据库生成实体代码,支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite读写分离、分表分库。</Description> <Description>打造 .NETCore 最方便的 ORMDbFirst 与 CodeFirst 混合使用,提供从实体同步数据库,或者从数据库生成实体代码,支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite读写分离、分表分库。</Description>
@ -20,8 +20,8 @@
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="Npgsql" Version="4.0.5" /> <PackageReference Include="Npgsql" Version="4.0.5" />
<PackageReference Include="Npgsql.LegacyPostgis" Version="4.0.5" /> <PackageReference Include="Npgsql.LegacyPostgis" Version="4.0.5" />
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="2.18.3" /> <PackageReference Include="Oracle.ManagedDataAccess.Core" Version="2.18.5" />
<PackageReference Include="SafeObjectPool" Version="1.0.14" /> <PackageReference Include="SafeObjectPool" Version="2.0.1" />
<PackageReference Include="System.Data.SqlClient" Version="4.6.0" /> <PackageReference Include="System.Data.SqlClient" Version="4.6.0" />
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.110" /> <PackageReference Include="System.Data.SQLite.Core" Version="1.0.110" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" /> <PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" />

View File

@ -449,8 +449,13 @@ namespace FreeSql.Internal {
} }
if (overrieds > 0) { if (overrieds > 0) {
cscode.AppendLine("}"); cscode.AppendLine("}");
var assemly = Generator.TemplateEngin._compiler.Value.CompileCode(cscode.ToString()); Assembly assembly = null;
var type = assemly.DefinedTypes.Where(a => a.FullName.EndsWith(trytbTypeLazyName)).FirstOrDefault(); try {
assembly = Generator.TemplateEngin._compiler.Value.CompileCode(cscode.ToString());
} catch (Exception ex) {
throw new Exception($"【延时加载】{trytbTypeName} 编译错误:{ex.Message}\r\n\r\n{cscode}");
}
var type = assembly.DefinedTypes.Where(a => a.FullName.EndsWith(trytbTypeLazyName)).FirstOrDefault();
trytb.TypeLazy = type; trytb.TypeLazy = type;
trytb.TypeLazySetOrm = type.GetProperty("__fsql_orm__", BindingFlags.Instance | BindingFlags.NonPublic).GetSetMethod(true); trytb.TypeLazySetOrm = type.GetProperty("__fsql_orm__", BindingFlags.Instance | BindingFlags.NonPublic).GetSetMethod(true);
} }

View File

@ -41,6 +41,7 @@ namespace FreeSql.MySql {
public string Name { get; set; } = "MySql MySqlConnection 对象池"; public string Name { get; set; } = "MySql MySqlConnection 对象池";
public int PoolSize { get; set; } = 100; public int PoolSize { get; set; } = 100;
public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10); public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
public TimeSpan IdleTimeout { get; set; } = TimeSpan.Zero;
public int AsyncGetCapacity { get; set; } = 10000; public int AsyncGetCapacity { get; set; } = 10000;
public bool IsThrowGetTimeoutException { get; set; } = true; public bool IsThrowGetTimeoutException { get; set; } = true;
public int CheckAvailableInterval { get; set; } = 5; public int CheckAvailableInterval { get; set; } = 5;
@ -50,17 +51,25 @@ namespace FreeSql.MySql {
public string ConnectionString { public string ConnectionString {
get => _connectionString; get => _connectionString;
set { set {
var connStr = value ?? ""; _connectionString = value ?? "";
var poolsizePatern = @"Max\s*pool\s*size\s*=\s*(\d+)";
Match m = Regex.Match(connStr, poolsizePatern, RegexOptions.IgnoreCase); 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; if (m.Success == false || int.TryParse(m.Groups[1].Value, out var poolsize) == false || poolsize <= 0) poolsize = 100;
var connStrIncr = dicConnStrIncr.AddOrUpdate(connStr, 1, (oldkey, oldval) => oldval + 1); var connStrIncr = dicConnStrIncr.AddOrUpdate(_connectionString, 1, (oldkey, oldval) => oldval + 1);
PoolSize = poolsize + connStrIncr; PoolSize = poolsize + connStrIncr;
_connectionString = m.Success ? _connectionString = m.Success ?
Regex.Replace(connStr, poolsizePatern, $"Max pool size={PoolSize}", RegexOptions.IgnoreCase) : Regex.Replace(_connectionString, pattern, $"Max pool size={PoolSize}", RegexOptions.IgnoreCase) :
$"{connStr};Max pool size={PoolSize}"; $"{_connectionString};Max pool size={PoolSize}";
var initConns = new List<Object<DbConnection>>(); 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 initConns = new List<Object<DbConnection>>();
for (var a = 0; a < PoolSize; a++) for (var a = 0; a < PoolSize; a++)
try { try {
var conn = _pool.Get(); var conn = _pool.Get();

View File

@ -55,6 +55,7 @@ namespace FreeSql.Oracle {
public string Name { get; set; } = "Oracle Connection 对象池"; public string Name { get; set; } = "Oracle Connection 对象池";
public int PoolSize { get; set; } = 100; public int PoolSize { get; set; } = 100;
public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10); public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
public TimeSpan IdleTimeout { get; set; } = TimeSpan.Zero;
public int AsyncGetCapacity { get; set; } = 10000; public int AsyncGetCapacity { get; set; } = 10000;
public bool IsThrowGetTimeoutException { get; set; } = true; public bool IsThrowGetTimeoutException { get; set; } = true;
public int CheckAvailableInterval { get; set; } = 5; public int CheckAvailableInterval { get; set; } = 5;
@ -64,15 +65,23 @@ namespace FreeSql.Oracle {
public string ConnectionString { public string ConnectionString {
get => _connectionString; get => _connectionString;
set { set {
var connStr = value ?? ""; _connectionString = value ?? "";
var poolsizePatern = @"Max\s*pool\s*size\s*=\s*(\d+)";
Match m = Regex.Match(connStr, poolsizePatern, RegexOptions.IgnoreCase); 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; if (m.Success == false || int.TryParse(m.Groups[1].Value, out var poolsize) == false || poolsize <= 0) poolsize = 100;
var connStrIncr = dicConnStrIncr.AddOrUpdate(connStr, 1, (oldkey, oldval) => oldval + 1); var connStrIncr = dicConnStrIncr.AddOrUpdate(_connectionString, 1, (oldkey, oldval) => oldval + 1);
PoolSize = poolsize + connStrIncr; PoolSize = poolsize + connStrIncr;
_connectionString = m.Success ? _connectionString = m.Success ?
Regex.Replace(connStr, poolsizePatern, $"Max pool size={PoolSize}", RegexOptions.IgnoreCase) : Regex.Replace(_connectionString, pattern, $"Max pool size={PoolSize}", RegexOptions.IgnoreCase) :
$"{connStr};Max pool size={PoolSize}"; $"{_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 initConns = new List<Object<DbConnection>>(); var initConns = new List<Object<DbConnection>>();
for (var a = 0; a < PoolSize; a++) for (var a = 0; a < PoolSize; a++)

View File

@ -50,6 +50,7 @@ namespace FreeSql.PostgreSQL {
public string Name { get; set; } = "PostgreSQL NpgsqlConnection 对象池"; public string Name { get; set; } = "PostgreSQL NpgsqlConnection 对象池";
public int PoolSize { get; set; } = 50; public int PoolSize { get; set; } = 50;
public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10); public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
public TimeSpan IdleTimeout { get; set; } = TimeSpan.Zero;
public int AsyncGetCapacity { get; set; } = 10000; public int AsyncGetCapacity { get; set; } = 10000;
public bool IsThrowGetTimeoutException { get; set; } = true; public bool IsThrowGetTimeoutException { get; set; } = true;
public int CheckAvailableInterval { get; set; } = 5; public int CheckAvailableInterval { get; set; } = 5;
@ -59,15 +60,23 @@ namespace FreeSql.PostgreSQL {
public string ConnectionString { public string ConnectionString {
get => _connectionString; get => _connectionString;
set { set {
var connStr = value ?? ""; _connectionString = value ?? "";
var poolsizePatern = @"Maximum\s*pool\s*size\s*=\s*(\d+)";
Match m = Regex.Match(connStr, poolsizePatern, RegexOptions.IgnoreCase); var pattern = @"Maximum\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; if (m.Success == false || int.TryParse(m.Groups[1].Value, out var poolsize) == false || poolsize <= 0) poolsize = 100;
var connStrIncr = dicConnStrIncr.AddOrUpdate(connStr, 1, (oldkey, oldval) => oldval + 1); var connStrIncr = dicConnStrIncr.AddOrUpdate(_connectionString, 1, (oldkey, oldval) => oldval + 1);
PoolSize = poolsize + connStrIncr; PoolSize = poolsize + connStrIncr;
_connectionString = m.Success ? _connectionString = m.Success ?
Regex.Replace(connStr, poolsizePatern, $"Maximum pool size={PoolSize}", RegexOptions.IgnoreCase) : Regex.Replace(_connectionString, pattern, $"Maximum pool size={PoolSize}", RegexOptions.IgnoreCase) :
$"{connStr};Maximum pool size={PoolSize}"; $"{_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 initConns = new List<Object<DbConnection>>(); var initConns = new List<Object<DbConnection>>();
for (var a = 0; a < PoolSize; a++) for (var a = 0; a < PoolSize; a++)

View File

@ -45,6 +45,7 @@ namespace FreeSql.SqlServer {
public string Name { get; set; } = "SqlServer SqlConnection 对象池"; public string Name { get; set; } = "SqlServer SqlConnection 对象池";
public int PoolSize { get; set; } = 100; public int PoolSize { get; set; } = 100;
public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10); public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
public TimeSpan IdleTimeout { get; set; } = TimeSpan.Zero;
public int AsyncGetCapacity { get; set; } = 10000; public int AsyncGetCapacity { get; set; } = 10000;
public bool IsThrowGetTimeoutException { get; set; } = true; public bool IsThrowGetTimeoutException { get; set; } = true;
public int CheckAvailableInterval { get; set; } = 5; public int CheckAvailableInterval { get; set; } = 5;
@ -54,15 +55,23 @@ namespace FreeSql.SqlServer {
public string ConnectionString { public string ConnectionString {
get => _connectionString; get => _connectionString;
set { set {
var connStr = value ?? ""; _connectionString = value ?? "";
var poolsizePatern = @"Max\s*pool\s*size\s*=\s*(\d+)";
Match m = Regex.Match(connStr, poolsizePatern, RegexOptions.IgnoreCase); 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; if (m.Success == false || int.TryParse(m.Groups[1].Value, out var poolsize) == false || poolsize <= 0) poolsize = 100;
var connStrIncr = dicConnStrIncr.AddOrUpdate(connStr, 1, (oldkey, oldval) => oldval + 1); var connStrIncr = dicConnStrIncr.AddOrUpdate(_connectionString, 1, (oldkey, oldval) => oldval + 1);
PoolSize = poolsize + connStrIncr; PoolSize = poolsize + connStrIncr;
_connectionString = m.Success ? _connectionString = m.Success ?
Regex.Replace(connStr, poolsizePatern, $"Max pool size={PoolSize}", RegexOptions.IgnoreCase) : Regex.Replace(_connectionString, pattern, $"Max pool size={PoolSize}", RegexOptions.IgnoreCase) :
$"{connStr};Max pool size={PoolSize}"; $"{_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 initConns = new List<Object<DbConnection>>(); var initConns = new List<Object<DbConnection>>();
for (var a = 0; a < PoolSize; a++) for (var a = 0; a < PoolSize; a++)

View File

@ -45,6 +45,7 @@ namespace FreeSql.Sqlite {
public string Name { get; set; } = "Sqlite SQLiteConnection 对象池"; public string Name { get; set; } = "Sqlite SQLiteConnection 对象池";
public int PoolSize { get; set; } = 100; public int PoolSize { get; set; } = 100;
public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10); public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
public TimeSpan IdleTimeout { get; set; } = TimeSpan.Zero;
public int AsyncGetCapacity { get; set; } = 10000; public int AsyncGetCapacity { get; set; } = 10000;
public bool IsThrowGetTimeoutException { get; set; } = true; public bool IsThrowGetTimeoutException { get; set; } = true;
public int CheckAvailableInterval { get; set; } = 5; public int CheckAvailableInterval { get; set; } = 5;
@ -55,15 +56,23 @@ namespace FreeSql.Sqlite {
public string ConnectionString { public string ConnectionString {
get => _connectionString; get => _connectionString;
set { set {
var connStr = value ?? ""; _connectionString = value ?? "";
var poolsizePatern = @"Max\s*pool\s*size\s*=\s*(\d+)";
Match m = Regex.Match(connStr, poolsizePatern, RegexOptions.IgnoreCase); 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; if (m.Success == false || int.TryParse(m.Groups[1].Value, out var poolsize) == false || poolsize <= 0) poolsize = 100;
var connStrIncr = dicConnStrIncr.AddOrUpdate(connStr, 1, (oldkey, oldval) => oldval + 1); var connStrIncr = dicConnStrIncr.AddOrUpdate(_connectionString, 1, (oldkey, oldval) => oldval + 1);
PoolSize = poolsize + connStrIncr; PoolSize = poolsize + connStrIncr;
_connectionString = m.Success ? _connectionString = m.Success ?
Regex.Replace(connStr, poolsizePatern, $"Max pool size={PoolSize}", RegexOptions.IgnoreCase) : Regex.Replace(_connectionString, pattern, $"Max pool size={PoolSize}", RegexOptions.IgnoreCase) :
$"{connStr};Max pool size={PoolSize}"; $"{_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 att = Regex.Split(_connectionString, @"Attachs\s*=\s*", RegexOptions.IgnoreCase); var att = Regex.Split(_connectionString, @"Attachs\s*=\s*", RegexOptions.IgnoreCase);
if (att.Length == 2) { if (att.Length == 2) {