关于 SqlDataReader 并发问题

XBodhi. 2019-04-24 06:05:40
环境如下:

部署了一个 WebAPI 项目。

1秒几十条 或是 按着 F5 不放(几十秒) 通过ADO.NET 访问数据库结构会 链接会挂掉。

有谁有相关经验可以解决此问题

ADO.NET 部分代码如下:

/// <summary>
/// 获取映射后类型为 T 的数据实体。
/// </summary>
/// <typeparam name="T">映射的数据实体对象类型。</typeparam>
/// <param name="commandText">针对数据源运行的文本命令。</param>
/// <param name="commandType">指示或指定如何解释 System.Data.IDbCommand.CommandText 属性。</param>
/// <param name="dataParameters">针对数据源运行的文本命令的参数集合。</param>
/// <exception cref="DbConverterException">执行数据读取器或数据映射到实体出错。</exception>
/// <returns>映射后类型为 T 的数据实体。</returns>
public T GetMappedDataEntity<T>(StringBuilder commandText, CommandType commandType, params IDataParameter[] dataParameters)
where T : INamingContainerEntity, new()
{
T t = default(T);
IDataReader dataReader = null;
try
{
IDictionary<string, PropertyInfo> properties = ExtractMappingDataAttribute<T, MappingDataFieldAttribute>.GetProperties();
if (properties != null && properties.Count > 0)
{
dataReader = this.ExecuteReader(commandType, commandText, dataParameters);
if (dataReader.Read())
{
t = SetPropertyValue<T>(dataReader, properties);
}
dataReader.Close();
this.MainConnection.Close();
}
}
catch (DbHelperException ex)
{
throw new DbConverterException(ex.Message, ex);
}
finally
{
if (dataReader != null && !dataReader.IsClosed)
dataReader.Close();
this.MainConnection.Close();
}
return t;
}
...全文
1478 41 打赏 收藏 转发到动态 举报
写回复
用AI写文章
41 条回复
切换为时间正序
请发表友善的回复…
发表回复
bluaFalcon 2019-04-27
  • 打赏
  • 举报
回复
这篇文章很好,对我有帮助
luj_1768 2019-04-27
  • 打赏
  • 举报
回复
你的测试任务完成了,服务器通过了测试。就是这样的。如果有人打电话给你,一直对你说:你好,请问贵姓?你准备如何应对?
鶖獼鼀龑 2019-04-26
  • 打赏
  • 举报
回复
这个程序有问题吧
闭包客 2019-04-26
  • 打赏
  • 举报
回复
程序处理不了并发,一般的出错信息是超时。 你的异常信息很可能多线程的同步问题,和并发压力是无关的。
xiaoxiangqing 2019-04-26
  • 打赏
  • 举报
回复
lock(locker),locker用一个公共变量
正怒月神 2019-04-26
  • 打赏
  • 举报
回复
甚至,我其实都不明白 数据库单例模式存在的意义是什么。
正怒月神 2019-04-26
  • 打赏
  • 举报
回复
而面对高并发的请求时,Lock这种根本不是解决手段。 应该使用消息中间件,作为缓冲处理。让请求平稳的过渡到服务器。 ribbitmq,你自己百度一下。类似也还有很多。 而且如果真是高并发的话,服务器分流有没有? 这种问题绝对不是纠结一个数据库链接的事情了。 如果高并发,数据库绝对不会用单例模式+lock。 这摆明是自杀式攻击。
正怒月神 2019-04-26
  • 打赏
  • 举报
回复
引用 16 楼 XBodhi. 的回复:
[quote=引用 13 楼 闭包客 的回复:]
这个不需要做成什么单实例,问题很可能就出现在单实例这里。



附加方法,其实没有太大区别的。因为最后还是实例。

目前 在外围 有控制 派生的 SqlHelper,不会重复 创建,因为 和 内部控制 链接 (Connection )是一回事,因为最后都会 应用一个 链接。

否则 链接会暴增的。连接池也会增加。

无非的区别就是 多 new 个 SqlHelper 。[/quote]
你的论点和你的需求也是相互矛盾的。

首先,我假设你用单例模式,而且还使用扯淡的lock。
然后大家一个个访问数据库了。没有问题,都能拿到数据。
如果让你不用单例模式和lock,你说数据库链接会暴增。
那就是说同一时刻的请求很多咯?
那你使用lock,面对这么多请求,你觉得用户们心态会不会爆炸啊?
最后一个用户,是不是要等前面人都完成,在轮到自己?要么就是一直超时咯?
qq_43318673 2019-04-26
  • 打赏
  • 举报
