Foxtable(狐表)用户栏目专家坐堂 → [分享]<结贴>异步不能用狐表自带的事务,使用OleDb原生事务,解决异步comit线程干扰报错:如果分配给命令的连接位于本地挂起事务中,ExecuteNonQuery 要求命令拥有事务。命令的 Transaction 属性尚未初始化。


  共有5174人关注过本帖树形打印复制链接

主题:[分享]<结贴>异步不能用狐表自带的事务,使用OleDb原生事务,解决异步comit线程干扰报错:如果分配给命令的连接位于本地挂起事务中,ExecuteNonQuery 要求命令拥有事务。命令的 Transaction 属性尚未初始化。

帅哥哟,离线,有人找我吗?
chen37280600
  1楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1279 积分:7959 威望:0 精华:4 注册:2017/12/31 14:53:00
[分享]异步不能用狐表自带的事务,使用OleDb原生事务,解决异步comit线程干扰报错:如果分配给命令的连接位于本地挂起事务中,ExecuteNonQuery 要求命令拥有事务。命令的 Transaction 属性尚未初始化。  发帖心情 Post By:2020/5/5 22:52:00 [只看该作者]

狐表在20210529后的版本已增加可以异步使用的Sql事务,这个帖子的方法不再需要了。但是可以留作研究OleDb独立事务

=============================================
我的bs里,有些方法有事务,一般用于入库单和出库单,涉及到多表的批量插入,因此按照官方文档,开了事务。这些事务,由于要插入的行和修改的表都比较多,耗时较长,都启动了异步。

于是今天出现一个:
2020-05-05 10:45:54.7266
报错定位:
如果分配给命令的连接位于本地挂起事务中,ExecuteNonQuery 要求命令拥有事务。命令的 Transaction 属性尚未初始化。
   在 System.Data.OleDb.OleDbConnectionInternal.ValidateTransaction(OleDbTransaction transaction, String method)
   在 System.Data.OleDb.OleDbConnection.ValidateTransaction(OleDbTransaction transaction, String method)
   在 System.Data.OleDb.OleDbCommand.ValidateConnectionAndTransaction(String method)
   在 System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method)
   在 System.Data.OleDb.OleDbCommand.ExecuteNonQuery()
   在 System.Data.Common.DbDataAdapter.UpdateRowExecute(RowUpdatedEventArgs rowUpdatedEvent, IDbCommand dataCommand, StatementType cmdIndex)
   在 System.Data.Common.DbDataAdapter.Update(DataRow[] dataRows, DataTableMapping tableMapping)


按照事务的代码:
Try
    Connections("数据源").BeginTransaction()
'开始事务
    Dim cmd As new
SQLCommand
    cmd.ConnectionName =
"数据源"
    cmd.CommandText =
"Del ete From {订单} Where [订单编号] = 32"
    cmd.
ExecuteNonQuery
    cmd.CommandText =
"Del ete From {订单明细} Where [订单编号] = 32"
    cmd.
ExecuteNonQuery
    Connections("数据源").Commit
'提交事务,所有操作生效

Catch
ex As Exception '如果出错
    Connections("数据源").Rollback()
'回滚事务,撤销所有操作

End
Try

我在感觉,异步多线程下,Connections("数据源")是存在线程干扰,这个东西并不是new出来的,而且在狐表启动后,外部数据源里初始化好的。多个线程共用一个Connections("数据源"),

场景1:
A线程把事务Begin,
B线程刚好到把事务Commit
A线程才开始插入数据,于是就报错了

场景2:
A线程把事务Begin,
A线程对事务配置了待执行的插入代码
B线程刚好到把事务Commit,由B来帮A线程Commit
A线程继续对事务配置剩下待执行的插入代码,已经出问题了

我个人感觉会有问题,这个问题貌似需要狐爸的资深用户解答


我去百度了一个mysql里事务和多线程,貌似跟我说的一样

那BS里怎么解决耗时较久的写入问题?

[此贴子已经被作者于2022/1/14 10:44:09编辑过]

 回到顶部
帅哥哟,离线,有人找我吗?
chen37280600
  2楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1279 积分:7959 威望:0 精华:4 注册:2017/12/31 14:53:00
  发帖心情 Post By:2020/5/6 9:18:00 [只看该作者]

Connection Pool?

 回到顶部
帅哥哟,离线,有人找我吗?
狐狸爸爸
  3楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:管理员 帖子:47497 积分:251403 威望:0 精华:91 注册:2008/6/17 17:14:00
  发帖心情 Post By:2020/5/6 9:22:00 [只看该作者]

这个还是每次创建一个OleDbConnection或SQLConnection,然后在生成对应的OleDbCommand或SQLCommand对象,开启事务执行。
具体可以看看.net的文档,这里只是执行以下sql语句,直接用原生.net代码也方便。

Foxtable内置事务在多线程中的问题,可能需要一点时间才能解决。
[此贴子已经被作者于2020/5/6 9:23:16编辑过]

 回到顶部
帅哥哟,离线,有人找我吗?
chen37280600
  4楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1279 积分:7959 威望:0 精华:4 注册:2017/12/31 14:53:00
  发帖心情 Post By:2020/5/6 9:43:00 [只看该作者]

那能不能利用狐表的Connections,动态创建连接,用创建出来的连接用于异步里的事务。用完后,我自己回收控制资源,自己搞数据库连接池


它创建一个正在使用的数据库池集合,空闲的数据库池集合

