Click here to Skip to main content
15,946,342 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello all:

I am creating a worksheet application. There is a common set of fields (i.e. name, Birthdate, some text fields, etc.) Then there is a 'code' that brings up a set of questions.

Each code can have a different amount of questions, and could have different types (i.e. string, int, float, etc.)

So what I figured is to have a Database with the name, birthdate, and code as the key to the file, and a 4096 byte 'blob' (no amount of fields for any code can go over this size).

I was creating 'structs' for each set of questions that belong to a code, and copying them in and out of the 'blob', but it doesn't seem to be working. No matter what I try, I get either 'attempting to write to protected code' errors, or the information appears garbled, or the newest one, "cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed."

What is the best way to do this? One of my example 'code' structs is below:
C#
public partial class Code1 : Form
{
    private new frmMain ParentForm;
    private Code1_Record ws = new Code1_Record();

    public Code1(frmMain _parent, byte[] _record)
    {
        InitializeComponent();
        ParentForm = _parent;

        if (_record != null)
        {
            LoadData(_record);
        }
    }

    private void LoadData(byte[] _record)
    {
        //int iSize = Marshal.SizeOf(ws);
        //byte[] bTmp = new byte[iSize];
        //Array.Copy(_record, 0, bTmp, 0, iSize);
        ws = FromBytes(_record);

        tbxL_CFA.Text = ws.fL_CFA;
        tbxL_SFAprox.Text = ws.fL_SFAprox;
        tbxL_SFAmid.Text = ws.fL_SFAmid;
        tbxL_SFAdistal.Text = ws.fL_SFAdistal;
        tbxL_POP.Text = ws.fL_POP;
        tbxL_PTA.Text = ws.fL_PTA;
        tbxL_DPA.Text = ws.fL_DPA;

        chbL_CFA.Checked = ws.bL_CFA;
        chbL_SFAprox.Checked = ws.bL_SFAprox;
        chbL_SFAmid.Checked = ws.bL_SFAmid;
        chbL_SFAdistal.Checked = ws.bL_SFAdistal;
        chbL_POP.Checked = ws.bL_POP;
        chbL_PTA.Checked = ws.bL_PTA;
        chbL_DPA.Checked = ws.bL_DPA;

        tbxR_CFA.Text = ws.fR_CFA;
        tbxR_SFAprox.Text = ws.fR_SFAprox;
        tbxR_SFAmid.Text = ws.fR_SFAmid;
        tbxR_SFAdistal.Text = ws.fR_SFAdistal;
        tbxR_POP.Text = ws.fR_POP;
        tbxR_PTA.Text = ws.fR_PTA;
        tbxR_DPA.Text = ws.fR_DPA;

        chbR_CFA.Checked = ws.bR_CFA;
        chbR_SFAprox.Checked = ws.bR_SFAprox;
        chbR_SFAmid.Checked = ws.bR_SFAmid;
        chbR_SFAdistal.Checked = ws.bR_SFAdistal;
        chbR_POP.Checked = ws.bR_POP;
        chbR_PTA.Checked = ws.bR_PTA;
        chbR_DPA.Checked = ws.bR_DPA;
    }

    private void btnSave_Click(object sender, EventArgs e)
    {
        ws.fL_CFA = tbxL_CFA.Text;
        ws.fL_SFAprox = tbxL_SFAprox.Text;
        ws.fL_SFAmid = tbxL_SFAmid.Text;
        ws.fL_SFAdistal = tbxL_SFAdistal.Text;
        ws.fL_POP = tbxL_POP.Text;
        ws.fL_PTA = tbxL_PTA.Text;
        ws.fL_DPA = tbxL_DPA.Text;

        ws.bL_CFA = chbL_CFA.Checked;
        ws.bL_SFAprox = chbL_SFAprox.Checked;
        ws.bL_SFAmid = chbL_SFAmid.Checked;
        ws.bL_SFAdistal = chbL_SFAdistal.Checked;
        ws.bL_POP = chbL_POP.Checked;
        ws.bL_PTA = chbL_PTA.Checked;
        ws.bL_DPA = chbL_DPA.Checked;

        ws.fR_CFA = tbxR_CFA.Text;
        ws.fR_SFAprox = tbxR_SFAprox.Text;
        ws.fR_SFAmid = tbxR_SFAmid.Text;
        ws.fR_SFAdistal = tbxR_SFAdistal.Text;
        ws.fR_POP = tbxR_POP.Text;
        ws.fR_PTA = tbxR_PTA.Text;
        ws.fR_DPA = tbxR_DPA.Text;

        ws.bR_CFA = chbR_CFA.Checked;
        ws.bR_SFAprox = chbR_SFAprox.Checked;
        ws.bR_SFAmid = chbR_SFAmid.Checked;
        ws.bR_SFAdistal = chbR_SFAdistal.Checked;
        ws.bR_POP = chbR_POP.Checked;
        ws.bR_PTA = chbR_PTA.Checked;
        ws.bR_DPA = chbR_DPA.Checked;

        ws.bPlaque = chbPlaque.Checked;
        ws.sLocation = tbxLocation.Text;

        ParentForm.CloseExamForm(ToBytes(ws));
        this.Close();
    }

