Execution order problem when using Action - c#

I have the following C# code running in a console app for .NET Core 2.2 on Debian 9 x64:
DbCall(Action action) {
try {
lock(thisLock) {
action();
}
}
catch (Exception ex) {
//exception handling
}
}
private T DbCall<T>(Func<T> func) {
try {
lock(thisLock) {
return func();
}
} catch (Exception ex) {
//exception handling
}
}
public void RemoveClassAEntity(ClassA classAentity) {
DbCall(() => {
DbContext.ClassAEntities.Remove(classAentity);
DbContext.SaveChanges();
});
}
public List<ClassA> GetClassAEntities(Func<ClassA, bool> condition) {
return DbCall(() => {
return DbContext.ClassAEntities
.Where(condition)
.ToList();
});
}
public void RemoveClassAEntitiesWithCondition() {
var entities = GetClassAEntities(e => SatisfiesCondition(e));
entities.Sort();
entities.ForEach(e => RemoveClassAEntity(e));
}
There are multiple methods similar to RemoveClassAEntity, that's why I introduced the DbCall methods, so that I wouldn't need to repeat the lock and exception handling.
The method RemoveClassAEntity is public and can be called from multiple threads. However, it cannot be called from different threads at the same time for the same entity (SatisfiesCondition cannot return true at the same time in different threads)
My problem is that "Value cannot be null. Parameter name: entity" error occurs sometimes, originating from the line "action();". I am fairly certain that RemoveClassAEntity is never called with null argument. I couldn't reproduce the issue with a debugger, only by checking error logs in production environment.
I expected the delegate passed to DbCall to be executed synchronously with the calling method, but I get the impression that the delegate is executed after the calling method exits, that's why the exception occurs. If that could be the case, how do I force it to run before the RemoveClassAEntity method exits?
If that's not the case, what could be?

Related

Returning BadRequest from WebApi Custom method

Using .net core web api here.
I have a endpoint in my api as:
[HttpPost("data")]
public async Task<IActionResult> PostData(List<string> udata)
{
JArray sets = new JArray();
try
{
sets = Helper.GetData(udata);
}
catch (Exception e)
{
return StatusCode(500, e.Message);
}
}
In the above I am calling an custom method in my helper "GetData" which does all the processing and calculations. To make the Api controller clean I moved all the processing to this helper method.
Below is my helper class:
public static class Helper
{
public static BadRequestObjectResult GetMessage(string message)
{
return new BadRequestObjectResult(message);
}
public static JArray GetData(List<string> udata)
{
if(udata == null)
return GetMessage("Data is null");
//do some processing and calclulations here
//return BadRequest if some issue
}
}
If there is some processing issue or some of the data is not as intended or some other issue I want to throw BadRequest. For this I made a custom method to do so "BadRequestObjectResult".
Now my issue is, if there is an issue in GetData it doesnt throws back to my api or exits from my loop. It just continues to next statement.
I know there is some issue by the way I am returning this but not able to find the issue.
Can anyone point out the correct way to handle this?
My suggestion is to throw an exception from your Helper class and and handle it from your PostData method. For example...
You could throw an ArgumentException and explicitly catch that from your API method.
public static class Helper
{
public static JArray GetData(List<string> udata)
{
if(udata == null)
throw new ArgumentException("Data is null");
//do some processing and calclulations here
//throw ArgumentException if there is an issue
}
}
[HttpPost("data")]
public async Task<IActionResult> PostData(List<string> udata)
{
JArray sets = new JArray();
try
{
sets = Helper.GetData(udata);
return Ok(sets);
}
catch (ArgumentException e)
{
return BadRequest(e.Message);
}
}
This way you can only worry about return codes from your controller while your Helper methods are only concerned with the input and aren't returning something specialized for a controller. It's a bit more flexible that way if you ever want to use your Helper class elsewhere.
This will also meet your requirement of stopping processing upon hitting a bad result, so as soon as a bad result is encountered the result set is thrown away and a BadRequest response is issued.

Unit Test for certain types of exceptions

Some background before I get into my question. I am currently working on a project that is migrating from an IBM DB2 to a SQL Server. Not to get into too much detail, but this DB2 linked server sometimes disconnects with the SQL server, which is normal for linked servers. I have this working in code and have a process setup for this to take care of it.
Anyway, I am trying to write a Test Method that throws a DbException (which is the exception that is thrown when the linked server is not connected) to test the process which I wrote when the linked server is disconnected. Is there a way to force throw a certain type of exception so I can test my code?
The try catch block looks something like this:
try
{
//Regular Processing and attempt to update to DB2
}
catch (DbException ex)
{
//Other processing to catch a linked server issue
}
catch (Exception ex)
{
//Even more processing for other exceptions
}
It's the same method as most unit testing, Inject your dependency via an interface, put your real db logic in one class based on that interface, and your
test stuff in another based on that interface.
interface IDBProcessor
{
void Process()
}
class ThrowyClass : IDBProcessor
{
public Exception ThrowThis {get; set;}
public void Process()
{
throw ThrowThis;
}
}
void MyMethod(IDBProcessor processor)
{
try
{
processor.Process()
}
catch (DbException ex)
{
//Other processing to catch a linked server issue
}
catch (Exception ex)
{
//Even more processing for other exceptions
}
}
Then in your unit test, Make a ThrowyClass with the exception you want and pass it in. ( There are mocking frameworks that will save you from making a Test class if you like).
[Test]
void MyThrowTest()
{
var throwy = new ThrowyClass() { ThrowThis = new SomeSpecificException() };
var myClass = new MyClass()
myClass.MyMethod(throwy);
// Assert what you expect
}
You will have to customize things to your specific application. You may wish to inject the IProcessor in the constructor of "MyClass"
You can simply throw it like this way :
throw new DbException();
You should take a look at IDbConnection and try the Moq framework
your code should like the following
var dbConnectionMock = new Mock<IDbConnection>();
dbConnectionMock.Setup(x => x.Open())
.Callback(() => {
throw new SqlException();
}).Verifiable();
https://github.com/Moq/moq4/wiki/Quickstart

