In my sql stored procedure, i do some insertion and updating which in some scenarios throws Primary Key or unique key violation.
When I try to execute this procedure from ADO.net, .net application also throws that exception and let me know that something wrong had happen.
But when I try to execute this procedure from EF, it just executes. Neither it show anything nor update anything.
How should I handle or notify user that something wrong had happen?
Ado.Net code is
SqlConnection sqlConnection = new SqlConnection(#"data source=database01; database=test; user id=test; password=test;");
SqlCommand cmd = new SqlCommand("[uspUpdateTest]", sqlConnection);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("RunID", RunID);
cmd.Parameters.AddWithValue("RunCode", RunCode);
sqlConnection.Open();
var str = cmd.ExecuteNonQuery();
Entity Framework Code is
TestEntities context = new TestEntities();
var str=context.UpdateRun(RunID, RunCode);
I am very much sure, you must set some return type(dummy) in your function import. It makes sense most of the time, because if you don't do so, your method name does not appear in intellisense and you will no be able to access it using context.MethodName.
My suggestion for you is, remove the return type of your Function Import and set it to none. Execute your method using ExecuteFunction method of context.
Context.ExecuteFunction(FunctionName,Parameters). It'll definitely throws the exception.
First of all, make sure you're throwing an Exception in your stored procedure which we can catch in our C# code. See - http://social.msdn.microsoft.com/forums/en-US/adodotnetdataproviders/thread/efea444e-6fca-4e29-b100-6f0c5ff64e59 - quote:
If you want RAISERROR to throw a SqlException, you need to set its
severity above 10. Errors with a severity of 10 and below are
informational, and thus don't throw exceptions.
I'll also show you the following code. I have been using this in my MVC controllers when getting data from my service layer using Entity Framework:
try
{
try
{
//Entity Framework/Data operations that could throw the data exception
//...
} catch (DataException dex) //see http://msdn.microsoft.com/en-us/library/system.data.dataexception.aspx
{
//Specifically handle the DataException
//...
}
}
catch (Exception e)
{
//do something (logging?) for the generic exception
throw e;
}
You can put a breakpoint on the last catch if the first catch doesn't trigger to see Exception-type/inner-exception of 'e' and go from there. It is useful to put a breakpoint on the generic exception, as it let's me know when I haven't handled something.
We can use the following way for sql raised error exception from entity framework:
Let's say, we have DBContext. So that
var connection= (SqlConnection)db.Database.Connection;
if (connection != null && connection.State == ConnectionState.Closed)
{
connection.Open();
}
SqlCommand com = new SqlCommand("spname", connection);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.Add(new SqlParameter("#parameter", parameter));
try
{
com.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex.message;
} `
The question here gives quite a nice summary of catching and handling the exceptions gracefully. You have several options after that for rolling back etc.
Related
Why does EF error interface is so unhelpful ? How can one find the exact cause for a DbContext.SaveChanges exception, when the errors tell almost nothing about the parameters involved in the exception?
One serious shortcoming of EF in my opinion is detecting what is causing a given exception after issuing SaveChanges().
It has been long since I have been struggling with EF error interface. I once helped myself a bit by writing a method that flattens all the db context validation errors providing straightforward messages with Table, Column and error message for each error. Otherwise one has to dig deep in the error structures dbContext returns... I wonder why they did this this way!
In any case, to my problem:
I perform several add operations in several entities in my dbContext, and in the end issue one single SaveChanges().
Now, I GetValidationErrors() returns 0 errors, so no validation issues.
But SaveChanges throws the following exception:
The conversion of a datetime2 data type to a datetime data type
resulted in an out-of-range value. The statement has been terminated.
How does DbContext points out the specific cause of the error in any way when what he passes over to you is a nested labyrinth of inner objects that looks like:
?!
If it's the DbEntityValidationException you can just override the SaveChanges method and grab the error and re throw it with the errors parsed out something like this:
public partial class MyEntities
{
public override int SaveChanges()
{
try
{
return base.SaveChanges();
}
catch (DbEntityValidationException ex)
{
var errorMessages = ex.EntityValidationErrors
.SelectMany(x => x.ValidationErrors)
.Select(x => x.ErrorMessage);
var fullErrorMessage = string.Join("\n\r", errorMessages);
var exceptionMessage = string.Concat(ex.Message, "The validation errors are: ", fullErrorMessage);
throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
}
}
}
I started using Entity Framework 4.3.1 with code first approach.
I want to avoid application crash when database server is shut down or unavailable catching specific exceptions.
Imagine this short sample piece of code:
using (var db = new MyContext())
{
var people = new People();
db.People.AddObject(people);
db.SaveChanges();
}
When server is shut down, I receive ProviderIncompatibleException.
If I try to modify code catching ProviderIncompatibleException like this
using (var db = new MyContext())
{
try
{
var people = new People();
db.People.AddObject(people);
db.SaveChanges();
}
catch(ProviderIncopatibleException)
{
}
}
I receive compiler error "The type caught or thrown must be derived from System.Exception".
How can I catch most specific Exception using Entity framework?
Thank you for help.
There's a typo in the class name - you missed out an 'm' in Incompatible.
Try again with ProviderIncompatibleException
I have created a sample application in Silverlight with RIA services. I am using entity framework for CRUD operation but it does not work for INSERT Operation with following Exception, "Submit operation failed validation. Please inspect Entity.ValidationErrors for each entity in EntitiesInError for more information." I have not apply any validation but don't know how the error occurs.
I have tested that when I create an object of DB entity and assign values to it and then save by calling object.SaveChages(), it works fine. But its default method does not work. Any help is appreciated.
Thanks
The SubmitOperation callback has an EntitiesInError property which you can use to iterate thru the entities. That's the way of getting the "real" error.
Here's the method I have to show the user what went wrong...
public static bool WasSubmittedOK(SubmitOperation so, string errorMessageHeader, out string errorMessage)
{
errorMessage = string.Empty;
if (!so.HasError)
return true;
so.MarkErrorAsHandled();
errorMessage = "An unknown error has occurred";
if (so.EntitiesInError.Count() > 0)
{
StringBuilder builder = new StringBuilder();
builder.AppendFormat("{0}\r\n", errorMessageHeader);
foreach (Entity item in so.EntitiesInError)
{
#if DEBUG
builder.AppendFormat("\r\nFor {0}", item.GetType());
#endif
foreach (ValidationResult error in item.ValidationErrors)
{
builder.AppendFormat("\r\n- {0}", error.ErrorMessage);
Debug.WriteLine(string.Format("Error in {0}:'{1}'", string.Join(",", error.MemberNames.ToArray()), error.ErrorMessage));
}
}
errorMessage = builder.ToString();
}
else if (so.Error != null) { errorMessage = so.Error.Message; }
return false;
}
Are you able to drill into the validation errors? I actually have an article about this coming in December MSDN Magazine Data Points but I bet you don't want to wait, right? :)
Even if you haven't applied any specific validations, there are things like foreign key contsraints that EF will still check. If you can see what the error is that will be ultimately useful in solving your problem. Debug into the exception. See if there is a DbEntityValidationException available...maybe it's in an innerexceptoin. DbEntityValidationException will have one or more EntityValidationErrors. Each of those contains a list of all of the errors found for one instance. That means expanding the EntityValidationErrors items one at a time and looking at the ValidationError items contained within.
I am using EclipseLink in my web application, and I am having a hard time gracefully catching and handling Exceptions it generates. I see from this thread what seems to be a similar problem, but I don't see how to work around or fix it.
My code looks like this:
public void persist(Category category) {
try {
utx.begin();
em.persist(category);
utx.commit();
} catch (RollbackException ex) {
// Log something
} catch (HeuristicMixedException ex) {
// Log something
} catch (HeuristicRollbackException ex) {
// Log something
} catch (SecurityException ex) {
// Log something
} catch (IllegalStateException ex) {
// Log something
} catch (NotSupportedException ex) {
// Log something
} catch (SystemException ex) {
// Log something
}
}
When persist() is called with an entity that violates a uniqueness constraint, I get an explosion of exceptions that are caught and logged by the container.
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504):
org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The statement
was aborted because it would have caused a duplicate key value in a unique or
primary key constraint or unique index identified by 'SQL110911125638570'
defined on 'CATEGORY'.
Error Code: -1
(etc)
I have tried the following:
try {
cc.persist(newCategory);
} catch (PersistenceException eee) {
// Never gets here
System.out.println("MaintCategory.doNewCateogry(): caught: " + eee);
} catch (DatabaseException dbe) {
// Never gets here neither
System.out.println("MaintCategory.doNewCateogry(): caught: " + dbe);
}
I realize that using DataBaseException is not portable, but I need to start somewhere. The exceptions never get caught. Any suggestions?
It looks like I won't get any more activity on this question, so I will post my work-around and leave it at that. A number of web searches haven't found much of anything that is helpful. I would have thought this is a textbook case but none of the tutorials I have found covers it.
As it turns out in this condition with EclipseLink, the Exception you can catch when the SQL constraint is violated is the RollBackException that is the result of the em.commit() call. So I have modified my persist method like this:
public void persist(Category category) throws EntityExistsException {
try {
utx.begin();
em.persist(category);
utx.commit();
} catch (RollbackException ex) {
Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
throw new EntityExistsException(ex);
} catch (HeuristicMixedException ex) {
Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
} catch (HeuristicRollbackException ex) {
Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalStateException ex) {
Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
} catch (NotSupportedException ex) {
Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
} catch (SystemException ex) {
Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
}
}
So the caller catches the EntityExistsException and takes the appropriate action. The log still fills up with the internal exceptions but that can be shut off later.
I realize that this is a bit of an abuse of the intent of the EntityExistsException that is normally only used when an entity ID field is re-used, but for the purposes of the user application it doesn't matter.
If anyone has a better approach please post a new answer or comment.
Edit your persistence.xml adding the following property:
property name="eclipselink.exception-handler" value="your.own.package.path.YourOwnExceptionHandler"
Now create the class YourOwnExceptionHandler (on the correct package). It requires to implement org.eclipse.persistence.exceptions.ExceptionHandler.
Create a non argument constructor and the required method handleException(...).
Inside this method, you can catch the exceptions!
EclipseLink should only be throwing either a PersitenceException or a RollbackException depending on the environment and the order of operations you are calling on the EntityManager.
What is your logging level? It is likely that you are seeing these exceptions logged by EclipseLink but only thrown as causes of the RollbackException.
You can turn off exception logging with the PU property but for diagnostic purposes it is generally better to allow EclipseLink to log the exceptions.
2019-12-18
As its a very well viewed question and I just had a very similar issue with EclipseLink, in a Maven multi module web application running on Weblogic 12c server and using JTA, I am going to post my solution here, hoping to save a couple hours for someone.
In the persistence.xml we are having:
< property name="eclipselink.persistence-context.flush-mode"
value="commit" />
The REST resource class was marked with #Transactional, meaning that the transaction starts at the point when the request has been received by the related method of the resource class, and it ends when this method returns.
JTA used for managing the transactions.
Now, JTA commit time happens to occur AFTER the resource class's method returns (with a response to the REST client).
Which subsequently means that:
Even though you had a very proper setup to catch the Exception, you
cannot, as exceptions like SQLIntegrityConstraintViolationException
occur only AFTER your INSERT/UPDATE/DELETE query
--that has been sitting all this time in your JPA provider cache--,
now finally sent to the database.
Which happens just after the resource class's method returns, and at that point, all the exceptions has been skipped already.
Since no query sent == no exception occured at the time when the execution ran through the try{...}catch(Exception e){...} lines, you were not able to catch it,
but at the end, you will see the exception in the server's log.
Solution:
I had to manually call flush() on EntityManager to force flush and the exception to occur at the proper time and line (basically in the try block) to be able to catch it, handle it, and allow my REST method to return with my intended response.
The final caught exception in the log (I have masked some not related info):
javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - x.x.x.v00000000-0000000): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (XXXXX.UNIQUE_KEY_NAME) violated
Related pseudo code:
try {
repository.update(entity);
repository.getEntityManager().flush();
} catch (Exception e ) {
log.info(e.toString());
...
}
I'm using Spring Boot 1.1.9 + EclipseLink 2.5.2. This is the only way I can catch ConstraintViolationException. Note that my handleError(ConstraintViolationException) is a very simple implementation which just returns the first violation it finds.
Note that this code was also required when I switched to Hibernate 4.3.7 and Hibernate Validator 5.1.3.
It seems that adding PersistenceExceptionTranslationPostProcessor exceptionTranslation() to my persistence JavaConfig class also has no effect.
import javax.persistence.RollbackException;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
#ControllerAdvice
class GlobalExceptionHandler
{
#ExceptionHandler(TransactionSystemException.class)
public ResponseEntity<Object> handleError(final TransactionSystemException tse)
{
if(tse.getCause() != null && tse.getCause() instanceof RollbackException)
{
final RollbackException re = (RollbackException) tse.getCause();
if(re.getCause() != null && re.getCause() instanceof ConstraintViolationException)
{
return handleError((ConstraintViolationException) re.getCause());
}
}
throw tse;
}
#ExceptionHandler(ConstraintViolationException.class)
#SuppressWarnings("unused")
public ResponseEntity<Object> handleError(final ConstraintViolationException cve)
{
for(final ConstraintViolation<?> v : cve.getConstraintViolations())
{
return new ResponseEntity<Object>(new Object()
{
public String getErrorCode()
{
return "VALIDATION_ERROR";
}
public String getMessage()
{
return v.getMessage();
}
}, HttpStatus.BAD_REQUEST);
}
throw cve;
}
}
I use this.
if (!ejbGuardia.findByPkCompuestaSiExiste(bean.getSipreTmpGuardiaPK())) {
ejbGuardia.persist(bean);
showMessage(ConstantesUtil.MENSAJE_RESPUESTA_CORRECTA, SEVERITY_INFO);
} else {
showMessage("Excel : El registro ya existe. (" + bean.toString() + ") ", SEVERITY_ERROR);
}
and my function from above:
public boolean findByPkCompuestaSiExiste(Object clasePkHija) throws ClassNotFoundException {
if (null != em.find(this.clazz, clasePkHija)) {
return true;
}
return false;
}
With that I dont need to program a validation for each Persist, its common in the my DAO Classes.
I am executing a series of Caliburn.Micro IResults by yield returning them from an IEnumerable method called by a Caliburn.Micro action message. The first IResult calls a WCF RIA service Invoke operation. Sometimes this operation fails and throws an exception. This is handled in the IResult where the InvokeOperation object is checked for error, I mark the error as handled and set the IResult's error message field to the error so I can recover it from the client.
The problem is that for some reason this interrupts the co-routine executing. I can't think of any good reason why, but when I'm in debug mode VS skips to the server code and bring up the unhandled exception helper telling me there was an uncaught exception (duh), and the co-routine never continues executing the other members of the IEnumerable.
Here is some of the code.
Called from the Action Message:
public IEnumerable<IResult> Submit()
{
var register = new RegisterUserResult(Username, Password, Email, _userModel);
yield return register;
if (register.Success)
{
if (RegisterAsTrainer)
yield return new ApplyRoleToUserResult(Username, "Trainer", _userModel);
yield return new NavigateResult(new Uri("/MainPageViewModel", UriKind.Relative));
}
else ErrorMessage = register.ErrorMessage;
}
The code in the DomainService (which sometimes throws an exception)
[Invoke]
public void CreateUser(string username, string password, string email)
{
Membership.CreateUser(username, password, email);
}
...where Membership is the ASP.NET class, which I am using for membership management.
The IResult that calls the above service (some details elided for clarity):
public void Execute(ActionExecutionContext context)
{
ErrorMessage = null;
Success = false;
var ctx = new TrainingContext();
ctx.CreateUser(_username, _password, _email, CreateUserCallback, null);
}
private void CreateUserCallback(InvokeOperation invokeOp)
{
if (invokeOp.HasError)
invokeOp.MarkErrorAsHandled();
Completed(this, new ResultCompletionEventArgs
{
Error = invokeOp.Error,WasCancelled = invokeOp.IsCanceled
});
}
The IResult.Completed DOES fire, but the rest of the method never executes. I'm literally tearing my hair out with this, please please help me.
Ugh I figured this out, stupid me. I was setting the IResult Error field, thinking I'd need to use that information later. I didn't know that having a non-null Error field would cause co-routine execution to halt (I thought only the Canceled field would do that). I'll leave this here in case anyone else runs into this issue.