1请求数据库连接时
2先在空闲里找。如果有,就给予;如果没有,就创建一个新的数据库连接池。把该连接放到正在使用的池
3用完后把数据库连接放回到空闲池,等待下次使用。

以上思路,用狐表设计并不能难做。
只是别人还有个超时自动关闭闲置的数据库连接

----------------------------------
创建线程池,是因为避免创建和销毁时的耗时,但是对于已经在异步里的线程,其实是否耗时,都没所谓,已经不堵塞主线程。
根据资料,一般创建和销毁数据库连接池要250ms,执行单条sql是170ms。对于用户保存入库单,多表插入上条sql,数据库连接的创建与销毁时间,并不是什么紧缺的资源

而且我的系统,一般多就几十人一起用,能审核的就有3-5个人。感觉不需要上线程池,狐爸有什么建议吗?

(其实我目前只想单纯解决这个报错,让事务能在异步顺利执行。系统用户数也就不到10个人,一天总共插入3000条数据左右而已)
[此贴子已经被作者于2020/5/6 9:56:07编辑过]

 回到顶部
帅哥哟,离线,有人找我吗?
chen37280600
  5楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1279 积分:7959 威望:0 精华:4 注册:2017/12/31 14:53:00
  发帖心情 Post By:2020/5/6 9:59:00 [只看该作者]

我看了ado.net的SqlConnection     https://blog.csdn.net/winfredzen/article/details/72898152

它的SqlConnection,与狐表的Connection是同一个玩意吗?狐表有引入好这个dll,能直接用吗?能支持参数化吗?

 回到顶部
帅哥哟,离线,有人找我吗?
有点蓝
  6楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:超级版主 帖子:111393 积分:567029 威望:0 精华:9 注册:2015/6/24 9:21:00
  发帖心情 Post By:2020/5/6 10:06:00 [只看该作者]

SqlConnection和狐表的Connection不是同一个东西。狐表的Connection是在.net oledbConnection基础上的封装

SqlConnection可以直接在foxtable里使用,ado.net的东西基本都可以使用。可以自己包装一套用法替代foxtable的SQLcommand

 回到顶部
帅哥哟,离线,有人找我吗?
chen37280600
  7楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1279 积分:7959 威望:0 精华:4 注册:2017/12/31 14:53:00
  发帖心情 Post By:2020/5/6 11:54:00 [只看该作者]

总结了一段这样的事务代码,用OleDb,在异步里没问题
大家用就是了

Dim foxCon As Connection = Connections("DB") '狐表本地的数据库源
Dim oleCon As new System.Data.OleDb.OleDbConnection() '创建新的OleDB连接对象
oleCon.ConnectionString = foxCon.ConnectionString '设置连接字符串
Dim trans As System.Data.OleDb.OleDbTransaction '创建一个事务对象准备,注意不能new,因为是Null
Dim oleCmd As new System.Data.OleDb.OleDbCommand '创建一个SQL执行器
oleCmd.Connection = oleCon '把Sql执行器与数据库连接绑定

Try
    oleCon.Open() '启动数据库连接
    trans = oleCon.BeginTransaction() '启动事务,并返回这个事务对象    
    oleCmd.Transaction = trans '把SQL执行器与事务绑定

    '业务代码---
    oleCmd.CommandText = "Insert Into workinfo (ID,Name) Values(?,?)"
    oleCmd.Parameters.Clear '非常重要
    oleCmd.Parameters.Add("@ID","111")
    oleCmd.Parameters.Add("@Name","Test1")
    oleCmd.ExecuteNonQuery
    oleCmd.CommandText = "Insert Into workinfo (ID,Name2) Values(?,?)"
    oleCmd.Parameters.Clear '非常重要
    oleCmd.Parameters.Add("@ID","222")
    oleCmd.Parameters.Add("@Name","Test2")
    oleCmd.ExecuteNonQuery
    '业务代码---
    trans.Commit() '提交事务
Catch ex As Exception '如果出错
    trans.Rollback() '回滚事务,撤销所有操作
    MessageBox.show(ex.ToString())
Finally
    oleCon.Close()
End Try


### 注意空值的赋值方法!
1. 在狐表封装的sqlCommand里,oleCmd.Parameters.Add("@ApproveTime",Nothing)
2. 在原生的OleDb里,oleCmd.Parameters.Add("@ApproveTime",DBNull.Value)


[此贴子已经被作者于2020/5/6 22:14:24编辑过]

 回到顶部
帅哥哟,离线,有人找我吗?
wei0769
  8楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:八尾狐 帖子:1824 积分:19564 威望:0 精华:0 注册:2013/4/10 14:38:00
  发帖心情 Post By:2020/5/6 12:09:00 [只看该作者]

 新建一个oledb连接,利用狐表的连接字符,完成后关闭。

 


 回到顶部
帅哥哟,离线,有人找我吗?
chen37280600
  9楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:六尾狐 帖子:1279 积分:7959 威望:0 精华:4 注册:2017/12/31 14:53:00
  发帖心情 Post By:2020/5/6 15:09:00 [只看该作者]

已总结解决,见7楼

 回到顶部
帅哥哟,离线,有人找我吗?
ycli368
  10楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:四尾狐 帖子:998 积分:10453 威望:0 精华:0 注册:2012/12/11 14:25:00
  发帖心情 Post By:2022/1/14 10:26:00 [只看该作者]

直接用sqlserver的存储过程也可以解决

 回到顶部