Exception not thrown by mocked object

Objective is to unit test a PUBLIC VOID Method.
I have a mocked service, which my class-under-test would call, in a for-each loop with 3 different parameters.
The class-under-test passes some input parameters to "SendRequest" method of the service which executes using those parameters.
I want the mocked service to throw an exception when one of the parameters has a specific value e.g "abc".
I use something like this:
public class ClassUnderTest
{
private IMyService _myservice;
public ClassUnderTest(IMyService myservice)
{
_myservice = myservice;
}
public void MyMethod()
{
//assume I get those 3 values from somewhere, in here.
var list = new List<string>{"abc","aaa","bbb"};
foreach(var item in list)
{
try
{
_myservice.SendRequest(item);
}
catch(Exception ex)
{
//do some logging and continue calling service with next item in list
}
}
}
}
var myService = new Mock<IMyService>();
myService.Setup(x => x.SendRequest("abc")).Throws<Exception>();
myService.Setup(x => x.SendRequest("aaa"));
myService.Setup(x => x.SendRequest("bbb"));
var classUnderTest = new ClassUnderTest(myService.Object);
classUnderTest.MyMethod();
myService.Verify(x =>x.SendRequest(It.IsAny<string>()), Times.Exactly(2));
More Context:
As MyMethod returns void, to test it, I can only rely on the the fact that my dependencies were invoked at different portions of the code in this method. For e.g. if there is a null check for input parameters before service call, the method would return before it invokes the service. If it goes past null check, the dependency service would be invoked. I would be able to trace these in the code coverage results( and in debug mode).
When I run the test, it fails because its invoking the service thrice but I expect the invocation to happen twice(now may be I am wrong and may be that although it is supposed to throw exception the invocation attempt is still counted by Verify call and hence I get 3 runs).
Whatever be the case, on debug I see that the service never throws exception. I have a try-catch in the for-each-loop where I want to do some logging and continue calling the service again with the next value. But I never get to get inside the Catch block.
What am I doing wrong?
Option 1: Specific Exception
My 1st suggestion would throw a more specific exception so you can be more sure.
Option 2: Inject an ILogger service
Refactor out the logging into an ILogger and inject that in. Then pass a mock of that in and assert against it.
Option 3: Extract and Override
If you must check catch block was hit you can use extract and override:
public class ClassUnderTest
{
private IMyService _myservice;
public ClassUnderTest(IMyService myservice)
{
_myservice = myservice;
}
public void MyMethod()
{
//assume I get those 3 values from somewhere, in here.
var list = new List<string>{"abc","aaa","bbb"};
foreach(var item in list)
{
try
{
_myservice.SendRequest(item);
}
catch(Exception ex)
{
LogError(ex);
}
}
}
protected virtual LogException(Exception ex)
{
//do logging
}
}
public class TestableClassUnderTest : ClassUnderTest
{
public bool LoggingWasCalled { get; set; }
protected virtual LogException(Exception ex)
{
LoggingWasCalled = true;
}
}
Then you could sheck something like this:
var testableSut = new TestableClassUnderTest ();
testableSut.MyMethod("abc");
Assert.True(testableSut.LoggingWasCalled);
I walk through it in more detail here: http://devonburriss.me/testing-the-untestable/

Refactoring exception handling

