多线程 c# 环境中的 Mysql 事务

多维数据集
public class MysqlDbHandler : IDbHandler
    {
        string connStr = $"...";

        MySqlConnection conn;

        public async Task<DbConnection> ConnectAsync()
        {
            try
            {
                conn = new MySqlConnection( connStr );
                await conn.OpenAsync();
                return conn;
            }
            catch (Exception e)
            {
                conn.Close();
                throw;
            }
        }

        public async Task ExecuteNonQuery(MySqlCommand command)
        {
            using (var conn = await ConnectAsync())
            {
                command.Connection = (MySqlConnection)conn;
                using (command)
                {
                    command.ExecuteNonQuery();
                }
            }
        }

        public async Task<MySqlDataReader> ExecuteReaderQuery(MySqlCommand command)
        {
            using (var conn = await ConnectAsync())
            {
                command.Connection = (MySqlConnection)conn;
                using (command)
                    return (MySqlDataReader)await command.ExecuteReaderAsync();
            }

        }
}


public abstract class BaseRepository<T>
{
        protected IDbHandler dbHandler;
        protected IList<T> Items;

        protected string UpdateQuery, AddQuery, GetAllQuery;

        protected BaseRepository(IDbHandler dbHandler, string updateQuery, string addQuery, string getAllQuery)
        {
            this.dbHandler = dbHandler ?? throw new ArgumentNullException( nameof( dbHandler ) );
            UpdateQuery = updateQuery ?? throw new ArgumentNullException( nameof( updateQuery ) );
            AddQuery = addQuery ?? throw new ArgumentNullException( nameof( addQuery ) );
            GetAllQuery = getAllQuery ?? throw new ArgumentNullException( nameof( getAllQuery ) );
        }

        public async Task Update(T t)
        {
            var query = UpdateQuery;
            var parameters = BuildParameterList( t );
            var command = NewCommand( query, parameters );
            await dbHandler.ExecuteNonQuery( command );
        }

        protected abstract Dictionary<string, object> BuildParameterList(T t);
        protected MySqlCommand NewCommand(string query) => new MySqlCommand( query );


        protected MySqlCommand NewCommand(string query, Dictionary<string, object> parameters) 
        {
            var cmd = new MySqlCommand( query );
            foreach (var p in parameters)
                cmd.Parameters.AddWithValue( p.Key, p.Value );
            return cmd;
        }
}

我有一组存储库类,我传递给它们的单个实例 dbHandler通过构造函数。这些存储库类本身具有构造命令对象并与公共 dbHandler 方法(ExecuteNonQuery、ExecuteReaderQuery)交互以获取连接并执行查询/命令的方法。我需要将事务合并到其中一些命令中,但我不确定它们在多线程环境中是否安全。如果一个线程使用上面实现的 ConnectAsync 打开一个连接,开始一个事务,并开始处理/执行命令,而另一个线程打开一个连接,并执行一个不相关的命令,这不打算成为该事务的一部分,这会起作用吗?如预期的那样,或者这会使我的代码受到竞争条件的影响,在这种情况下,不相关的命令在某些条件下可能成为交易的一部分?

布拉德利·格兰杰

事务与其启动的连接相关联(即MySqlConnection.BeginTransaction调用的连接对象)。它不会被MySqlConnection进程中的任何其他打开和活动的对象使用。(尝试使用MySqlTransaction不同对象MySqlConnection将是一个错误。)

另请注意,如果您使用的是 MySQL Connector/NET(又名MySql.Data),那么异步操作实际上不起作用是一个长期存在的已知问题:MySQL 错误 70111您应该切换到替代 MySQL ADO.NET 库,例如MySqlConnector,以获得真正的异步行为。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章