    private void btnClose_Click(object sender, EventArgs e)
    {
        // Check to see if any data changed
        ParentForm.CloseExamForm(null);
        this.Close();
    }

    #region Record Layout and Methods to and from byte[]
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    private struct Code1_Record
    {
        //Left Measurements
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        public string fL_CFA;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        public string fL_SFAprox;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        public string fL_SFAmid;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        public string fL_SFAdistal;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        public string fL_POP;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        public string fL_PTA;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        public string fL_DPA;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        //Left 'Abnormal' (true/false)
        public bool bL_CFA;
        public bool bL_SFAprox;
        public bool bL_SFAmid;
        public bool bL_SFAdistal;
        public bool bL_POP;
        public bool bL_PTA;
        public bool bL_DPA;

        //Right Measurements
        public string fR_CFA;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        public string fR_SFAprox;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        public string fR_SFAmid;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        public string fR_SFAdistal;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        public string fR_POP;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        public string fR_PTA;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        public string fR_DPA;
        //Right 'Abnormal' (true/false)
        public bool bR_CFA;
        public bool bR_SFAprox;
        public bool bR_SFAmid;
        public bool bR_SFAdistal;
        public bool bR_POP;
        public bool bR_PTA;
        public bool bR_DPA;

        //Plaque
        public bool bPlaque;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string sLocation;
    }

    private byte[] ToBytes(Code1_Record str)
    {
        int size = Marshal.SizeOf(str);
        byte[] arr = new byte[size];
        IntPtr ptr = Marshal.AllocHGlobal(size);

        Marshal.StructureToPtr(str, ptr, true);
        Marshal.Copy(ptr, arr, 0, size);
        Marshal.FreeHGlobal(ptr);

        return arr;
    }

    private Code1_Record FromBytes(byte[] arr)
    {
        Code1_Record str = new Code1_Record();

        int size = Marshal.SizeOf(str);
        IntPtr ptr = Marshal.AllocHGlobal(size);

        Marshal.Copy(arr, 0, ptr, size);

        str = (Code1_Record)Marshal.PtrToStructure(ptr, str.GetType());
        Marshal.FreeHGlobal(ptr);

        return str;
    }
}
    #endregion


Thak you very much in advance for helping me.
Posted

The best way is not having "different types of variables" or even different variables of the same type in a blob. It would defeat the purpose of the relational model.

But in rare cases you really can benefit from this approach (hardly, but I don't want to discuss it any further), the approach could be serialization:
http://en.wikipedia.org/wiki/Serialization[^],
https://msdn.microsoft.com/en-us/library/ms973893.aspx[^],
https://msdn.microsoft.com/en-us/library/7ay27kt9%28v=vs.110%29.aspx[^],
https://msdn.microsoft.com/en-us/library/ms733127%28v=vs.110%29.aspx[^] (most robust, consistent and easy to use serialization approach).

—SA
 
Share this answer
 
v2
Thank you - Serialization did what I wanted:

private byte[] ObjectToByteArray(Object obj)
{
    if (obj == null)
        return null;
    BinaryFormatter bf = new BinaryFormatter();
    using (MemoryStream ms = new MemoryStream())
    {
        bf.Serialize(ms, obj);
        return ms.ToArray();
    }
}

private Object ByteArrayToObject(byte[] bArray)
{
    if (bArray == null)
        return null;
    BinaryFormatter bf = new BinaryFormatter();
    using (MemoryStream ms = new MemoryStream(bArray))
    {
        return bf.Deserialize(ms);
    }
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900