Entity Framework - DbUpdateException to a custom Exception - entity-framework

I am using Entity Framework and when a DbUpdateException is thrown from dbContext.SaveChanges() how do I create a custom exception and throw that instead?
Would I create a condition on each SQL constraint that can be thrown:
if (e.InnerException.InnerException.Message.Contains("UNIQUE KEY"))
{
throw new CustomException("message");
}

EDIT: That approach makes good sense to me. If you know your application/DB is going to have a specific error, and it will help you or your users to have a specific custom exception type that quickly identifies what would otherwise be a somewhat complex or specific scenario, then absolutely yes. It's good practice to use both the exception type and the exception message to make the error as clear as possible. My code below is an even simpler example than what you seem to drilling down into. Rather than letting other code end up with a null reference exception or some other consequence, I beat everything to the punch with throw new DatabaseDataNotFoundException("Cannot find ServerAppConfiguration value for {0}", key);.
Just make your own exception class that inherits from Exception, here's a custom exception I use for exactly that purpose:
public class DatabaseDataNotFoundException : Exception
{
public DatabaseDataNotFoundException() : base() { }
public DatabaseDataNotFoundException(string message) : base(message) { }
public DatabaseDataNotFoundException(string message, params object[] args)
: base(String.Format(CultureInfo.CurrentCulture, message, args)) { }
public DatabaseDataNotFoundException(string message, Exception inner)
: base(message, inner) { }
public DatabaseDataNotFoundException(string message, Exception inner, params object[] args)
: base(String.Format(CultureInfo.CurrentCulture, message, args), inner) { }
protected DatabaseDataNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
Then your code becomes:
if (e.InnerException.InnerException.Message.Contains("UNIQUE KEY"))
{
throw new DatabaseDataNotFoundException("message");
}

Related

Dbcontext disposed exception EF core 3.1

I recently migrated my web application from ASP.net to.NETCore, I have already registered the DBcontext using DI in my startup.cs
services.AddDbContext<MyContextDB>
(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")),
....
public partial class MyContextDB: IdentityDbContext<USER>, IMyContextDB
...
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLazyLoadingProxies();
}
I have also avoided the use of "using" to retrieve data through the context , and I verified that I don't have any call to manually "Dispose()" the context
However I keep getting this exception whenever I reach this part of the application :
public class Licence : ILicence
{
private static IOptionsMonitor<LicenceConfiguration> _appSettings;
private readonly MyContextDB _context;
public Licence(MyContextDB context, IOptionsMonitor<LicenceConfiguration> optionsAccessor)
{
_context = context;
_appSettings = optionsAccessor;
}
public LICENCECODE GetLicenceCode(string key)
{
LICENCECODE LicenceCode = null;
LicenceCode = _context.LICENCECODE.SingleOrDefault(l => l.LICENCEKEY == key);
return LicenceCode;
}
}
"Cannot access a disposed object. A common cause of this error is
disposing a context that was resolved from dependency injection and
then later trying to use the same context instance elsewhere in your
application. This may occur if you are calling Dispose() on the
context, or wrapping the context in a using statement. If you are
using dependency injection, you should let the dependency injection
container take care of disposing context instances.\r\nObject name:
'MyContextDB'."
I've been through every article available on the internet about this exception but yet I can't identify the actual cause of it.
Could you please help me resolve it
The exception is raised specifically when this call is made :
public async Task<LICENCECODE> GetLicenceCode(string key)
{
LICENCECODE LicenceCode = null;
LicenceCode = await _context.LICENCECODE.SingleOrDefaultAsync(l => l.LICENCEKEY == key);
return LicenceCode;
}
PS: I tried to change the method to async because I thought that could be the cause of the issue but unfortunately it's still happening.
the call to that method is from another Model class
validLicence = _licence.CheckLicence(type.Name, ref message, out maxCount);
....
and then inside
CheckLicence
LICENCECODE LicenceCode = GetLicenceCode(LicenceKey).Result;
I guess it depends on how you are using your Licence class, but it might have to do with the lifetime of the request ending before you complete your work in Licence. This could for example happen if your controller action is asynchronous.
Try registering the class with transient lifetime instead:
services.AddTransient<ILicence, Licence>();

handling a specific exception type

I've defined two AfterThrowing advices to handle exceptions with the same pointcut.
#AfterThrowing(pointcut="...", throwing="ex")
public void method1(Exception ex) {}
#AfterThrowing(pointcut="...", throwing="ex")
public void method2(GatewayException ex) {}
Is there a way for me to prevent the generic method1 being executed if the exception is a GatewayException?
Any ideas greatly appreciated
C
It would be the easiest to check the instance of the exception inside the advice body and return early if it's of the more specific exception type:
#AfterThrowing(pointcut="...", throwing="ex")
public void method1(Exception ex) {
if (ex instanceof GatewayException) {
return;
}
// handle the more generic Exception case
}
#AfterThrowing(pointcut="...", throwing="ex")
public void method2(GatewayException ex) {
// handle the more specific GatewayException
}
I know you expected a solution based on some AspectJ language construct, but the thing is, there's no such construct.

Capture exception thrown by Hystrix fallback?

I'm designing a service facade and I have a method signature that looks like this:
public Policy getPolicy(long policyId) throws PolicyNotFoundException
If nothing bad happens then a Policy object (simple POJO) is returned. If the requested policy is not found then a checked exception PolicyNotFoundException is thrown (just as a reference - we follow this article when it comes to best practices on exception handling within an application).
The layer above the service facade layer (in this case a Spring MVC RestController) knows how to handle such a PolicyNotFoundException and return an appropriate payload.
I'm trying to incorporate this into a HystrixCommand by doing something like this:
#HystrixCommand(groupKey = "PolicyService", fallbackMethod = "getPolicySafe", ignoreExceptions = { PolicyNotFoundException.class })
public Policy getPolicy(long policyId) throws PolicyNotFoundException {
LOGGER.info("Getting policy {}", policyId);
// Simulate some error condition for testing purposes
throw new RuntimeException("Something happened!");
}
private Policy getPolicySafe(long policyId, Throwable t) throws PolicyNotFoundException {
LOGGER.warn("Falling back to circuit-breaker for getting policy {}", policyId, t);
throw new PolicyNotFoundException(policyId);
}
Basically I want my circuit breaker to simply behave as if the policy wasn't found by the original lookup. The problem I'm having with this though is the exception I throw from the fallback method is getting lost in translation somewhere. The exception I end up seeing in the layer above is the RuntimeException thrown by the command method and not the exception thrown by the fallback method. Is there a way around this? I don't want to change the contract of my original method either nor do I want the layer above this to know anything other than to have to catch PolicyNotFoundException in the case a policy isn't found. Whatever is needed here should be captured within this service facade layer.
Any and all help would be greatly appreciated. Thanks!
So based on the link #spencergibb gave - I may have found a solution after upgrading to Hystrix 1.5.7. This code works as expected
PolicyRestController.java
#RestController
#RequestMapping("/policies")
public class PoliciesApi {
private static final Logger LOGGER = LoggerFactory.getLogger(PoliciesApi.class);
#Autowired
private PolicyService policyService;
#RequestMapping(value = "/{policyId}", method = RequestMethod.GET, produces = { MediaTypes.POLICY_JSON_VALUE, MediaTypes.POLICY_XML_VALUE })
public Policy getPolicy(#PathVariable long policyId) {
try {
// This just shown for simplicity. There is more to this method (input validation/etc)
return this.policyService.getPolicy(policyId);
}
catch (PolicyNotFoundException ex) {
// NotFoundException is a RuntimeException annotated with #ResponseStatus(HttpStatus.NOT_FOUND)
// So the service returns a 404 to the client
LOGGER.info("Policy {} wasn't found", ex.getPolicyId(), ex);
throw new NotFoundException(String.format("Policy %s was not found", ex.getPolicyId()));
}
}
}
PolicyService.java
public interface PolicyService {
#Cacheable("allPolicies")
public List<Policy> getPolicies();
#Cacheable("policies")
public Policy getPolicy(long policyId) throws PolicyNotFoundException;
}
PolicyServiceImpl.java:
#Service
public class PolicyServiceImpl implements PolicyService {
#HystrixCommand(groupKey = "PolicyService", fallbackMethod = "getPolicySafe", ignoreExceptions = { PolicyNotFoundException.class })
public Policy getPolicy(long policyId) throws PolicyNotFoundException {
LOGGER.info("Getting policy {}", policyId);
// Simulate some error condition for testing purposes
throw new RuntimeException("Something happened!");
}
#HystrixCommand(groupKey = "PolicyService", ignoreExceptions = { PolicyNotFoundException.class }, raiseHystrixExceptions = { HystrixException.RUNTIME_EXCEPTION })
private Policy getPolicySafe(long policyId) throws PolicyNotFoundException {
// Here is we hit our fallback we want to log a warning & simply act as if the policy wasn't found by throwing the same contingency exception as the API does
LOGGER.warn("Falling back to circuit-breaker for getting policy {}", policyId);
throw new PolicyNotFoundException(policyId);
}
}
While your solution might work for you I've noticed some weirdness in your code (I can't check my assumptions so I would like to ask you to check this).
Try to avoid using checked exceptions in your code because it's
awkward to maintain.
Based on your code you will never catch
"PolicyNotFoundException" since you're using raiseHystrixExceptions = { HystrixException.RUNTIME_EXCEPTION } which means that you won't to get your custom exception so that HystrixRuntimeException will be propagated. Try to rewrite your code as follows so it should
simplify the code and maybe fix some of your problems:
#Service
public class PolicyServiceImpl implements PolicyService {
#HystrixCommand(groupKey = "PolicyService", fallbackMethod = "getPolicySafe")
public Policy getPolicy(long policyId) throws PolicyNotFoundException {
LOGGER.info("Getting policy {}", policyId);
throw new PolicyNotFoundException(); // throw real PolicyNotFoundException if policy is absent for the given id
}
#HystrixCommand(groupKey = "PolicyService")
private Policy getPolicySafe(long policyId) throws PolicyNotFoundException {
// Here is we hit our fallback we want to log a warning & simply act as if the policy wasn't found by throwing the same contingency exception as the API does
LOGGER.warn("Falling back to circuit-breaker for getting policy {}", policyId);
throw new PolicyNotFoundException(policyId);
}
}
This is the default behavior of hystrix. "If command has a fallback then only first exception that trigers fallback logic will be propagated to caller"
See the error propagation section here.
I do this:
#Component
public class HystrixClient {
#HystrixCommand(ignoreExceptions = {ClientArgumentException.class})
public POJO getPojo(String id)
throws ClientNoDataFoundException, ClientArgumentException, ClientGeneralException {
//call my service and return POJO
}
}
#Component
public TrueClientUsedForAnotherSerivce {
#Autowired
HystrixClient hystrixClient;
public POJO getPojo(String id)
throws ClientNoDataFoundException, ClientArgumentException, ClientGeneralException, ClientOpenCircuitException {
try {
POJO result = hystrixClient.getCellular(id);
return result;
}
catch(HystrixRuntimeException e) {
LOG.debug("The circuit is open");
throw new ClientOpenCircuitException("Open circuit");
}
}
It only works if #HystrixCommand method is in another class.

How can i catch exceptions in a method that throws them(JAVA)?

I have a class with a method that throws some exceptions and catches them inside itself, but when i call it in my Main class they seem to not being catched.
An example about my problem:
public class Test {
public static void method (int number) throws InvalidNumberException {
try {
if (number == 5) {
throw new InvalidNumberException("Invalid number");
}
} catch (InvalidNumberException inv) {
System.out.println(inv);
}
}
}
public class InvalidNumberException extends Exception {
public InvalidNumberException (String s) {
super(s);
}
}
public class Main {
public static void main(String args[]) {
Test.method(5);
}
}
When i try to compilate the last one i get this error:
Main.java:3: error: unreported exception InvalidNumberException; must be caught or declared to be thrown
Test.method(5);
Is there a way to fix it without catching the exception in the Main class?
Because you're catching the InvalidNumberException inside of method, there's no need for a throws clause, however, the existence of it mandates that calls to it must handle the exception. Thus, the compiler is expecting you to handle the exception in main.
To solve this, simply remove the throws clause modifying method, since you're already handling the exception inside.

Iqueryable throws exception when no results found

From what I have read the code I have should not be throwing an exception when no results are found. I am using a generic repository similar to what is found here:
http://huyrua.wordpress.com/2010/07/13/entity-framework-4-poco-repository-and-specification-pattern/
The code where the exception is thrown:
List<CADDrawing> projectDrawings = repository.Find<CADDrawing>(x => x.ProjectNumber == result.StringResult)
.Where(y => y.Obsolete == false)
.ToList();
Does anyone have experience with this or know what would cause an exception to be thrown when running a query?
Update:
The find code:
public IEnumerable<TEntity> Find<TEntity>(ISpecification<TEntity> criteria) where TEntity : class
{
return criteria.SatisfyingEntitiesFrom(GetQuery<TEntity>()).AsEnumerable();
}
public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class
{
/*
* From CTP4, I could always safely call this to return an IQueryable on DbContext
* then performed any with it without any problem:
*/
// return DbContext.Set<TEntity>();
/*
* but with 4.1 release, when I call GetQuery<TEntity>().AsEnumerable(), there is an exception:
* ... System.ObjectDisposedException : The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
*/
// here is a work around:
// - cast DbContext to IObjectContextAdapter then get ObjectContext from it
// - call CreateQuery<TEntity>(entityName) method on the ObjectContext
// - perform querying on the returning IQueryable, and it works!
var entityName = GetEntityName<TEntity>();
IQueryable<TEntity> ThisQuery = ((IObjectContextAdapter)DbContext).ObjectContext.CreateQuery<TEntity>(entityName);
System.Data.Entity.Core.Objects.ObjectQuery objectQuery = (System.Data.Entity.Core.Objects.ObjectQuery)ThisQuery;
objectQuery.MergeOption = System.Data.Entity.Core.Objects.MergeOption.OverwriteChanges;
return ThisQuery;
}
public IQueryable<TEntity> SatisfyingEntitiesFrom(IQueryable<TEntity> query)
{
return query.Where(Predicate);
}
You're calling ToList() on a null object
Please see the following post for handling of null lists
how do I treat null lists like empty lists in linq?