LINQ to SQL DuplicateKeyException problem - linq-to-sql

I am using LINQ2SQL and I have a table called Customers with three columns
CustmerID, CustomerCode, CustomerName
CustmerID is Primery Key(and Identity=yes) and CustomerCode is just UniqueKey.
When I am updating this table using LINQ to SQL with duplicate customercode, I expect to see DuplicateKeyException but it is going into the general exception block instead of DuplicateKeyException block. Any ideas?
This is the code
public void Update(Customer cust)
{
using (LINQDemoDataContext db = new LINQDemoDataContext())
{
Customers entity = CustomerMapper.ToEntity(new Customers(), cust);
try
{
db.Customers.Attach(entity, true);
db.SubmitChanges();
}
//Concurrency Exception
catch (ChangeConflictException)
{
throw new ChangeConflictException("A concurrency error occurred!");
}
//duplicate record
catch (DuplicateKeyException)
{
throw new DuplicateKeyException(entity.CustmerCode);
}
//everything else
catch (Exception ex)
{
throw ex;
}
}
}
I am using VisualWebDeveloperExpress 2008 and SQL Express 2005.
Thanks & Regards,
Supremestar

If memory serves, and I may be wrong here, the DuplicateKeyException only fires for the primary key of the table.

I ran into this same problem, where the duplicate key objects were being retained in-memory even though they were not getting inserted into the database. I came up with the following work around:
MyDataContext _myDataContext = new MyDataContext(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString);
public void AddObject(object myObject)
{
try
{
_myDataContext.Objects.InsertOnSubmit(myObject);
_myDataContext.SubmitChanges();
}
catch (System.Data.Linq.DuplicateKeyException ex)
{
_myDataContext = new MyDataContext(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString);
throw ex;
You can then catch and handle (or ignore) the thrown DuplicateKeyException in the caller.
Another work around (albeit inefficient and memory hogging) is to create a new data context inside the AddObject method instead of using the shared data context instantiated as a class member.

I had the problem when adding an entity i got from a different DataContext.
(I bound the FooDb-Property of a BarDb-Entity to the SelectedValue from a DropDownList, which had a Table from a short-living DataContext as DataSource)
Let's look at the Linq2Sql internal Attach(entity):
private void attach_FooDb(FooDb entity){
this.SendPropertyChanging();
entity.BarDb = this;
}
And the BarDb Property set:
set{
BarDb previousValue = this._BarDb.Entity;
if (((previousValue != value) || (this._BarDb.HasLoadedOrAssignedValue == false))){
this.SendPropertyChanging();
if ((previousValue != null)){
this._BarDb.Entity = null;
previousValue.FooDb.Remove(this);
}
this._BarDb.Entity = value;
if ((value != null)){
value.FooDb.Add(this);
this._FK_Bar = value.ID;
}else{
this._FK_Bar = default(System.Guid);
}
this.SendPropertyChanged("BarDb");
}
}
So when attaching to a FooDb, the corresponding DataContext will recognize the BarDb Entity as newly created and added, even though it already existed in the Database.
You can solve it by:
only using a single DataContext or
creating a BarDb_safe Property in the submitting DataContext, which will first request the "equal" entity from the database, applies all properties and then attaches it the usual way.

Related

MSDTC on server 'servername' is unavailable with linq to sql

I am using Transactionscope with linqtosql. I have the following code:
public bool Save(int Id, List<Student> students, List<Subject> subjects)
{
var isDataSaved = false;
using (TransactionScope scope = new TransactionScope())
{
try
{
// Save the students
SaveStudents(students);
// Save the subjects
SaveSubjects(subjects);
scope.Complete();
isDataSaved = true;
}
catch (Exception ex)
{
throw ex;
}
return isDataSaved;
}
}
In both the methods I am using the two tables : Students, Subjects present in the same database. The datacontext object dependency is setup using the constructor as mentioned in the below class:
public class StudentsRepository:IStudentsRepository
{
public StudentsRepository()
{
_dataContext = new SchoollDetailsDataContext(connectionString);
}
}
The same datacontext object is used in both the methods SaveStudents and SaveSubjects.
I am getting an exception : MSDTC on server 'servername' is unavailable.
As per my initial analysis this kind of error will occur where a database operation will be in my local database and another will be in a remote database.
Can anyone help me to know is there anything I am missing here?
You need to turn the MSDTC service on.
Start-->Control Panel --> Administrative Tools --> services.
Find the service Distributed Transaction Coordinator and start it.
By default its startup property is set to Manual so its switched off.

Spring MVC Exceptions

I have the following code in the Controller class and for some reason although i have exception handling implemented as well as a try.....catch block i am still unable to capture my exceptions.
I am just executing a test, in the DAO class i change the sql string that inserts into the database to leave out a column just so the DAO will fail. The DAO class fails and the error is written to the logs however even thou the officerManager.RegisterOfficer(officer) was not successful the code goes on to return the model.addAttribute("results","Record Was Saved").
This is not accurate and i would like for the controller to throw an error. Under is the code.
Controller
#RequestMapping(value="officer_registration.htm", method=RequestMethod.POST)
public ModelAndView handleRequest(#Valid #ModelAttribute Officers officer,BindingResult result,ModelMap m,Model model,HttpServletRequest request,HttpServletResponse response)throws Exception{
try{
if(result.hasErrors()){
model.addAttribute("division", myDivision);
model.addAttribute("position", myPosition);
model.addAttribute("gender", myGender);
return new ModelAndView("officer_registration");
}else{
//check the request if its an update or an insert
String user_request = request.getParameter("user_request");
logger.info("The Users Request Was " + user_request);
if (user_request.equals("Save")){
officerManager.RegisterOfficer(officer);
model.addAttribute("results","Record Was Saved");
}else{
officerManager.UpdateOfficer(officer);
model.addAttribute("results","Record Was Updated");
}
model.addAttribute("division", myDivision);
model.addAttribute("position", myPosition);
model.addAttribute("gender", myGender);
return new ModelAndView("officer_registration");
}
}catch(Exception e ){
model.addAttribute("division", myDivision);
model.addAttribute("position", myPosition);
model.addAttribute("gender", myGender);
model.addAttribute("results","Error: Unable to Save Record!");
return new ModelAndView("officer_registration");
}
}
DAO
public void saveOfficer(Officers officer) {
logger.info("In saveOfficer");
//SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
try{
int count = getJdbcTemplate().update("INSERT INTO crimetrack.tblofficers (userName,password, fName, lName, oName, divisionNo, positionId, emailAdd, startDate, endDate, genderId,phoneNo, dob,badgeNo) "+
"VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
, new Object[]{officer.getUserName(),StringSecurity.EncryptString(officer.getPassword()),officer.getfName(),
officer.getlName(),officer.getoName(),officer.getDivisionNo(),officer.getPositionId(),
officer.getEmailAdd(),officer.getStartDate(),officer.getEndDate(),officer.getGenderId(),
officer.getPhoneNo(),officer.getDob(),officer.getBadgeNo()});
logger.info(count +" Rows affected in tblOfficers");
}catch(Exception e){
logger.error("Could not save officer ", e);
}
}
You're not allowing the error to bubble up back to the controller.
You're handling the exception within the DAO, in which case the method exits normally, and no exception is caught within the Controller.
Either don't surround the DAO with a try catch and let the exception bubble back to the controller (recommended), or catch and rethrow the exception (if you follow this route, throw as a RuntimeException, either create your own, or rethrow as a RuntimeException, that way you won't have to catch all the way through the call stack.)
Also, it's generally frowned upon to catch generic exception as it is tougher to nail down exactly what caused it unless you look within the logs. Knowing which exceptions to handle ahead of time is usually better practice.

hibernate: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException

When saving an object to database using hibernate, it sometimes fails because of certain fields in the object exceeding the maximum varchar length defined in the database.
Therefore I am using the following approach:
Attempt to save
If getting an DataException, I then truncate the fields in the object to the max length specified in the db definition, then try to save again.
However, in the second save after truncation, I'm getting the following exception:
hibernate: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails
Here's the relevant code, do you notice anything wrong with it?
public static void saveLenientObject(Object obj){
try {
save2(rec);
} catch (org.hibernate.exception.DataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
saveLenientObject(rec, e);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void saveLenientObject(Object rec, DataException e) {
Util.truncateObject(rec);
System.out.println("after truncation ");
save2(rec);
}
public static void save2(Object obj) throws Exception{
try{
beginTransaction();
getSession().save(obj);
commitTransaction();
}catch(Exception e){
e.printStackTrace();
rollbackTransaction();
//closeSession();
throw e;
}finally{
closeSession();
}
}
All Hibernate exceptions (except for NonUniqueResultException) are irrecoverable. If you get an exception you should close the session and open another one for further operations.
See also:
13.2.3. Exception handling
The hibernate documentaiton is quite clear that once an exception is thrown the session will be left in an inconsistent state so is not safe to use for further operations. I suspect that what you're getting here is that the session is left half saving your first attempt so bad things happen.
Fundamentally you should not rely on database errors to check the length of your fields, instead you should pre-validate this in java code. If you know the lengths enough to truncate, then I suggest you simply call your trucate util every time.
Alternatively use Hibernate Validator to declaratively validate the objects before saving.

Handling database connection exceptions with Linq to SQL and Rx

I am trying learn how to best use the Reactive Extensions library and have set up simple test WPF application to view a logging database table. In a ViewModel class I am populating an ObservableCollection with the first 100 log entries from a Linq to Sql DataContext and I'm trying to use Rx to keep the UI responsive.
The following snippet works unless the database is unavailable at which point the app throws an exception and crashes. Where would be the best place to handle database connection exceptions and why are they not handled by the OnError method of the Observer?
ObservableCollection<LogEntry> _logEntries = new ObservableCollection<LogEntry>();
DataContext dataContext = new DataContext( "connection string" );
(from e in dataContext.LogEntries
select e).Take( 100 ).ToObservable()
.SubscribeOn( Scheduler.ThreadPool )
.ObserveOnDispatcher()
.Subscribe( _logEntries.Add, ex => System.Diagnostics.Debug.WriteLine( ex.ToString() ) );
Try this instead of ToObservable:
public static IObservable<T> SafeToObservable(this IEnumerable<T> This)
{
return Observable.Create(subj => {
try {
foreach(var v in This) {
subj.OnNext(v);
}
subj.OnCompleted();
} catch (Exception ex) {
subj.OnError(ex);
}
return Disposable.Empty;
});
}
In general though, this isn't a great use of Rx since the data source isn't very easy to Rx'ify - in fact, the code will execute most of the work on the UI thread, send it out to random worker threads, then send it back (i.e. completely wasted work). Task + Dispatcher.BeginInvoke might suit you better here.

Convert.ChangeType() on EntityObject

I'm working on MySQL using .Net Connector 6.3.6 and created Entity models on VS 2010. I'm planning to write a generic method that would add an EntityObject to its corresponding table. Here is how it looks:
public void AddToTable(ObjectContext dataContext, string tableName, EntityObject tableObj)
{
try
{
Type type = dataContext.GetType();
string methodName = "AddTo" + tableName;
MethodInfo methodInfo = type.GetMethod(methodName);
PropertyInfo propInfo = dataContext.GetType().GetProperty(tableName);
Object[] parameters = new Object[] { Convert.ChangeType(tableObj, propInfo.PropertyType) };
methodInfo.Invoke(dataContext, parameters);
}
catch (Exception e)
{
edit://gonna handle it appropriately here!
}
}
ObjectContext will be the actual ObjectContext class.
But I'm getting exception saying "object must implement IConvertible" when I use Covert.ChangeType() on an EntityObject.
How to overcome this problem?
Edit: FYI, my main intention is to make write a method which is as generic as possible so that no casting to a particular table type would be required.
Thanks,
Alerter
You're reinventing the wheel.
public void AddToTable<TEntity>(ObjectContext dataContext, TEntity tableObj)
{
dataContext.CreateObjectSet<TEntity>().AddObject(tableObj);
}
And please don't eat exceptions.
Followed the following generalized repository pattern:
[link]http://www.codeproject.com/Articles/37155/Implementing-Repository-Pattern-With-Entity-Framew[link] It is very intuitive and fits my requirement :)