C# LINQ - Recognize unique index violation - linq

I am using Linq-to-SQL for accessing SQL Server 2008.
In database I have UNIQUE index on some column.
When I enter duplicated data in that column, LINQ will throw SqlException with an error message. Is there a way to figure out that exception is related to UNIQUE index and not some other SQL error?
Solution I am aware of is to user RegEx to parse exception message, but I would like to know is there more elegant approach?

You could use the SQLException.Number property.
For more details you could iterate the Errors collection each of which have thier own number.
As an aside, in the past I have written my own custom serialiser for SqlException but it appears that in 4.5 ToString() has been overridden so this is not now necessary.

You could check the table having the unique constraint on whether it already has a row with some value in the constrained column:
if (linqDataContext.ConstrainedTable.Any(row => row.ConstrainedColumn == somevalue))
{
//show a message, saying you've already got this value
//and it is not applicable
}
else
{
//accept your changes with smth like this:
linqDataContext.SubmitChanges();
}
Another question, whether this approach is applicable for you, i.e. whether the cost of this query overwhelms the cost of catching an exception and processing it. If the constrained column is indexed, than a simple request on that column must not be that costy.

Related

JdbcTemplate update, why do we need to pass in types?

This post helped me a bit, explaining that JdbcTemplate will figure out which column to fill on its own. However, it means that there's no need to pass in the types, so why/when should we do it?
Another related question: I accidentally passed an Object[] rather than int[] and the app gave me an exception in mysql: Data truncation: Data too long for column 'username' at row 1. However, the parameter was just "test" and the column was VARCHAR(60). Though I realize that Object[] will not be autoboxed to int[], but what makes it "too long"? I think it's related to the implementation of how does update() use types, but I cannot figure it out...
Thank you for answering!

Exception handling using Oracle Forms Builder

I am making my first Oracle form in Oracle Forms Builder with the help of web material i.e. tutorials etc. I have written the following code in the WHEN-BUTTON-PRESSED trigger:
INSERT INTO PATIENT VALUES
(:CNIC_NO, :P_NAME, :CITY, :ADDRESS, :GENDER, :BLOOD_GROUP, :DISEASE, :WARD_NO);
COMMIT;
The problem here is that an unhandled exception is raised by the trigger with the following error numbers:
ORA-12899 (Reason is the Null value is inserted in non-Null column)
ORA-1400 (Reason is that the data length is too large than the allowed length)
I need to popup an informative message box for these and a default one for the others.
First of all I would avoid this errors by builtin Oracle forms validation. Set Required property to True on property panel for all items, which are based on not null database columns. Oracle forms then forces user to enter a value.
Next set Datatype and Maximum length properties to set basic data validations.
This should be enough in your case. If your still want to catch an exception, use code like this:
begin
INSERT ...
exception
when others then
message(DBMSERRTEXT);
end;
Anyway - it is not good idea to insert data using when button pressed triggers. It is not transaction safe. Use standard forms block. Oracle forms does all the data validations and manipulations for you.
You have either to guarantee there is a suitable value will be inserted in the specified column that doesn't accept null value the you have to use NVL function inside the insert statement. Well, it's quite a good idea to have a technique too.
handle Oracle Forms errors and informative messages
You have also to construct your table columns size larger enough to store the inserted as the address for example must be larger than 100 varchar2.
You can use The Default Oracle Forms Menu Tool Bar will handle the form's CRUD Operations for you. Instead of writing the insert,update,etc.
But, you have to specify using it by yourself for every form module.

How to use calculated fields in my LightSwitch Query?

