returning values struct vs. class/ref vs. value

bri189a

Well-known member
Joined
Sep 11, 2003
Messages
1,004
Location
VA
This is a technical one that is above me...

Ive got a custom class I made that uses a lot of external procedures from mpr.dll. Basically I get the values I need from them and put them into what use to be a struct and return the struct to the program that requires them. The struct is very simple... it contains to string properties.

The problem I am having is that when I take those strings and use them in just about anything (such as a database) the strings get corrupted somehow and the data is lost, this doesnt happen if I put it into a control that has a list collection such as a ListBox or ListView. I thought that maybe this was because I was passing it back via a struct, so I changed my struct that Im passing back into a class and the same problem occurs, so now Im wonder if rather than a static method I should be using a regular method. Below is an example of what is happening...

C#:
//MYTEST.DLL
//I put both the struct and the class... in actuallity its either one or the other...same with procedures
//I just wanted to show for example...
public strcut Demo1
{
     public string ItemX;
     public string ItemY;
}
public class Demo2
{
     private string ix = "";
     private string iy = "";
     public string ItemX;
     {
          get { return ix; }
          set { ix = value; }
     }
     public string ItemY;
     {
          get { return iy; }
          set { iy = value; }
     }
     public Demo2()
     {
          //no initialization
     }
}
public Class DoDemo
{
     public Demo()
     {
           //no initialization
     }
     public static Demo1[] GetItems()
     {
           Demo1[] items;
          //Code that does the external procedures and sets items
          return items;
     }
     public static Demo2[] GetItems()
     {
          Demo2[] items;
          //Code that does the external procedures and sets items
          return items;
     }
}
//The calling program looks like this:
public SomeProcedure()
{
     Demo1[] d1 = DoDemo.GetItems();
     foreach(Demo1 d in d1)
     {
           DataRow r = myTable.NewRow();
           r[0] = d.ItemX;
           r[1] = d.ItemY;
           myTable.Rows.Add(r);
     }
     myDataAdapter.Update();
}

If the actual values returned by the procedure were:

TEST123
SOMEBODY
ANYTHING
FOUR
EXTERNAL

What would go into the database is the following:

TEST123
SOMEBOD
ANYTHIN
FOURHIN
EXTERNA

Notice that because the first return string was a length of 7, it truncated all other strings to 7 if they were longer, if they were less it appended the remaining letters from a previous value that has 7 characters.

Now if instead of the above procedure I was to have:

C#:
public SomeProcedure()
{
     Demo1[] d1 = DoDemo.GetItems();
     foreach(Demo1 d in d1)
     {
           myListView.Items.Add(d.ItemX);
           myListView.Items[myListView.Items.Count - 1].Tag = d.ItemY;
     }
}

Everything would display proper on the control. And what this is the crap Im doing now to get things to work... I put everything into a hidden ListView and then from the ListView into a database... absolutely horrendous programming; I know this! And I want to fix it! - (update) Actually read my update below, only the next paragraph works, the above actually results in the same problem. (/update)

I also can move my DataAdapter.Update() method into the foreach loop, but that causes such large program lag that I rather just leave the horrendous programming to be honest with you.

This scope/reference problem Im having is driving me up the wall. Im willing to send the actually DLL that is doing this to someone who is knowledgable enough about using external procedures that use a lot of marshalling and memory management to fix the problem. This will be a great learning experience for me because Im lost on this one.


Thanks!
 
Last edited by a moderator:
Two things - what does your update statement look like for that data-adapter, and second, how is that column in the database defined?
 
the data adapter set-up statement looks similiar to this, the real one has more fields and a primary key, but again to keep it simple... also in the database in case your wondering the string length is set to 50:

C#:
//Insert Commands [..]
da.InsertCommand = new OleDbCommand("ADD_DEMO", myConn);
da.InsertCommand.CommandType=CommandType.Procedure;
da.InsertCommand.Parameters.Add("@ItemX", OleDbType.Char, 50, "ItemX");
da.UpdateCommand.Parameters.Add("@ItemY", OleDbType.Char, 50, "ItemY");

//Update Commands [..]

//Delete comands [..]
 
Last edited by a moderator:
Okay then, that answers my first questions.

Now, did you interrogate the data-table before you issue the Update on your data-adapter to see that the values there are as expected?
 
