Error using form dataset over coded instance

pachjo

Well-known member
Joined
Dec 12, 2006
Messages
370
Programming Experience
10+
OK so I am now getting into changing my app so I use designer created data access objects, dataset, tableadapter etc.

I am plodding along nicely but have come across this error which I dont understand why it happens.

{"Input string was not in a correct format."}

Now the previous "messy" way I was coding actually worked the first time I coded it and I did not think anything more about it.

Here it is:

VB.NET:
If Not glb_dtTransactionDesc.Rows.Find(txtTextBox.Text) Is Nothing Then

glb_dtTransactionDesc started life as:

VB.NET:
Public glb_dtTransactionDesc As New DataTable

Now here is the new way I am doing it which does not show any syntax error but does crash with the previously stated error above:

VB.NET:
If Not Me.MyFinanceDataSet1.TransactionDescriptions.Rows.Find(T.Text) Is Nothing Then


Note T is the same as txtTextbox......renamed as it is a through away object:)
 
Right I think I have found the problem and it is to do with the primary key of my table.

I have two tables which I had to setup like this to be able to create a key constraint.

TransactionDescriptions (Table)
-----------------------
descriptionID (Primary)
description (indexed no duplicates)


Transactions (Table)
---------------------
transactionID (primary) (indexed no duplicates with transactiondate)
transactiondate
descriptionID (foreign key)

This makes sense to me. But now I cannot use the .find method as it wants to match on a primay key not the actual description text. If I make description the primary I cannot create a foreign ket contraint in the other table???
 
Can you use Select?

VB.NET:
Dim results() as DataRow 'array
Dim findStr as String = string.Format( _
  [COLOR=gray][B]"[Description] LIKE '%{0}%' AND [Age] < {1} OR [BirthDay] >= #{2:MM/dd/yyyy hh:mm:ss}#"[/B][/COLOR], 
  descrTextBox.Text, _
  ageTextBox.Text, _ 
  birthdayDateTimePicker.Value _
)
rows = myDataSet.MyDataTable.Select(findStr)
 
If rows.Count = 0 Then
  'no matches
Else
  'you can iterate the row results or something..
End If

I added extra things here like AGE and BIRTHDAY that you dont need; i'm just demonstrating how to use Select.. note that dates must be in that american format. You cannot supply a date in any other way
 
also, consider whether you should be getting the database to do this select.. if youre just after a quick "find" e.g. when the user has a grid of 100 rows, and they quickly want to see rows that contain "apple" then for sure you can select the rows, then highlight them or something.. But dont use this method to e.g. download 5000 results from the database, and then use Select for heavy duty searching; index the database column and use the database to search; it's what they do best
 
Hi cjard, thanks for your input ;)

All I am trying to do is to let the user know if the transaction description they are trying to add already exists.

They enter the entry in a textbox and click save. I then see if it exists before trying to save it.

I remember some time ago I used select as you say but think I was told .find was better? Will have a search.

So is it a case that the .find would never work in this way?

Thanks
 
I remember some time ago I used select as you say but think I was told .find was better? Will have a search.
Like most things in life/computing there is no "better" or "worse".. there are different thigns for different purposes

.Find is for very quickly retrieving a single row as dictated by the primary key.
.Select parses the text you supplied and enumerates all rows looking for ones that match the criteria. Understandably this operation is significantly slower

The cases for using both, are limited

So is it a case that the .find would never work in this way?
It really does depend on what youre doing. If you had a dataset and you wanted to retrieve a row somewhere, based on its primary key then you could use .Find .. but that doesnt necessarily mean that you should


Here is a ridiculous scenario:
A table has a million entries. You, the programmer, writes code that downloads all million entries, then throughout your program, you use .Find or .Select, ignoring the role of the database completely
--> Noone sensible would do this

Similarly:
You have an operation that will execute a million times, each time it needs a different value from the database to the last, but in total, it is probably only going to use 50 distinct database values. You code your app so it hits the database a million times. By the time it is done, the database has returned each value, on average, 20,000 times.


Hopefully you can see how silly both these are. In the first case, you would leave the data in the db and let it search; thats what databases do.
In the second, you would download all 50 in advance, and Find() them repeatedly, removing the network transit bottleneck

All I am trying to do is to let the user know if the transaction description they are trying to add already exists
If transaction description is to be unique, then why is it not the primary key of the table?

Consider that you would be better off just putting a Unique Index on the table (different to a primary key) description column, thereby ensuring that it is impossible to enter the same description twice.


Note that we dont normally key off descriptive fields.. I suspect that there may be an oddity in the data layer of your program..
 