in my lightswitch application im trying to create a Customers Screen for customers who have balance value, and my balance value is a Calculated Field in the Customer Entity
when i tried to put the logic in the Process Query Event Like This
query =( from i in query
where(i.Balance>0)
select i );
i get an exception .. what is the best way to handle these kind of situations ??
i saw an answer here but i didn't know how to implement it exactly i need a sample code for it can anyone help me ??
thanks in advance
The query will be executed by the data provider, which doesn't know about calculated fields. What you can do is to filter what you want via LINQ, referring to the actual fields, not the calculated ones.
For example, let's say Balance is your calculated field, that you defined as Credit - Debit (which are normal fields). You want your query to return the rows where Balance > 0. This is how you'd write the query (in the PreprocessQuery event, note there is no ProcessQuery event):
partial void TestQuery_PreprocessQuery(ref IQueryable<Customer> query)
{
query = (
from c in query
where ((c.Credit - c.Debit) > 0)
select c);
}
Another theoretical way of solving the problem would be setting a filter in the Executed event handler. However, for whatever the reason, when I do it, the filter is not applied to the screen. But even if this method would work, still you'd be filtering on the client side, which might not be what you want.
I'm actually looking for a solution to this problem
(unfortunately I can't just include the calculation from the calculated field, because my calculation uses another calculated field which uses recursion)
A couple of pointers I thought you might find helpful:
#julio.g - for the Executed event handler, the "result" parameter is an IEnumerable parameter (as opposed to the PreProcess_Query event handler, where the "query" parameter is a ref IEnumerable) so any changes you make to the "result" will only be local to that method
#3oon - afaik, SQL Views are not supported in LightSwitch. The best option I've come across so far is to create a WCF RIA Service based on a Stored Procedure, then adding it as a datasource.
This blog post should help get you started.
http://tejana.wordpress.com/2010/12/09/microsoft-lightswitch-and-stored-procedures-using-wcf-ria-services/
Hope that helps!

How to Get Primary Key and Unique Constraint Columns in Derby

How does one do this? The SYSCOLUMNS system table only has columns for tables. SYSCHECKS has a REFERENCEDCOLUMNS object. Is there any way to get this.
I'm aware of the JDBC getPrimaryKeys call, but that doesn't get unique constraint columns.
Derby - constraints
It took some digging to find the above question; my question is a partially answered follow-up question to the one above.
Taking the CONSTRAINTID against SYSKEYS gives a CONGLOMERATEID, which when taken against SYSCONGLOMERATES yields a DESCRIPTOR. The DESCRIPTOR is a POJO that contains an int-array in the baseColumnPositions method. This int-array contains the COLUMNNUMBERS in SYSCOLUMNS of the columns in the constraint.
If querying in straight SQL, getting the DESCRIPTOR field yields a string with a CSV list of ints that have to be parsed. Fortunately for me, I happen to be working in Clojure, so calling the baseColumnPositions method and using the resulting int-array are trivial.

LINQ Insert query

Me again!
I have a question re. inserting into a sql table using LINQ. I am essentially creating a feedback form whereby a user enters there details, hits submit and their data is inserted into a sql table.
I haven't got very far!!!
protected void btnSubmitFeedback_Click(object sender, EventArgs e)
{
ORFeedDataClassesDataContext db = new ORFeedDataClassesDataContext();
tblOnlineReportingFeedback newtblonlineReportingFeedback = new tblOnlineReportingFeedback();
newtblonlineReportingFeedback.Name = "txtbxFdName";
db.tblOnlineReportingFeedbacks.InsertOnSubmit(newtblonlineReportingFeedback);
db.SubmitChanges();
}
I have set up the sql table so that an unique autonumber is inserted each time a row is inserted. However, when I run the above, I receive the following:
"SqlException was handled by user code - String or binary data would be truncated. The statement has been truncated"
Can anyone think of a work around for this? Chances ar emy code is a load of poo anyway so if someone can correct me, I would be most grateful.
The error you're getting is caused by your Name column in the tblOnlineReportFeedback table.
The length of the column is not long enough to hold the data.
try changing the column to at least VARCHAR(11)
Also, i'm not sure if you're meaning to put txtbxFdName as the string to insert. It sounds to be it should be getting it from a textbox named "txtbxFdName"
newtblonlineReportingFeedback.Name = txtbxFdName.Text;
The error message states that the field Name in the database is too small to contain the value you're trying to insert. Try redesigning the table to fit more characters
I would check the lengths of your column in your table ... looks like you are trying to put in something a wee bit too big and hence the truncation.
Kindness,
Dan
What a tool!!! I got that excited about LINQ I forgot to make sure the table was set up correctly.
Maybe its time to step away from the computer for a while!
Hang on a second, I have run it, the error reported above is sorted but I the name returned is "txtbxFdName" as opposed to the value within that particular textbox.
Just if anyone is looking in at this, the correct code should look like this:
protected void btnSubmitFeedback_Click(object sender, EventArgs e)
{
ORFeedDataClassesDataContext db = new ORFeedDataClassesDataContext();
tblOnlineReportingFeedback newtblonlineReportingFeedback = new tblOnlineReportingFeedback();
newtblonlineReportingFeedback.Name = txtbxFdName.Text;
db.tblOnlineReportingFeedbacks.InsertOnSubmit(newtblonlineReportingFeedback);
db.SubmitChanges();
}
Thanks for a fresh pair of eyes all.
You may want to take a look at not only your column sizes in the actual table, but in the properties of the objects in the .dbml view too, make sure all the datatypes in this pane match up to those in the actual table.
You should also consider putting this code into a using statement as its good practise to minimise memory problems =]
using(ORFeedDataClassesDataContext db = new ORFeedDataClassesDataContext())
{
tblOnlineReportingFeedback newtblonlineReportingFeedback = new tblOnlineReportingFeedback
newtblonlineReportingFeedback.Name = txtbxFdName.Text;
db.tblOnlineReportingFeedbacks.InsertOnSubmit(newtblonlineReportingFeedback);
db.SubmitChanges();
}

Resources