Ill tell you this... I added the OnUpdating Event and looked at the parameters as they are going in and they look correct - at least in the Locals window - hope that was what you were asking for, I was on the track that maybe the database was corrupted or something too originally... but like I said, calling Update() during the for loop doesnt have any problems, and I went back and tested, and actually adding the values to a list box and then putting them in the database actually has the same problem, unless of coarse I move the update into the for loop where Im now going through the listbox list. Its the strangest thing Ive ever seen... thanks for helping on this btw...

Also, fyi, Im pretty much using a copy and paste of other databases Ive done that have worked fine, but dont use that api wrapper class. The table in this dataset I was originally using FillSchema with, but thinking that might of been the problem I stopped using that and made the information via code myself, but that resulted in the same problem.
 
Last edited by a moderator:
Also, I did the following; I changed from CommandType.StoredProcedure to CommandType.Text and in my RowUpdating Event I changed my SQL text as needed so the rows would be updated, this worked perfectly as expected. I dont know whats going on with this thing.

Also I tried a whole new database building from scratch, same thing.
 
Last edited by a moderator:
Well its deffinitely that custom class, I can pass just strings in an array and everything works like it should. Ive tried Copy and Clone, but no matter what it seems as if theres a reference problem in my custom class that whenever Im trying to save the property it gets this problem. I dont know how to fix it. Any volunteers? Ill send the entire source code. Its a great class, gets your domains and computers on a domain easily and as quick as network neighborhood does.
 
Either attach the zipped source here (remove the .exe files though) or PM me with the code and Ill have a look as soon as I get a bit of spare time.
 
I got a quick chance to walk through the code and it seems like your datatable is the cause of truncation.

I put a breakpoint on: DOMAINS.Update(ds, "DOMAINS");

and in command window:
? ds.Tables["DOMAINS"].Rows[1].ItemArray[1]
"ODO1S"

which should be "ODO1SIMULATOR"

Ill see later if I can narrow this down some more - perhaps if you create a schema for your data-table it would work?
 
Thanks for looking... Ive tried using FillSchema(), building the schema manually, having no schema at all and lettin ADO take care of it, it all comes out the same; Im glad to hear though that its happening on someone elses computer...now I dont feel completely insane.

Heres a list of things Ive tried and have failed, but please try again if you think it will work - I couldve screwed it up:

-Take out the dataset and just using the table
-Use SQL text with parameters
-Rebuilding the database from scratch
-Changing the names of the parameter to something totally differant from the column
-not using the @ symbol
-unencrypting the database
-explicitly telling the shcema that the string length if 50 (which it showed up in the schema anyway...but...had to try)

Things that did work:
-Putting Update() in for loop - takes the point out of disconnected data though...

-Having SQL text like the following:
"INSERT INTO DOMAINS (DomainName, Track) VALUES ({DomainName}, {Track})"
and then putting in the RowUpdatingEvent()
string s = da.UpdateCommand.CommandText;
s = s.Replace("{DomainName}", e.Row["DomainName"]);
s = s.Replace("{Track}", e.Row["Track"]);
da.UpdateCommand.CommandText = s;
---now that is just plain silly and horrible, but it worked!

Im grateful for any help any of you find!

Brian
 
Now this is weird - I created a new Access database with one table like your, and then added your queries. I didnt apply any security, etc to the file, and everything ran exactly as I expected.

Now, when I started to model my table after yours, as soon as I set the DomainName.Required = Yes (from default of No value), I got the error you got.

So, I deleted the table and re-added the same layout, just setting the column names and data-types (left all else as default).
 
Unfortunately that didnt work for me; I deleted the table, then re-made the table, using defaults for each column (just changed the yes/no type to true/false - did you do that?, and made ID auto number and primary key), and still same thing... like I said though, Im glad to see its just not me, thanks for your help with this, let me know if you find anything else!
 
Try creating a new Access file and re-create your table (with defaults to start - then tweak your columns)/stored procs in that file. Thats the way I got it to work.
 
I did exactly that, I also PMd you a message with my email to send me your database that worked so I can see what if any difference there is...
 
I figured it out! I figured it out!

Im excited about this... in the parameter for "DOMAIN" ("@DomainName"), change the length from 50 to 0... dont know why... makes it work though... Im going to research later, because I do want to know why!!!!!! Anyone who would know why, please share the wealth!

Thanks PD and mocella for your help through this... Im like 4 days behind now, but now I can code correctly...THANKS AGAIN :D
 
Back
Top