Open moxixuan opened 4 years ago
用 TryRegister 呢?
注册 SqlConnection 对象,会并发访问同一个 key 吗?
用 TryRegister 呢?
你的意思是注册失败的异常都不处理吗?
用 TryRegister 呢?
你的意思是注册失败的异常都不处理吗?
是的,只注册一次
注册 SqlConnection 对象,会并发访问同一个 key 吗?
是的,有可能(虽然出现的次数不多),我观察生产环境的日志,有看到这个异常
TakeOutGD 注册失败,请勿重复注册 ReuqestId: c8ac5f66fe014848 at IdleBus2.InternalRegister(TKey key, Func1 create, Nullable1 idle, Boolean isThrow) at IdleBus2.Register(TKey key, Func1 create) at MeiYiJia.TakeOut.Mall.Dapper.IdleBusExtensions.GetSqlConnectionByCompanyCode(IdleBus1 idleBus, String connectionStringTemplate, String companyCode) in /src/src/MeiYiJia.TakeOut.Mall.EntityFrameworkCore/Dapper/IdleBusExtensions.cs:line 33 at MeiYiJia.TakeOut.Mall.Dapper.IdleBusExtensions.GetSqlConnectionByCompanyCode(IdleBus1 idleBus, String companyCode) in /src/src/MeiYiJia.TakeOut.Mall.EntityFrameworkCore/Dapper/IdleBusExtensions.cs:line 44 at MeiYiJia.TakeOut.Mall.Dapper.StoreDapperRepository.GetPlatformInfoAsync(String storeCode) in /src/src
用 TryRegister 呢?
你的意思是注册失败的异常都不处理吗?
是的,只注册一次
但是这边有可能是其他的原因引起的注册失败,我是不是要捕捉到具体的错误,根据不同的情况处理?
你可能理解错意思了,IdleBus是把一个对象重复使用,如果会并发访问 key 对应的实例,是不适合用的。
简单点说,一个 SqlConnection 实例不支持并发访问。
注册的对象,必须是支持单例才行。
你可能理解错意思了,IdleBus是把一个对象重复使用,如果会并发访问 key 对应的实例,是不适合用的。
简单点说,一个 SqlConnection 实例不支持并发访问。
我这边只是使用了static
public static SqlConnection GetSqlConnectionByCompanyCode(this IdleBus<SqlConnection> idleBus
, string connectionStringTemplate
, string companyCode)
{
if (!idleBus.Exists($"TakeOut{companyCode}"))
{
var db = idleBus.GetTocCenterSqlConnection();
var dbConfig = db.QueryFirst<DbConfig>($"select top 1 * from tbDbConfig(nolock) where CompanyCode = '{companyCode}';");
var conStr = string.Format(connectionStringTemplate, dbConfig.DbService, dbConfig.DbName, dbConfig.DbUser, dbConfig.DbPwd);
idleBus.Register($"TakeOut{dbConfig.CompanyCode}", () => new SqlConnection(conStr));
}
var conn = idleBus.Get($"TakeOut{companyCode}");
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
return conn;
}
如果这个注册了,确实会重复使用,但是在docker重启之后,会有大量的访问,这个时候可能会同时注册
所以这里应该要保证线程安全的单例。是这样吗?
你需要延迟释放 SqlConnection 吗,个人觉得 IdleBus 不适合你的场景。上面已经解释了原因
你需要延迟释放 SqlConnection 吗,个人觉得 IdleBus 不适合你的场景。上面已经解释了原因
这边不需要延迟释放 SqlConnection 的,这个封装的方法,主要是判断一下IdleBus 是否有这个key,如果有的话,直接返回SqlConnection (这是大多数情况)但是在第一次注册的时候,有可能会同时注册的情况,我现在通过
public static SqlConnection GetSqlConnectionByCompanyCode(this IdleBus<SqlConnection> idleBus
, string connectionStringTemplate
, string companyCode)
{
if (!idleBus.Exists($"TakeOut{companyCode}"))
{
lock (_syncRoot)
{
if (!idleBus.Exists($"TakeOut{companyCode}"))
{
var db = idleBus.GetTocCenterSqlConnection();
var dbConfig = db.QueryFirst<DbConfig>($"select top 1 * from tbDbConfig(nolock) where CompanyCode = '{companyCode}';");
var conStr = string.Format(connectionStringTemplate, dbConfig.DbService, dbConfig.DbName, dbConfig.DbUser, dbConfig.DbPwd);
idleBus.Register($"TakeOut{dbConfig.CompanyCode}", () => new SqlConnection(conStr));
}
}
}
var conn = idleBus.Get($"TakeOut{companyCode}");
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
return conn;
}
这种方式处理了,这时有效的。
您好,我有如下代码, 我想先判断某个key是否已经注册, 如果没有的话,就查询一下数据库,然后注册, 这看起来没有问题的。
但是当sql查询的速度比较慢,或者是并发请求的时候,或导致重复注册的问题 我暂时想到的解决思路是在外面加一个锁
这样的话,在不考虑分布的清空下,是有效的。
请问这样的情况有没有其他解决思路呢?