Hi,

I did go back and change the setup of the database so that description is now the primary key and descriptionid is a unique index which is the foreign key in the transactions table.

But now you have made me think?

I usually code a so in this scenario if a user tries to enter a duplicate entry I catch it in an if staement and provide a friendly message telling them their mistake.

But are you saying I should let the try/catch block trap it instead? In doing so does this not just display a message that most users would not understand?

BTW I am seeing now how FANTASTIC using datasets/tableadaptors and bindingsources are:D

How the hell did I ever get into the awful way of coding it all manually? Thanks for pointing me on the path of true enlightenment;) :)
 
Mmm I am trying to see how I can compare the type of the exception with that of System.Data.DBConcurrencyException so that I can provide a friendlier error message.

Is this the correct approach?
 
Mmm this works:)

VB.NET:
[SIZE=2][COLOR=#0000ff]Catch[/COLOR][/SIZE][SIZE=2] objError [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] SqlClient.SqlException[/SIZE]
[SIZE=2][COLOR=#0000ff]Select[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Case[/COLOR][/SIZE][SIZE=2] objError.Number[/SIZE]
[SIZE=2][COLOR=#0000ff]   Case[/COLOR][/SIZE][SIZE=2] 2627[/SIZE]
[SIZE=2][COLOR=#0000ff]          Me[/COLOR][/SIZE][SIZE=2].MyFinanceDataSet1.TransactionDescriptions.Rows.Remove(ro)[/SIZE]
[SIZE=2]MessageBox.Show([/SIZE][SIZE=2][COLOR=#a31515]"The transaction description "[/COLOR][/SIZE][SIZE=2] & t.Text & [/SIZE][SIZE=2][COLOR=#a31515]" already exists"[/COLOR][/SIZE][SIZE=2], _[/SIZE]
[SIZE=2][COLOR=#a31515]"Duplicate Entry"[/COLOR][/SIZE][SIZE=2], MessageBoxButtons.OK, MessageBoxIcon.Exclamation)[/SIZE]
[SIZE=2][COLOR=#0000ff]Case[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Else[/COLOR][/SIZE]
[SIZE=2]         MessageBox.Show([/SIZE][SIZE=2][COLOR=#a31515]"Location: btnSaveDescription_Click"[/COLOR][/SIZE][SIZE=2] & System.Environment.NewLine & System.Environment.NewLine & [/SIZE][SIZE=2][COLOR=#a31515]"The following error occurred whilst saving the description changes"[/COLOR][/SIZE][SIZE=2] & _[/SIZE]
[SIZE=2]System.Environment.NewLine & System.Environment.NewLine & objError.Message & System.Environment.NewLine & System.Environment.NewLine & [/SIZE][SIZE=2][COLOR=#a31515]"If the problem persists contact support@......"[/COLOR][/SIZE][SIZE=2], _[/SIZE]
[SIZE=2][COLOR=#a31515]"Save Error"[/COLOR][/SIZE][SIZE=2], MessageBoxButtons.OK, MessageBoxIcon.Error)[/SIZE]
[SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Select[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Catch[/COLOR][/SIZE][SIZE=2] objError [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Exception[/SIZE]
[SIZE=2]MessageBox.Show([/SIZE][SIZE=2][COLOR=#a31515]"Location: btnSaveDescription_Click"[/COLOR][/SIZE][SIZE=2] & System.Environment.NewLine & System.Environment.NewLine & [/SIZE][SIZE=2][COLOR=#a31515]"The following error occurred whilst saving the description changes"[/COLOR][/SIZE][SIZE=2] & _[/SIZE]
[SIZE=2]System.Environment.NewLine & System.Environment.NewLine & objError.Message & System.Environment.NewLine & System.Environment.NewLine & [/SIZE][SIZE=2][COLOR=#a31515]"If the problem persists contact support@......"[/COLOR][/SIZE][SIZE=2], _[/SIZE]
[SIZE=2][COLOR=#a31515]"Save Error"[/COLOR][/SIZE][SIZE=2], MessageBoxButtons.OK, MessageBoxIcon.Error)[/SIZE]
[SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Try[/COLOR][/SIZE]
 
Hi,

I did go back and change the setup of the database so that description is now the primary key and descriptionid is a unique index which is the foreign key in the transactions table.
Erm.. You did this in the database? Purely for the sake of providing a quick lookup based on a description, you made a descriptive field the primary key? I really wouldnt have done that, but hey.. it's your app..

.Find and .Select are dataset methods that work without ever accessing the database. If youre prepared to go to the lengths of editing the database, then you should consider what is to do the work and how you can realise a multi tier security model out of this..

Just think about the logic of this for a moment; if you have a descriptive column that you assert will be unique and hence sufficient to identify exactly one row, then why do you have another column that is unique, and is called somethingID indicating it is an ID field.. So given that it is unique, it can be used to ID one row, so whats the point of the other column? Why do you have two independently unique columns on a single table? It could indicate a normalisation error or flaw in the database design.
There's a can of worms here, and I dont like it..

But now you have made me think?
That's actually quite a compliment
;)

I usually code a so in this scenario if a user tries to enter a duplicate entry I catch it in an if staement and provide a friendly message telling them their mistake.
Erm. I usually configure the back end so a duplicate entry is impossible to achieve, and I dont run a check for everything before I try to achieve it because I would spend my entire coding life writing check routines.

But are you saying I should let the try/catch block trap it instead?
Yes! In most things in life, we try a dangerous thing with knowledge of how to handle things that go wrong. It is rare that things go wrong, and as a result we achieve better performance.

Suppose we are coding a routine that inputs a value into a table
A PK exists ensuring no duplicate rows
We can do (pseudocode):

VB.NET:
SELECT COUNT(*) FROM table WHERE pk = whatever
If count > 0 then
  MessageBox.Show("That record already exists")
Else
  INSERT INTO table VALUES(1,2,3)

or we can just try it:
VB.NET:
Try
  INSERT INTO table VALUES(1,2,3)
Catch
  MessageBox.Show("That record already exists")

In the first case, the db scans the table and retrieves the count. lets say this takes 1 second
Then your app decides it is safe to insert
The insert command scans the table to make sure it is safe to do the insert
When it is safe, the insert is done

2 table scans are needed for this. OK, they are quick because PK accesses are quick, but youre senselessly doubling up what the database does!


In the second, we jsut insert. The db scans and checks and then does the insert. SOME of the time an error occurs, not all. By assuming that we will mostly be successful we dont waste time doing scans for safety that arent required

In doing so does this not just display a message that most users would not understand?
Um, Try/Catch blocks themselves NEVER show a message by default. You and only you, the programmer, shows info to the user. If your complaint is of the complexity of the message you show, then show something simpler.


How the hell did I ever get into the awful way of coding it all manually?
Tradition? ;)

Interestingly, it is still all coded manually.. Its just that the manual code is generated automatically.. Kinda like having your passenger change gear for you in the car doesnt mean you have an automatic transmission, but it does mean you dont have the bother of doing it ;)
 
Just think about the logic of this for a moment; if you have a descriptive column that you assert will be unique and hence sufficient to identify exactly one row, then why do you have another column that is unique, and is called somethingID indicating it is an ID field.. So given that it is unique, it can be used to ID one row, so whats the point of the other column? Why do you have two independently unique columns on a single table? It could indicate a normalisation error or flaw in the database design.
There's a can of worms here, and I dont like it..

LOL read back a bit dude, I am removing redundantcy.

I have a description table and a transaction table.

The description is unique yes. But I don't want to store the description text for each row it is used in the transaction table so I use a descriptionID instead.

If I have 100 rows with a transaction description of

"a very very very very ....... very long description"

Is it not better to store the descriptionID of 3 and lookup the text when needed?
 
Erm. I usually configure the back end so a duplicate entry is impossible to achieve, and I dont run a check for everything before I try to achieve it because I would spend my entire coding life writing check routines.

Um, Try/Catch blocks themselves NEVER show a message by default. You and only you, the programmer, shows info to the user. If your complaint is of the complexity of the message you show, then show something simpler.

Well I think you can see I do now have the back end ensuring unique values only.

When I first posted I did not know of the SQLException object and therefore did not know that I could trap the exact error and thus provide a more descriptive message.

However tis now done ;)
 
Is it not better to store the descriptionID of 3 and lookup the text when needed?

Yes, but you wouldnt make the description the primary key.. You'd make the ID the PK and put a check constraint of "not exists" on the description field, or a unique index if your rdbms doesnt support coded constraint checks
 
I did originally have the DescriptionID as primary but am making so many changes I suspect I am getting completely discombobulated.

Basically as I am so bloody minded I am rewriting my whole application again by importing each 'old style' function / sub and addressing the mess contained within one step at a time.

Painful I know but I'm sure you can image the amount of code I have removed simply by using the designer generated dataset, table adapters etc.

With each old block I import, I cringe as it jumps out at me how crap it really was!!
 
Back
Top