.NET 2.0 Serialize and Deserialize Dataset With Row State

Serialize an object is not very difficult, but we have to understand why I decided to implement some features, so my goal is:

  • Simple load and save data on a file
  • Client-Server data communication

so I have two thinks to take care:

  • Some field may be DBNull (not null)
  • DataRows have a row state to keep

For first problem I use this great serialize-deserialize code from CodeProject, A Raw Deserializer; this supports null value serializing.

The second is directly implemeted.

There are two methods:

public static byte[] DataSetToBytes(DataSet ds)

public static DataSet BytesToDataSet(byte[] data)

Here complete code:

public static byte[] DataSetToBytes(DataSet ds)
{
    //Default preCode to test byte array content
    return DataSetToBytes(ds, 48); // '0'
}

public static byte[] DataSetToBytes(DataSet ds, byte preCode)
{
    //preCode is to test byte array content
    bool bDeleted = false;

    MemoryStream ms;
    RawSerializer rs;
    ms = new MemoryStream();
    rs = new RawSerializer(ms);

    ms.WriteByte(preCode); // first write precode

    rs.Serialize(ds.Tables[0].TableName);       // serialize tablename
    rs.Serialize(ds.Tables[0].Columns.Count);   // serialize columns count
    rs.Serialize(ds.Tables[0].Rows.Count);      // serialize rows count

    // serialize columns info
    foreach (DataColumn dc in ds.Tables[0].Columns)
    {
        rs.Serialize(dc.ColumnName);
        rs.Serialize(dc.AllowDBNull);
        rs.Serialize(dc.DataType.AssemblyQualifiedName);
    }

    // serialize data
    foreach (DataRow dr in ds.Tables[0].Rows)
    {
        // check deleted state and set row deleted flag
        if (dr.RowState == DataRowState.Deleted)
        {
            // reject changes to access deleted data
            dr.RejectChanges();
            bDeleted = true;
        }
        else
        {
            bDeleted = false;
        }
        foreach (DataColumn dc in ds.Tables[0].Columns)
        {
            //serialize field
            if (dc.AllowDBNull)
            {
                rs.SerializeNullable(dr[dc]);
            }
            else
            {
                rs.Serialize(dr[dc]);
            }
        }

        //serialize row state
        switch (dr.RowState)
        {
            case DataRowState.Added:
                rs.Serialize((byte)1);
                break;
            case DataRowState.Modified:
                rs.Serialize((byte)2);
                break;
            default:
                if (bDeleted)
                {
                    rs.Serialize((byte)3);
                }
                else
                {
                    rs.Serialize((byte)0);
                }
                break;
        }
    }

    rs.Flush();
    ms.Position = 0;
    return ms.ToArray();
}

public static DataSet BytesToDataSet(byte[] data)
{
    //dummy
    if (data.Length == 0) return null;

    MemoryStream ms;
    RawDeserializer rd;

    ms = new MemoryStream();
    rd = new RawDeserializer(ms);

    //ignore precode on first byte
    ms.Write(data, 1, data.Length - 1);

    ms.Position = 0;
    int rowState = 0;

    string tableName = rd.DeserializeString();  // deserialize table name
    int columns = rd.DeserializeInt();          // deserialize columns count
    int rows = rd.DeserializeInt();             // deserialize rows count

    DataSet dsIn = new DataSet();
    dsIn.Tables.Add(tableName);

    // deserialize columns with columns attribs
    for (int x = 0; x < columns; x++)
    {
        string columnName = rd.DeserializeString();
        bool allowNulls = rd.DeserializeBool();
        string type = rd.DeserializeString();

        DataColumn dc = new DataColumn(columnName, Type.GetType(type));
        dc.AllowDBNull = allowNulls;
        dsIn.Tables[0].Columns.Add(dc);
    }

    // deserialize data
    for (int y = 0; y < rows; y++)
    {
        DataRow dr = dsIn.Tables[0].NewRow();

        // deserialize fields
        for (int x = 0; x < columns; x++)
        {
            DataColumn dc = dsIn.Tables[0].Columns[x];
            object obj;

            if (dc.AllowDBNull)
            {
                obj = rd.DeserializeNullable(dc.DataType);
            }
            else
            {
                obj = rd.Deserialize(dc.DataType);
            }

            dr[dc] = obj;
        }

        //add new row, now this row is in Added state
        dsIn.Tables[0].Rows.Add(dr);

        // force real row state
        rowState = rd.DeserializeByte();
        switch (rowState)
        {
            case 0:
                dsIn.Tables[0].Rows[y].AcceptChanges();
                break;
            case 1:
                //dsIn.Tables[0].Rows[y].SetAdded();
                break;
            case 2:
                dsIn.Tables[0].Rows[y].AcceptChanges();
                dsIn.Tables[0].Rows[y].SetModified();
                break;
            case 3:
                dsIn.Tables[0].Rows[y].AcceptChanges();
                dsIn.Tables[0].Rows[y].Delete();
                break;
        }

    }
    return dsIn;
}
VN:F [1.9.3_1094]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Leave a Reply