In one of my classes I have a call to a repository which has some error handling on it. I would like to refactor the error handling code because it is quite repetitive and the only thing that really changes is the message.
My code currently looks something like this:
public IList<User> GetUser()
{
try
{
return _repository.GetUsers();
}
catch (WebException ex)
{
ErrorMessages.Add("...");
_logger.ErrorException("...", ex);
}
catch (SoapException ex)
{
ErrorMessages.Add("...");
_logger.ErrorException("...", ex);
}
... etc
}
I could replace those lines in my catch block with a call to another method which takes an error message value and a logger message value. However I suppose I could also do this using an Action<> parameter but I am very inexperienced at using Func<> and Action<> and don't really see what benefit I would have using one of those over a method.
My question is really what is the best way to refactor this code and why does one way benefit over the other (as per my example above).
Thanks for any help.
You can use lambdas to help with this.
If you define your general-purpose error handler to accept a parameter of type Action then you can call that action in the error handler.
You don't need to worry about return values because the lambda you write at the point of call can take care of that.
For example, your general handler could look like this:
public void AttemptAction(Action action)
{
try
{
action();
}
catch (WebException ex)
{
ErrorMessages.Add("...");
_logger.ErrorException("...", ex);
// Rethrow?
}
catch (SoapException ex)
{
ErrorMessages.Add("...");
_logger.ErrorException("...", ex);
// Rethrow?
}
}
And then you could use it like this:
public IList<User> GetUser()
{
IList<User> result = null;
AttemptAction(() => result = _repository.GetUsers());
return result;
}
Assuming the exception types are always the same but the messages are different, you can do this:
static public T Try<T>(string webMessage, string soapMessage, Func<T> func)
{
try
{
return func();
}
catch (WebException ex)
{
ErrorMessages.Add(webMessage);
_logger.ErrorException(webMessage, ex);
}
catch (SoapException ex)
{
ErrorMessages.Add(soapMessage);
_logger.ErrorException(soapMessage, ex);
}
}
This Try-method will use a delegate of type Func<T> to call a function and return its value. The function will be inside the same try-catch block. The messages are provides via parameters. Now, somewhere else in your code, you could call this like:
var users = Try("My web message.", "My soap message.", () => _repository.GetUsers());
Or, in your case even shorter (when not using parameters):
var users = Try("My web message.", "My soap message.", _repository.GetUsers);
Of course you can modify and arrange the parameters of Try to your own liking.
In case you are mixing method with and without return types, it is better not to use the Func but the Action. This will be able to comply to all situations:
static public void Try(string webMessage, string soapMessage, Action action)
{
try
{
action();
}
catch (WebException ex)
{
ErrorMessages.Add(webMessage);
_logger.ErrorException(webMessage, ex);
}
catch (SoapException ex)
{
ErrorMessages.Add(soapMessage);
_logger.ErrorException(soapMessage, ex);
}
}
But this solution makes the code a tiny bit more difficult to read / maintain:
IList<User> users;
Try("My web message.", "My soap message.", () => users = _repository.GetUsers());
You can use Aspect-Oriented Programming http://en.wikipedia.org/wiki/Aspect-oriented_programming.
The idea to place all repetitive code to special classes that are called aspect.
Your code will look like in PostSharp
[ExceptionLogger]
public IList<User> GetUser()
{
return _repository.GetUsers();
}
public class ExceptionLogger: OnMethodBoundaryAspect
{
//getting _logger and ErrorMessages
public override void OnException(MethodExecutionArgs args)
{
ErrorMessages.Add("...");
_logger.ErrorException("...", ex);
}
}
For c#, you ccan use PostSharp, Castle.Windsor or Unity frameworks.

What are some implementations of Exception filtering in the Circuit Breaker pattern?

The Circuit Breaker pattern, from the book Release It!, protects a remote service from requests while it is failing (or recovering) and helps the client manage repeated remote service failure. I like Davy Brion’s stateful circuit breaker and Ayende’s lazy timeout fix is very clean.
However, I have not seen a lot of implementations of filtering which exceptions will cause an increase in the failure count of a circuit breaker.
Don't worry about showing locking, unless your implementation is particularly dependent on clever locking. FYI, Phil Haack appears to have the latest version of TimedLock, used in Davy Brion's articles.
Filter by Predicate
A predicate can provide extended criteria and filtering logic.
public void AttemptCall(Action action, Predicate<Exception> match)
{
try
{
action();
}
catch(Exception e)
{
if(match(e))
state.ActUponException(e);
throw;
}
}
For example, you may want to increase the circuit breaker only on a WebException caused by a timeout.
circuitBreaker.AttemptCall(() => service.DoWork(), e =>
{
WebException local = e as WebException;
if(local == null)
return false;
return local.Status == WebExceptionStatus.Timeout;
});
Filter which Types will increase the count
Your first thought may be to construct a generic method call with a generic try... catch block. However, the below will not work due to a .NET bug, please see these questions for more information.
public void AttemptCall<TException>(Action action)
where TException : Exception
{
try
{
action();
}
catch(TException e)
{
state.ActUponExcpetion(e);
throw;
}
}
You need to catch all exceptions and investigate the type.
public void AttemptCall<TException>(Action action)
where TException : Exception
{
try
{
action();
}
catch(TException e)
{
if(e is TException)
state.ActUponExcpetion(e);
throw;
}
}
Filter which Types will not increase the count
Tim Ross wrote about this.
private readonly List<Exception> ignored = new List<Exception>();
public void Ignore<TException>()
where TException : Exception
{
Type type = typeof(TException);
if(ignored.Contains(type))
return;
ignored.Add(type);
}
public void AttemptCall(Action action)
{
try
{
action();
}
catch(Exception e)
{
if(!ignore.Contains(e.GetType()))
state.ActUponException(e);
throw;
}
}

Categories