My original problem was that I was experiencing deadlocks often when updating my SQL database. Through a little bit of research, I found that I'm able to define a custom DbConfiguration and with it a DbExecutionStrategy which instructs Entity Framework to automatically retry after getting certain errors after x milliseconds and y number of times. Great!
So, following the guide at https://msdn.microsoft.com/en-us/data/jj680699, I build my custom DbConfiguration, which is being used, but the associated DbExecutionStrategy seems to be ignored.
Originally, my entire DbConfiguration was being ignored, but I found that was because I was referencing it in my app.config as well as decorating my entity constructor with the DbConfigurationType attribute [DbConfigurationType(typeof(MyConfiguration))]. Now that I'm only using the app.config, at least my custom configuration is being called.
In its simplest form, my custom config looks like this:
public class MyConfiguration : DbConfiguration
{
public MyConfiguration()
{
System.Windows.MessageBox.Show("Hey! Here I am!"); //I threw this in just to check that I was calling the constructor. Simple breakpoints don't seem to work here.
SetExecutionStrategy("System.Data.SqlClient", () => new MyExecutionStrategy(3, TimeSpan.FromMilliseconds(500)));
}
}
My custom DbConfiguration is referenced in my app.config like so:
<entityFramework codeConfigurationType="MyDataLayer.MyConfiguration, MyDataLayer">
...
</entityFramework>
My custom DbExecutionStrategy is built like so:
private class MyExecutionStrategy : DbExecutionStrategy
{
public MyExecutionStrategy() : this(3, TimeSpan.FromSeconds(2))
{
System.Windows.MessageBox.Show($"MyExecutionStrategy instantiated through default constructor.");
}
public MyExecutionStrategy(int maxRetryCount, TimeSpan maxDelay) : base(maxRetryCount, maxDelay)
{
System.Windows.MessageBox.Show($"MyExecutionStrategy instantiated through parametered constructor.");
}
protected override bool ShouldRetryOn(Exception ex)
{
System.Windows.MessageBox.Show($"Overriding ShouldRetryOn.");
bool retry = false;
SqlException sqlException = GetSqlException(ex);
if (sqlException != null)
{
int[] errorsToRetry =
{
1205, //Deadlock
-2 //Timeout
};
if (sqlException.Errors.Cast<SqlError>().Any(x => errorsToRetry.Contains(x.Number)))
{
retry = true;
}
}
if (ex is TimeoutException)
{
retry = true;
}
return retry;
}
}
I'm not hitting anything at all in this particular piece of the code.
One thing that may be of note, is that every example I've seen so far (for example http://blog.analystcircle.com/2015/08/01/connection-resiliency-in-entity-framework-6-0-and-above/) has casted the exception in ShouldRetryOn directly to a SqlException using
SqlException sqlException = ex as SqlException;
I found that using this method always resulted in a null SqlException because my program is throwing an EntityException which can't be cast into a SqlException. My underlying SqlException is actually the inner exception of the inner exception of the EntityException. So, I put together a short recursive call to dig in and find it.
private SqlException GetSqlException(Exception ex)
{
SqlException result = ex as SqlException;
if (result == null && ex.InnerException != null)
result = GetSqlException(ex.InnerException);
return result;
}
This works properly, but the fact that I need to do it when the examples I've found don't is probably a clue as to what's going wrong. Do EntityExceptions not trigger a DbExecutionStrategy? If not, why is this listed as a solution to be used with EF 6? Any insight would be much appreciated.
EDIT:
Doing some more digging into the source for DbExecutionStrategy (https://github.com/aspnet/EntityFramework6/blob/master/src/EntityFramework/Infrastructure/DbExecutionStrategy.cs), I've found that my recursive function to find my SqlException from the EntityException is unnecessary. DbExecutionStrategy has a function UnwrapAndHandleException which does just that and passes the SqlException on to ShouldRetryOn. So, it seems I'm right back at square one.
EDIT 2:
Not really a solution, because it doesn't explain why my DbExecutionStrategy isn't being called as it should, but I have found that if I explicitly call the execution strategy, it works.
The code to use the execution strategy explicitly is:
var executionStrategy = new MyConfiguration.MyExecutionStrategy();
executionStrategy.Execute(
() =>
{
//build your context and execute db functions here
using (var context = new Entities())
{
...do stuff
}
});
Probably way too old by now but in case anyone is having the same issues:
exception.GetBaseException() gets you the root cause of any exception. No need for recursion
I'm able to get this to work using EF 6.4.0
Related
In an application using Entity Framework 6, I track the changes made on tables in the database in a specially designed entity. They track the changes on all tables, including their own table.
So if an exception occurs while saving changes in the database, I delete all of the pending tracking entities in order to avoid creating new and new trackers recursively, log the exception and exit the saving method.
However, if the exception is caused due to connection timeout, I try 3 times to resave the changes, while changing the EntityState of the tracking entities to avoid creating unnecessary trackers. In order to accomplish that, I need to catch a DbUpdateException, get the SqlException down the hierarchy of exceptions, and check its number. However, I'm not sure how deep is the SqlException in the hierarchy. To accomplish successfully getting the Sql Exception, I wrote this:
catch (DbUpdateException duEx)
{
var inner = new Exception();
inner = duEx;
do
{
inner = inner.InnerException;
}
while (!(inner is SqlException) && inner != null);
var innerEx = inner as SqlException;
if (innerEx != null && innerEx.Number == -2)
{
//do job here
}
I tested it and it seems to work, however it looks a bit clumsy. So my question is: Is there any way of getting the SqlException, if any, directly?
What I was wondering is whether there is already some 3rd party
extension method which I could use
No, but you can create it yourself:
public static class Helper
{
public static TException GetInnerException<TException>(this Exception ex) where TException : Exception
{
return ex.InnerException != null
? ex.InnerException as TException ?? GetInnerException<TException>(ex.InnerException)
: null;
}
}
And use it :
catch (DbUpdateException duEx)
{
if (duEx.GetInnerException<SqlException>()?.Number == -2)
{
//do job here
}
}
I have some cases where I don't care what exception is thrown (as long as some exception is thrown). Unfortunately,
Assert.Throws<Exception>(someDelegate);
doesn't pass unless exactly an instance of Exception (so not an instance of a derived class) is thrown. I know I can obtain the behavior I want with
Exception exception = Record.Exception(someDelegate);
Assert.NotNull(exception);
but it doesn't read right. Am I missing something in xUnit that has the behavior I want? Here are two tests that indicate what I mean:
[Fact]
public void Throws_exception_and_passes() {
Exception exception = Record.Exception(
() => { throw new InvalidOperationException(); }
);
Assert.NotNull(exception);
}
[Fact]
public void Throws_exception_and_fails() {
Assert.Throws<Exception>(
() => { throw new InvalidOperationException(); }
);
}
Per the documentation here:
http://xunit.codeplex.com/wikipage?title=HowToUse&referringTitle=Home
You have to specify the type of exception you want to be thrown. In general, this is good practice. You should be able to predict what scenarios a test would throw what type of exception. You should be able to design both you method and your test in a way that will allow you to predict this.
There are ways around this, like doing a try catch yourself, but you should look into changing your design a bit.
It didn't exist at the time of this question, but now one can use Assert.ThrowsAny<Exception> to test for any exception derived from Exception (and hence any exception at all), along with variants such as Assert.ThrowsAny<ArgumentException> which would test for any exception derived from ArgumentException and so on.
As you've identified if Assert.Throws<T> doesn't fit the bill, the only OOTB thing in xUnit you're left with is using Record.Exception.
As you've identified, the main way of doing a 'Assert throws anything` is to do
Assert.NotNull( Record.Exception( lambda ))
Look at it - not pretty. This is likely by design; there are very few things in xUnit.net that are by accident (as opposed to carefully considered opinionated design).
Record.Exception returns a result for a reason (and if you were using F#, you'd have to |> ignore to chuck away the value). You should always be able to Assert something about the nature of the Exception that's happening so that an actual problem in your code doesn't get ignored by chance as you change your code over time, which is the reason for all this testing stuff in the first place. Perhaps that might take the form of
var exception = Record.Exception( sut.Something );
Assert.True( typeof(SomeException).IsAssignableFrom( exception ) );
Looking at that, it's safer that an Assert.NotNull(), but still doesn't feel right. It's time to, as discussed in GOOS, listen to your tests (and in the case of an opinionated test framework, your test framework).
The biggest problem in your question is however that in a real example from a real test, there is always a way to make your interface clearer or express your expectation in another way, so the real answer is Mu.
xUnit won't stand in your way if you want to do your own Custom Assertion, something like:
public static bool Throws<T>(this Action action, bool discardExceptions = false)
where T : Exception
{
try
{
action.Invoke();
}
catch (T)
{
return true;
}
catch (Exception)
{
if (discardExceptions)
{
return false;
}
throw;
}
return false;
}
Or:
public static bool Throws(this Action action)
{
try
{
action.Invoke();
}
catch (Exception)
{
return true;
}
return false;
}
I was just looking in the xUnit.net source and here is the culprit:
private static Exception Throws(Type exceptionType, Exception exception)
{
Guard.ArgumentNotNull("exceptionType", exceptionType);
if (exception == null)
throw new ThrowsException(exceptionType);
if (!exceptionType.Equals(exception.GetType()))
throw new ThrowsException(exceptionType, exception);
return exception;
}
What would solve your problem is if this change were applied:
if(!exceptionType.Equals(exception.GetType()))
to:
if(!exception.GetType().IsAssignableTo(exceptionType))
You could possibly offer to submit a patch?
public static void SuppressException<TSut>(this TSut value, Action<TSut> action) where TSut : class
{
try
{
action.Invoke(value);
}
catch (Exception)
{
//do nothing
}
}
I started working on this "already started" project, and I'm having a really annoying error when trying to execute some interactions with SQL Server 2008:
The server failed to resume the
transaction. Desc.:
One of these errors I get in this specific method call:
The aspx.cs Call:
busProcesso openProcess = new busProcesso(pProcessoId);
try
{
if (openProcess.GetDocument() == null)
{
//Irrelevant code.
}
}
catch{ //... }
The Business class (relevant part):
public class busProcesso : IbusProcesso
{
public Processo vProcesso { get; set; }
RENDBDataContext db;
public busProcesso()
{
vProcesso = new Processo();
}
public busProcesso(decimal pProcessoId)
{
db = new RENDBDataContext();
try
{
vProcesso = db.Processos.SingleOrDefault(x => x.Id == pProcessoId);
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
public string GetDocument()
{
try
{
string document = null;
foreach (Processo_has_Servico ps in ListaServicosProcesso())
{
if (ps.Servico.Document != null) //Get the error right at this line.
{
document = ps.Servico.Document;
}
}
return document ;
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
public IQueryable<Processo_has_Servico> ListaServicosProcesso()
{
db = new RENDBDataContext();
try
{
return from ps in db.Processo_has_Servicos
join s in db.Servicos on ps.Servico_Id equals s.Id
where ps.Processo_Id == vProcesso.Id
select ps;
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
}
As I said, the error occurs right at the line:
if (ps.Servico.Document != null) from the GetDocument() method.
Opening SQL Server Activity Monitor, I see there is a process for my database (.Net SqlClient Data Provider)
After some time/use (when I start to get the "server failed to resume the transaction" error), I go to the SQL Server Activity Monitor and there's around 5 or 6 more identical processes that weren't killed and (probably) should've been. When I manually kill them, the error stops for a while, until it starts again.
I'm not really good at working in OO and all, so I'm probably missing something, maybe some way to close one of these connections. Also, any help/tip about this structure will be welcome.
PS. The error doesn't happen everytime. Sometimes it runs just perfectly. Then it starts to give the error. Then it stops. Sometimes it happens just once.. pretty weird.
The code in ListaServicosProcesso is creating the context db. Then it is returning an IQueryable.
At this point no request has been sent to the database.
Then there is a for each in the code. At this point EF says "I need to get the data from the database". So it tries to get the data.
But the context db is now out of scope, so it crashes, on the first line that tries to use the data.
There are 2 ways to get around this:
return a list from ListaServicosProcesso, this will force the database call to execute
move the for each into ListaServicosProcesso
Edit
Pharabus is correct db is not out of scope. The problem is here:
db = new RENDBDataContext();
A new instance of the context is being created without the old one being disposed. Try Dispose of db at the end of ListaServicosProcesso. Even better place db in a using statement. But then the foreach must be moved inside the using statement.
Here's a couple of ideas to try.
1/ You can attach SQL server profiler to see the query that is being executed, which will allow you to copy and paste that query to see the data that is in the database. This might be help.
2/ You never check whether ps.Servico is null - you jump straight to ps.Servico.Document. If ps.Servico is null then you will get a null reference exception if you try to access any properties on that object.
I'm not sure of the exact cause of the error you're seeing (if you Google it, the references are all over the place...), but there are a few things you could improve in your code and I've found that just cleaning things up a bit often makes problems go away. Not always, but often.
I agree with the other answerers that it would help to keep better track of your DataContext(s). For example in you're creating it once in the constructor, then again in ListaServicosProcesso(). At that point vProcesso is on one DataContext and other entities will be on another, which gets messy.
I think you could simplify the whole thing a bit, for example you could combine GetDocument() and ListaServicosProcesso() like this:
public string GetDocument()
{
try
{
// Are you sure vProcesso is not null?
if (vProcesso == null)
return null;
// Only create the context if it wasn't already created,
if (db == null)
db = new RENDBDataContext();
return db.Processo_has_Servicos
.Where(ps => ps.Processo_Id == vProcesso.Id && ps.Servico.Document != null)
.Select(ps => ps.Servico.Document) // use an implicit join
.SingleOrDefault();
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
So, I have a list containing a custom class, MyClass
MyClass has properties, which can be null (but aren't meant to be).
When this class is sorted, using a custom sorter, where the sorter accesses this null property and throws an exception, the exception is considered unhandled, even though there is a try-catch block around the sort method.
Now for some reason the exception still gets written to the console, which is what the exception handler is doing.
I have a real application with this same issue, causing my unit tests to fail, even though the exception is handled correctly and I cannot explain this.
So I have attached some sample code to explain myself better, run this from VS.
Updated Code
Results:
System.InvalidOperationException
Failed to compare two elements in the array.
Done!
So it seems to be handling my custom exception, and throwing its own?
using System;
using System.Collections.Generic;
using System.Data;
namespace TestSortException
{
class Program
{
static void Main()
{
try
{
var list = new List<MyClass>
{
new MyClass("1"),
new MyClass(null),
new MyClass("fdsfsdf")
};
list.Sort(new MyClassSorter());
}
catch(Exception e)
{
Console.WriteLine(e.GetType());
Console.WriteLine(e.Message);
}
Console.WriteLine("Done!");
Console.ReadLine();
}
}
class MyClassSorter : IComparer<MyClass>
{
public int Compare(MyClass x, MyClass y)
{
// try
// {
if (x.MyString == y.MyString)
return 0;
// Unhandled??? Exception here
if (x.MyString.Length > y.MyString.Length)
return 1;
return -1;
// }
// catch (Exception)
// {
// return -1;
// }
}
}
class MyClass
{
private string _myString;
public string MyString
{
get
{
if (_myString == null) throw new DataException("MyString is Null");
return _myString;
}
}
public MyClass(string myString)
{
_myString = myString;
}
}
}
There's a try/catch block round the Sort method, yes - and that catch block catches the exception. In other words, Sort throws an exception and your catch block catches it. It doesn't propagate out beyond Main - so "Done!" is printed.
This is exactly what I'd expect. In what way is it "unhandled" in your experience? Were you expecting Sort not to throw the exception? It needs to do something to indicate the failure to compare two elements, and this seems to be the most appropriate course of action.
In what way are your unit tests failing? Are you deliberately giving them invalid data? How do you want your comparison code to react to invalid data? If it should ignore it (and return a comparison based on another property), then you should actively check the property rather than letting an exception propagate. In most cases I'd rather allow the exception if this indicates that there's a bug earlier on though.
EDIT: Based on your other comments, it sounds like you're doing the appropriate thing, letting the exception bubble up - but it's not clear in what way you're seeing the exception not be handled.
If you're running in the debugger, it may be breaking on the exception being thrown, but that doesn't mean it won't be handled. Try either changing your exception settings or running without the debugger.
EDIT: Yes, Sort will catch the exception and throw an InvalidOperationException instead - but you can use the InnerException property of that exception to get hold of the original one. It's unfortunate that the documentation doesn't specify this :(
For example, when it checks that string "1" isn't equal to null. But it wants then to compare lengths of "1" string and null => which is impossible.
I assume you work with .Net Framework 4.0. The new thing there is that a NullRefenrenceException can not be caught any more (similar to OutOfMemory exception).
I would like to use a COM object in my application.
How can I make sure the object is registered in the machine?
The only solution I found (also on SO) was to use a try-catch block around the initialization:
try {
Foo.Bar COM_oObject = new Foo.Bar();
} catch (Exception ee) {
// Something went wrong during init of COM object
}
Can I do it in any other way?
I feel its wrong to deal with an error by expecting it and reporting it, I would rather know I will fail and avoid it to begin with.
You are using exception handling the right way: to fail gracefully from a specific situation that you know how to recover from.
There's not a problem with using try-catch in this case, but you could at least catch more specifically : ComException.
"I feel its wrong to deal with an error by expecting it and reporting it"
Isn't it exactly the purpose of try-catch? BTW, an Exception occurs when something really bad has happened and since it is a pretty bad thing that the COM object you are referring to is not registered, therefore, an Exception is the perfect solution. And you can't handle an exception in any other way.
I think this is the right way to do it.
If you know your component's ProgId. You could try this trick
comType = Type.GetTypeFromProgID(progID,true/*throw on error*/);
If you're doing this a lot and wish you had a non-exception throwing equivalent, try:
public static class Catching<TException> where TException : Exception
{
public static bool Try<T>(Func<T> func, out T result)
{
try
{
result = func();
return true;
}
catch (TException x)
{
// log exception message (with call stacks
// and all InnerExceptions)
}
result = default(T);
return false;
}
public static T Try<T>(Func<T> func, T defaultValue)
{
T result;
if (Try(func, out result))
return result;
return defaultValue;
}
}
So now you can do this:
Foo.Bar newObj;
if (!Catching<ComException>.Try(() => new Foo.Bar(), out newObj))
{
// didn't work.
}
Or if you have a default object stored in defaultMyInterface you'd use to implement an interface if there's nothing better:
IMyInterface i = Catching<ComException>.Try(() => new Foo.Bar() as IMyInterface,
defaultMyInterface);
You can also do this, in a completely different scenario:
int queueSize = Catching<MyParsingException>
.Try(() => Parse(optionStr, "QueueSize"), 5);
If Parse throws a MyParsingException, queueSize will default to 5, otherwise the returned value from Parse is used (or any other exception will propagate normally, which is usually what you want with an unexpected exception).
This helps to avoid breaking up the flow of the code, and also centralises your logging policy.