|
The problem here, though, isn't enumeration in general. It's the Hashtable+HashtableEnumerator that's the problem (though I wouldn't call it a problem). A Hashtable isn't a simple collection (it's not really a collection at all), so enumeration is complicated. Enumerating over an ArrayList (using the ArrayList+ArrayListEnumerator ) is much, much faster, as his performance results showed.
The problem here is just a case of using the right enumeration. It wasn't just the native code behind Array.Copy that produced better results (the ArrayList was still enumerated, remember).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Doh...that's what I get for not reading the original code thoroughly...for some reason, my brain translocated the foreach loop.
At any rate, although it's extremely unlikely, might leppie be on to something with collisions? What method does the Hashtable use to solve collisions, some sort of linked bucket? Only problem with that theory is insertion would take a much longer time as well...
Jeremy Kimball
I have traveled the gutters, lo these many days, with no signs of life. Well met.
-brianwelsch
|
|
|
|
|
No, because collisions occur when you insert items into a Hashtble . The original post is merely enumerating it. That merely entails enumerating the root buckets as well as any child buckets. In such a case, no hashing is necessary at all.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi Heath,
If you chage the WriteTokensFast function to this:
private void WriteTokensFast()
{
ArrayList tokenList = new ArrayList();
foreach (Token tokenItem in tokensHT.Values)
tokenList.Add(tokenItem);
WriteCollection(tokenList);
}
It still only takes 10 to 12 seconds to run even though it is iterating through the Values and casting them to a Token object (the slow function takes a minute and 40 seconds).
|
|
|
|
|
Interesting, though there is another likely possibility: if this is the first time your using those particular types, they must be JIT compiled. After that is complete, the types are cached as native code so the performance is akin to native code.
Try reversing the order of your calls and you should find the previously faster one takes as much time.
The Hashtable+HashtableEnumerator is still more complex. I'm surprised your not seeing a significant difference with around 39 MB of data in the Hashtable . I would expect a few seconds difference.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi Heath,
I actually ran these in separate test app runs. They weren't getting executed in the same process one after another, so that wouldn't be it.
I am completely clueless to the cause, but I spent a lot of time testing slightly different scenarios to figure out where the problem was with the slow function. I've basically ruled out iterating through the hashtable and casting as the culprits, but that leaves me with nothing.
I've been programming using C# and the .Net framework since the beta of version 1 was available, and this is easily the strangest performance quirk I have come across.
|
|
|
|
|
the real bryon wrote:
I've been programming using C# and the .Net framework since the beta of version 1 was available
Same here. That case is far from true for the majority of programmers (notice I didn't say "developers"?) that come here.
The only other thing I can think of is to profile the code and see where the bottleneck is. You can download a decent free one somewhere on MSDN, and there's other commercial ones around the 'net (including the Ants profile that advertises here on CodeProject).
This sure is a strange problem.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Interesting, I didnt notice passing your ICollection implentation as a parameter to the constructor, uses that. I will keep this in mind
However, I still cannot see why it should take so much longer. Maybe fixing the Capacity to a HUGE initial value could solve it, the only thing I can think of is collision checking, so the hash is more spread, that will require more memory too.
top secret xacc-ide 0.0.1
|
|
|
|
|
When you pass an ICollection to the ArrayList ctor, the Capacity is set to the number of elements in the ICollection using the Count , yes.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
How to cast from type 'DBNull' to type 'integer'
|
|
|
|
|
IamADotNetGuy wrote:
How to cast from type 'DBNull' to type 'integer'
Why? Null means the absence of a value. What integer value would you cast it to?
"You can have everything in life you want if you will just help enough other people get what they want." --Zig Ziglar
The Second EuroCPian Event will be in Brussels on the 4th of September
Can't manage to P/Invoke that Win32 API in .NET? Why not do interop the wiki way!
My Blog
|
|
|
|
|
Hi
sorry bit correction
One of the table in database is accepting Integer value,
But sometimes i want to pass null value to this column.
Please let me know on this
|
|
|
|
|
Ah! Okay that is easier:
If you are passing values in as parameters it is something like this:
command.Parameters.Add("@MyInteger", DBNull.Value);
If you are using some other means of inserting data and this doesn't make sense, let me know and I'll see if I can cook up an example for you.
"You can have everything in life you want if you will just help enough other people get what they want." --Zig Ziglar
The Second EuroCPian Event will be in Brussels on the 4th of September
Can't manage to P/Invoke that Win32 API in .NET? Why not do interop the wiki way!
My Blog
|
|
|
|
|
to pass a null value to a DB you must specify the value NULL in the insert string...
INSERT INTO MyTable (MyColumn) VALUES (NULL)
now if you want to retrieve NULL's as a 0 value from the column you could do the following in SQL:
SELECT ISNULL(MyColumn, 0) FROM MyTable
this will return the value of 0 instead of NULL
of course this is assuming you are writing the SQL string if not, then I'd go with the other solutions
|
|
|
|
|
The best I can think of is something like this:
object fieldValue = reader.GetValue(columnIndex);
if (fieldValue == System.DBNull.Value)
fieldValue = 0;
"You can have everything in life you want if you will just help enough other people get what they want." --Zig Ziglar
The Second EuroCPian Event will be in Brussels on the 4th of September
Can't manage to P/Invoke that Win32 API in .NET? Why not do interop the wiki way!
My Blog
|
|
|
|
|
Sorry. No can do...
DbNull represents an unknown value, and an int has no means of representing that.
One way around this can be to define a specific integer value as the value of unknown/not set/DbNull. For instance use -1 for this if valid values for your integer always are positive.
object obj = some_value_thats_either_an_int_or_dbnull;
int i = obj is DbNull.Value ? -1 : (int)obj;
Have a look at my latest article about Object Prevalence with Bamboo Prevalence.
|
|
|
|
|
How can i insert null value to a column of number type??
|
|
|
|
|
|
I am new to C# but have plenty of programming knowledge in C++ and Java.
I have a question on my logic for a program I am doing.
What I am doing is reading in a few tables from an Access DB and binding them to a form textbox fields. The form comes up with "company" infomation, and then in a subform is the contacts for that specific company. The company information is in one table with a foreign key to the contact table.
Now I can bring up all the company info and all the contact info right now. But I want the subform just to show the contacts just for that specific company. Is there a "filter" or something that I can run against my contact DataSet to show the appropiate rows, and hide the others?
I know this is pretty vague, but I just need the logic on how to do something like this.
_Jacob
|
|
|
|
|
What are you using for a control to display the contacts?
Yes, there is a way to filter results. See the DataView class, which you create over a DataTable (or modify DataTable.DefaultView ). But you may not have to.
If you use a DataGrid to display the contacts, you set the DataSource property to the DataSet , and set the DataMember to the "table.relationshipName", where "table" is your table name and "relationshipName" is your company<-contact relationship name. I know this works with two DataGrid s, and it should work with bound TextBox es since they use the same currency manager.
When using two DataGrid s, they both have the DataSource property set to the same DataSet . The master grid sets the DataMember to the table name only. The detail grid does what I outlined above. When you select a record in the master grid, the current item is used to automatically filter (via the DataRelation ) the detail grid. Since this all ties back to the CurrencyManager , a bound TextBox should work, too.
Here's to hoping!
Let me know. I don't have time to throw something together right now and have never had a need to try it this particular way.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Ok I will include some code.
I am pretty much doing what you said, - the DateView. I have to look up how to use that.
Heres what I have so far for an idea...
myConn.Open() ;
//Create DataSet myCompanyDataSet
OleDbDataAdapter myCompanyAdapter = new OleDbDataAdapter(strCompanyCom, myConn);
OleDbCommandBuilder myCompanyBuilder = new OleDbCommandBuilder(myCompanyAdapter);
myCompanyAdapter.FillSchema(myCompanyDataSet, SchemaType.Source);
DataTable CompanyTable = myCompanyDataSet.Tables["Table"];
CompanyTable.TableName = "tblCompany";
myCompanyAdapter.Fill(myCompanyDataSet,"tblCompany");
//Create DataSet myContactDataSet
OleDbDataAdapter myContactAdapter = new OleDbDataAdapter(strContactCom, myConn);
OleDbCommandBuilder myContactBuilder = new OleDbCommandBuilder(myContactAdapter);
myContactAdapter.FillSchema(myCompanyDataSet, SchemaType.Source);
CompanyTable = myCompanyDataSet.Tables["Table"];
CompanyTable.TableName = "tblContact";
myContactAdapter.Fill(myCompanyDataSet,"tblContact");
//Setup Relationship
myCompanyDataSet.Relations.Add(new DataRelation("ParentChild",
myCompanyDataSet.Tables["tblCompany"].Columns["COMPANYID"],
myCompanyDataSet.Tables["tblContact"].Columns["CompanyID"]));
---------------------------------
Thats what I have to for the connection and relationship.
my dataGrid is hooked up like this:
dataGrid1.DataSource = myCompanyDataSet;
dataGrid1.DataMember = "tblContact";
----------------------------------
Right now it still just prints all the contacts on the table no matter what record i am on.
Do you have any comments on this?
|
|
|
|
|
Ok I have it now being sorted:
I had to have the binding look like this:
dataGrid1.DataSource = myCompanyDataSet;
dataGrid1.DataMember = "tblCompany.ParentChild";
I just realized you have to use the master table then the relationship to pull out the filtered contacts.
My last Question is that when I am pressing my next/previous buttons and the text fields are updating with the right info but the Contact subform still shows the same information. ie its not being updated. I am thinking that the binding is not set correctly?? or maybe its not recomparing the table right to find the current company and contacts??
Thanks for the help.
Anyone have any hints?
|
|
|
|
|
I everyone... I need your help...
I am new to C# but i have good base in C++... its all look the same anyway...
Ok so, here the situation. I want to create a template container class. In c#, I found that is call a generic. So i use the 'Object' parameter for every function who need to works on the object that is "contained". My container is first design to use numerical object (int, float double), but to make good programmation i want it to be more flexible.
So here's my problem. I got some method that use mathematical operand like '+','-' and '*' on object thats is in my Arraylist. At compilation time i got the error:
Operator '+' cannot be applied to operands of type 'object' and 'object'
Yeah, I know, but there is no object in...yet....
Why is he bothering me with that. if a put a "int" in the list the '+' is define...
So, does anyone know a way to make a generic container that can use arithmetic operand on object.
Like a good old template class...
here a code sample to show what i mean:
the function that cause problem:
////////////////////
public void SourceAddSourceHandler(object S,OnNewDataEventArgs Args)
{
if(mLeftS!=null && mRightS!= null)
{
for(int i=this.Count;i
|
|
|
|
|
An object in C# is not the same thing as a template in C++. The current version of C# does not have generics nor nothing similar to templates.
You're right, you can overcome this limitation by using interfaces and/or the object data type. But you should think the object data type in the same way you use the 'void *' in C++: most of the time you'll need to cast it to the appropriate type to do something useful.
HTH...
Yes, even I am blogging now!
|
|
|
|
|
And to add to what Daniel said, that casting can be expensive, especially if your casting a struct to an object (boxing). An object is created and its members are filled with the members of the struct, then it is returned.
Generics in .NET (not just C#, mind you) will eliminate this problem since the object will actually be stored as the actual object type (unless it's a child class of an abstract type or interface, but that's besides the point) and no casting or boxing/unboxing is required.
Microsoft MVP, Visual C#
My Articles
|
|
|
|