void RecvPacket_A(Action whenRecv) { _recvComplete = false; bool isFirstRecv = true; _conn.StartReceive(result => { if (result == null) { throw new NotSupportedException(); } else { switch (result.Kind) { default: throw new NotSupportedException();//unknown case MySqlResultKind.Ok: { MySqlOkResult ok = result as MySqlOkResult; OkPacket = ok.okpacket; RecvComplete(); } break; case MySqlResultKind.Error: { MySqlErrorResult error = result as MySqlErrorResult; LoadError = error.errPacket; RecvComplete(); } break; case MySqlResultKind.PrepareResponse: { //The server will send a OK_Packet if the statement could be reset, a ERR_Packet if not. //on prepare MySqlPrepareResponseResult response = result as MySqlPrepareResponseResult; _prepareContext = new PreparedContext( response.okPacket.statement_id, _sqlStrTemplate, response.tableHeader); RecvComplete(); } break; case MySqlResultKind.TableResult: { //support partial table mode //last sub table is not partial table //and must notify reader first*** //before call RecvComplete(); //----------------------------------------- MySqlTableResult tableResult = result as MySqlTableResult; //*** _recvComplete = !tableResult.HasFollower; if (_tableResultListener != null) { //the _tableResultListener may modifid by other state (Close) //if don't lock we need to store it to local var _tableResultListener(tableResult); } //----------------------------------------- if (!tableResult.HasFollower) { RecvComplete(); } } break; case MySqlResultKind.MultiTableResult: { MySqlMultiTableResult multiTables = result as MySqlMultiTableResult; List<MySqlTableResult> subTables = multiTables.subTables; int j = subTables.Count; for (int i = 0; i < j; ++i) { MySqlTableResult table = subTables[i]; if (i < j - 1) { //not the last one //(the last one may complete or not complete) table.HasFollower = true; if (_tableResultListener != null) { //the _tableResultListener may modifid by other state (Close) //if don't lock we need to store it to local var _tableResultListener(table); } } else { //this is the last one in the series //support partial table mode //last sub table is not partial table //and must notify reader first*** //before call RecvComplete(); _recvComplete = !table.HasFollower; if (_tableResultListener != null) { //the _tableResultListener may modifid by other state (Close) //if don't lock we need to store it to local var _tableResultListener(table); } if (!table.HasFollower) { RecvComplete(); } } } } break; } } //----------------- //exec once if (isFirstRecv) { isFirstRecv = false; whenRecv(); whenRecv = null; } //----------------- }); }
/// <summary> /// +/- blocking /// </summary> /// <param name="nextAction"></param> public void Prepare(Action nextAction = null) { _execState = QueryExecState.Prepare; _queryUsedMode = QueryUseMode.Prepare; if (_cmdParams == null) { throw new Exception("Sql cmdParams can not null."); } //------------------- //blocking method*** //wait until execute finish //------------------- //prepare sql query _sqlParserMx.UsePrepareResponseParser(); _prepareContext = null; //------------------------------------------------------------- _writer.Reset(); ComPrepareStatementPacket.Write( _writer, _sqlStrTemplate.BindValues(_cmdParams, true)); //------------------------------------------------------------- if (nextAction != null) { //not block here SendAndRecv_A(_writer.ToArray(), nextAction); } else { //blocking _conn.InitWait(); SendAndRecv_A(_writer.ToArray(), _conn.UnWait); _conn.Wait(); } }