That's good news.
For "decoding" the data, check the ESQL/C demo included with the server ($INFORMIXDIR/demo/cdc)
/* Table of the CDC_ log rectypes and their symbolic names as
* published in the Manual
*/
cdc_logrec_t logrectab[NUM_CDCLOGRECTYPES] =
{
{CDC_REC_BEGINTX, "CDC_REC_BEGINTX"},
{CDC_REC_COMMTX, "CDC_REC_COMMTX"},
{CDC_REC_RBTX, "CDC_REC_RBTX"},
{CDC_REC_INSERT, "CDC_REC_INSERT"},
{CDC_REC_DELETE, "CDC_REC_DELETE"},
{CDC_REC_UPDBEF, "CDC_REC_UPDBEF"},
{CDC_REC_UPDAFT, "CDC_REC_UPDAFT"},
{CDC_REC_DISCARD, "CDC_REC_DISCARD"},
{CDC_REC_TRUNCATE, "CDC_REC_TRUNCATE"},
{CDC_REC_TABSCHEMA, "CDC_REC_TABSCHEM"},
{CDC_REC_TIMEOUT, "CDC_REC_TIMEOUT"},
{CDC_REC_ERROR, "CDC_REC_ERROR"}
};
Even if is not C#, it should help to understand how to handle the data stream and convert it to a "readable" format.
Javier
------------------------------
Javier Sagrera
------------------------------
Original Message:
Sent: Wed August 06, 2025 07:30 PM
From: George Wen
Subject: Informix CDC API - Is there a way to pull the change record using .NET?
Thanks, Javier! Your code works!
It seems the key difference is that I was using ExecuteNonQuery() instead of ExecuteReader(), which caused the issue.
The next hurdle is mapping the incoming stream to a CDC record. Reverse‑engineering the content manually would be extremely tedious, so having a sample code snippet for that would be really helpful.
------------------------------
George Wen
------------------------------
Original Message:
Sent: Wed August 06, 2025 06:24 AM
From: Javier Sagrera
Subject: Informix CDC API - Is there a way to pull the change record using .NET?
Hi,
Try something like:
using System;using System.Data;using IBM.Data.Informix;using System.Text;class sample{ public static string HexDump(byte[] bytes) { if (bytes == null) return "<null>"; int len = bytes.Length; StringBuilder result = new StringBuilder(((len + 15) / 16) * 78); char[] chars = new char[78]; // fill all with blanks for (int i = 0; i < 75; i++) chars[i] = ' '; chars[76] = '\r'; chars[77] = '\n'; for (int i1 = 0; i1 < len; i1 += 16) { chars[0] = HexChar(i1 >> 28); chars[1] = HexChar(i1 >> 24); chars[2] = HexChar(i1 >> 20); chars[3] = HexChar(i1 >> 16); chars[4] = HexChar(i1 >> 12); chars[5] = HexChar(i1 >> 8); chars[6] = HexChar(i1 >> 4); chars[7] = HexChar(i1 >> 0); int offset1 = 11; int offset2 = 60; for (int i2 = 0; i2 < 16; i2++) { if (i1 + i2 >= len) { chars[offset1] = ' '; chars[offset1 + 1] = ' '; chars[offset2] = ' '; } else { byte b = bytes[i1 + i2]; chars[offset1] = HexChar(b >> 8); chars[offset1 + 1] = HexChar(b); chars[offset2] = (b < 32 ? '·' : (char)b); } offset1 += (i2 == 8 ? 4 : 3); offset2++; } result.Append(chars); } return result.ToString(); } private static char HexChar(int value) { value &= 0xF; if (value >= 0 && value <= 9) return (char)('0' + value); else return (char)('A' + (value - 10)); } static string checkerror(IfxConnection conn, string func, int ret) { string rets = func; if (ret < 0) { IfxCommand cmmd = conn.CreateCommand(); cmmd.CommandText = "select * from syscdcerrcodes where errcode=" + ret.ToString(); IfxDataReader drdr = cmmd.ExecuteReader(); drdr.Read(); rets = " Error: " + drdr.GetString(0) + " " + drdr.GetString(1) + " " + drdr.GetString(2); drdr.Close(); return rets; } return rets + " OK"; } static void Main(string[] args) { IfxConnection conn; IfxBlob vblob; int maxSize = 512; IfxDataReader drdr; IfxCommand cmmd; long ssid = 0; byte[] vblobBuff = new byte[maxSize]; try { conn = new IfxConnection("Server=ids1210;Database=syscdcv1;User ID=informix; password=ximrofni;DB_LOCALE=en_US.819;"); conn.Open(); cmmd = conn.CreateCommand(); cmmd.CommandText = "execute function informix.cdc_opensess('ids1210',0,-1,100,1,1)"; drdr = cmmd.ExecuteReader(); drdr.Read(); ssid = drdr.GetInt32(0); drdr.Close(); Console.WriteLine("ssid " + ssid.ToString()); cmmd.CommandText = "execute function cdc_set_fullrowlogging('stores7:informix.t1',1);"; drdr = cmmd.ExecuteReader(); drdr.Read(); Console.WriteLine(checkerror(conn, "cdc_set_fullrowlogging", drdr.GetInt32(0))); drdr.Close(); cmmd.CommandText = "execute function cdc_startcapture(" + ssid + ",0,'stores7:informix.t1','c1',1)"; drdr = cmmd.ExecuteReader(); drdr.Read(); Console.WriteLine(checkerror(conn, "dc_startcapture", drdr.GetInt32(0))); drdr.Close(); cmmd.CommandText = "execute function cdc_activatesess(" + ssid + ",0)"; drdr = cmmd.ExecuteReader(); drdr.Read(); Console.WriteLine(checkerror(conn, "cdc_activatesess", drdr.GetInt32(0))); drdr.Close(); Console.WriteLine("Do something with stores7.informix.t1");// IfxSmartLOBLocator test = new IfxSmartLOBLocator(""); vblob = new IfxBlob(conn); vblob.Open(IfxSmartLOBOpenMode.ReadOnly); while (true) { long readed = vblob.Read(ssid, vblobBuff); //long readed=vblob.Read(vblobBuff, 0, maxSize, 0, IfxSmartLOBWhence.Current); if (readed>0) Console.WriteLine(HexDump(vblobBuff)); //else // Console.WriteLine("!!!empty blob"); if (Console.KeyAvailable) break; System.Threading.Thread.Sleep(1000); } vblob.Close(); cmmd.CommandText = "execute function cdc_set_fullrowlogging('stores7:informix.t1',0);"; drdr = cmmd.ExecuteReader(); drdr.Read(); Console.WriteLine(checkerror(conn, "cdc_set_fullrowlogging", drdr.GetInt32(0))); drdr.Close(); cmmd.CommandText = "execute function cdc_endcapture(" + ssid + ",0,'stores7:informix.t1')"; drdr = cmmd.ExecuteReader(); drdr.Read(); Console.WriteLine(checkerror(conn, "cdc_endcapture", drdr.GetInt32(0))); drdr.Close(); cmmd.CommandText = "execute function cdc_closesess(" + ssid + ")"; drdr = cmmd.ExecuteReader(); drdr.Read(); Console.WriteLine(checkerror(conn, "cdc_closesess", drdr.GetInt32(0))); drdr.Close(); conn.Close(); } catch (Exception e) { Console.WriteLine(e.Message); } }}
Not 100% sure if it works as it is quite old (1210), but I found it in my C# collection and usually I only keep stuff that works ;)
Javier
------------------------------
Javier Sagrera
Original Message:
Sent: Tue July 29, 2025 06:45 PM
From: George Wen
Subject: Informix CDC API - Is there a way to pull the change record using .NET?
Thanks for the response, Andreas.
You are correct regarding the Java SDK, which supports the IfxSmartBlob object with a session_id. However, the .NET SDK doesn't provide this object.
Additionally, the code snippet in the documentation here:
https://www.ibm.com/docs/en/informix-servers/15.0.0?topic=api-smart-large-object-read-functions
…is not fully consistent with the .NET SDK documentation:
https://www.ibm.com/docs/en/informix-servers/15.0.0?topic=SSGU8G_15.1.0/com.ibm.netpr.doc/ids_net_043.html
As a result, I'm really stuck at this point and unable to move forward.
------------------------------
George Wen
Original Message:
Sent: Tue July 29, 2025 10:19 AM
From: Andreas Legner
Subject: Informix CDC API - Is there a way to pull the change record using .NET?
Not an expert in .NET at all, but to me this looks like it's missing the link between the "session_id" and the LO read: session_id actually is a smart blob LO fd that you'd read from using ifx_lo_read() - or however this is called in .NET.
I'd recommend looking at the cdcapi.ec esql/c demo in (server's) $INFORMIXDIR/demo/cdc, but I have a feeling that's what you modeled your .NET code after anyway ;-)
HTH,
Andreas
------------------------------
Andreas Legner
Informix Dev
HCL Software