回复
66666666
正怒月神 2019-04-26
  • 打赏
  • 举报
回复
你只要负责 开启和关闭数据库链接。 或者直接使用using结束后自动会回收
正怒月神 2019-04-26
  • 打赏
  • 举报
回复
Helper 做成单例,就是问题的原因。 数据库链接根本不需要单例,不需要静态。 数据库连接池,会优化帮你选在空闲链接。
qq615699073 2019-04-26
  • 打赏
  • 举报
回复
学习学习,也遇到了类似的问题。
无V涯 2019-04-25
  • 打赏
  • 举报
回复
并发,添加锁吧,详细了解下数据并发问题就清楚了,连接也不用用一次就关闭
  • 打赏
  • 举报
回复
using(var reader =this.ExecuteReader(commandType, commandText, dataParameters) )
{
}
通过using自动释放,当然数据库连接的释放是另一回事情
大鱼> 2019-04-25
  • 打赏
  • 举报
回复
引用 30 楼 cpongo2q的回复:
[quote=引用 14 楼 道潯常的回复:][quote=引用 6 楼 XBodhi. 的回复:] 具体加在哪里,如果改成异步是否可以
异步是可以进行少许优化,尽可能的利用到资源,但是如果太过于频繁的访问,就需要考虑是否需要换一种设计模式,如先将频繁操作的数据放入缓存中,减少对数据库的直接操作。 不然,如果频繁对数据库进行增删改查操作,表锁死也是有可能发生的哦<br />↵↵<p>说实话我真不知道自己做错了什么</p>[/quote] 我之前也做了一个大数据的分析,也是需要频繁操作数据库,由于分析效率低下,我采用了Redis做缓存,然后最后结果用异步去操作数据库,你根据自己的情况合理的进行选择。 不过你也可以先去检查一下你与数据库服务器网络是否稳定,有没有丢包的存在。大家给你的只是建议,具体哪种适合你还需要自己去把握
秋的红果实 2019-04-25
  • 打赏
  • 举报
回复

if (properties != null && properties.Count > 0)
{
    object locker = new object();
    lock(locker)
    {
        dataReader = this.ExecuteReader(commandType, commandText, dataParameters);
        if (dataReader.Read())
        {
            t = SetPropertyValue<T>(dataReader, properties);
        }

    }
    
    //既然finally里面有close,这里貌似不用close
    //dataReader.Close();
    //this.MainConnection.Close();
}


捷古佛烈 2019-04-25
  • 打赏
  • 举报
回复
水回复 using ( dataReader = this.ExecuteReader(commandType, commandText, dataParameters)) { if (dataReader.Read()) { t = SetPropertyValue<T>(dataReader, properties); } }
cpongo3 2019-04-25
  • 打赏
  • 举报
回复
引用 楼主 XBodhi.的回复:
[quote=引用 13 楼 闭包客 的回复:]
这个不需要做成什么单实例,问题很可能就出现在单实例这里。



附加方法,其实没有太大区别的。因为最后还是实例。

目前 在外围 有控制 派生的 SqlHelper,不会重复 创建,因为 和 内部控制 链接 (Connection )是一回事,因为最后都会 应用一个 链接。

否则 链接会暴增的。连接池也会增加。

无非的区别就是 多 new 个 SqlHelper 。<br /><span><span style="font-size: 12px;">我就不明白了 我怎么就成功不了啊</span></span>
cpongo3 2019-04-25
  • 打赏
  • 举报
回复
引用 14 楼 道潯常的回复:
[quote=引用 6 楼 XBodhi. 的回复:] 具体加在哪里,如果改成异步是否可以
异步是可以进行少许优化,尽可能的利用到资源,但是如果太过于频繁的访问,就需要考虑是否需要换一种设计模式,如先将频繁操作的数据放入缓存中,减少对数据库的直接操作。 不然,如果频繁对数据库进行增删改查操作,表锁死也是有可能发生的哦<br /><span><span>我快疯了14楼 给我机会吧</span></span>
cpongo3 2019-04-25
  • 打赏
  • 举报
回复
[quote=引用 10 楼 好奇都是要学的的回复:]这也太费资源了, 如果只读的话, 用缓存啊, 第一次取出数据放入缓存, 然后操作缓存, 就不会出现数据库问题了。 添加的时候 插入数据同时 在插入缓存下。 或者用 datatable 不用dataReader  但读取数据就下来了。 向这样接口 只去不存的, 我都是用缓存, 广告, 新闻都是这么做的<br /><span>w诶什么10楼引用这么难啊</span>
加载更多回复(21)

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