以文本方式查看主题 - Foxtable(狐表) (http://foxtable.com/bbs/index.asp) -- 专家坐堂 (http://foxtable.com/bbs/list.asp?boardid=2) ---- [分享]<结贴>异步不能用狐表自带的事务,使用OleDb原生事务,解决异步comit线程干扰报错:如果分配给命令的连接位于本地挂起事务中,ExecuteNonQuery 要求命令拥有事务。命令的 Transaction 属性尚未初始化。 (http://foxtable.com/bbs/dispbbs.asp?boardid=2&id=149545) |
-- 作者:chen37280600 -- 发布时间:2020/5/5 22:52:00 -- [分享]<结贴>异步不能用狐表自带的事务,使用OleDb原生事务,解决异步comit线程干扰报错:如果分配给命令的连接位于本地挂起事务中,ExecuteNonQuery 要求命令拥有事务。命令的 Transaction 属性尚未初始化。 狐表在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 -- 发布时间:2020/5/6 9:18:00 -- Connection Pool? |
-- 作者:狐狸爸爸 -- 发布时间:2020/5/6 9:22:00 -- 这个还是每次创建一个OleDbConnection或SQLConnection,然后在生成对应的OleDbCommand或SQLCommand对象,开启事务执行。 具体可以看看.net的文档,这里只是执行以下sql语句,直接用原生.net代码也方便。 Foxtable内置事务在多线程中的问题,可能需要一点时间才能解决。
[此贴子已经被作者于2020/5/6 9:23:16编辑过]
|
-- 作者:chen37280600 -- 发布时间:2020/5/6 9:43:00 -- 那能不能利用狐表的Connections,动态创建连接,用创建出来的连接用于异步里的事务。用完后,我自己回收控制资源,自己搞数据库连接池 我去看mybatis原理帖子,https://blog.csdn.net/luanlouis/article/details/37671851 它创建一个正在使用的数据库池集合,空闲的数据库池集合 1请求数据库连接时 2先在空闲里找。如果有,就给予;如果没有,就创建一个新的数据库连接池。把该连接放到正在使用的池 3用完后把数据库连接放回到空闲池,等待下次使用。 以上思路,用狐表设计并不能难做。 只是别人还有个超时自动关闭闲置的数据库连接 ---------------------------------- 创建线程池,是因为避免创建和销毁时的耗时,但是对于已经在异步里的线程,其实是否耗时,都没所谓,已经不堵塞主线程。 根据资料,一般创建和销毁数据库连接池要250ms,执行单条sql是170ms。对于用户保存入库单,多表插入上条sql,数据库连接的创建与销毁时间,并不是什么紧缺的资源 而且我的系统,一般多就几十人一起用,能审核的就有3-5个人。感觉不需要上线程池,狐爸有什么建议吗? (其实我目前只想单纯解决这个报错,让事务能在异步顺利执行。系统用户数也就不到10个人,一天总共插入3000条数据左右而已)
[此贴子已经被作者于2020/5/6 9:56:07编辑过]
|
-- 作者:chen37280600 -- 发布时间:2020/5/6 9:59:00 -- 我看了ado.net的SqlConnection https://blog.csdn.net/winfredzen/article/details/72898152 它的SqlConnection,与狐表的Connection是同一个玩意吗?狐表有引入好这个dll,能直接用吗?能支持参数化吗?
|
-- 作者:有点蓝 -- 发布时间:2020/5/6 10:06:00 -- SqlConnection和狐表的Connection不是同一个东西。狐表的Connection是在.net oledbConnection基础上的封装 SqlConnection可以直接在foxtable里使用,ado.net的东西基本都可以使用。可以自己包装一套用法替代foxtable的SQLcommand |
-- 作者:chen37280600 -- 发布时间: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 -- 发布时间:2020/5/6 12:09:00 -- 新建一个oledb连接,利用狐表的连接字符,完成后关闭。
|
-- 作者:chen37280600 -- 发布时间:2020/5/6 15:09:00 -- 已总结解决,见7楼 |
-- 作者:ycli368 -- 发布时间:2022/1/14 10:26:00 -- 直接用sqlserver的存储过程也可以解决 |