New Posts New Posts RSS Feed: Exceptions and EntityManager.EntityChaged event
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Exceptions and EntityManager.EntityChaged event

 Post Reply Post Reply
Author
stephenmcd1 View Drop Down
DevForce MVP
DevForce MVP


Joined: 27-Oct-2009
Location: Los Angeles, CA
Posts: 166
Post Options Post Options   Quote stephenmcd1 Quote  Post ReplyReply Direct Link To This Post Topic: Exceptions and EntityManager.EntityChaged event
    Posted: 22-Apr-2011 at 4:41pm

We have some initialization logic that needs to happen for entities as they get added to an Entity Manager.  Currently, this is fired off from an event handler on EntityManager.EntityChanged.  This has worked well for us except for one thing.  If an exception is thrown in our initialization, it sometimes gets "swallowed".  After some fun times with Reflector, I noticed that EntityManager.OnEntityChanged is the one that is swallowing the exception if IsLoadingEntity is true.  This behavior might be nice for some cases, but in our case we want to know about these exceptions.

I was hoping I could just override OnEntityChanged to call my initialization logic directly (before calling base.OnEntityChanged() to raise the event).  This way, I'd be in control of the error handling, but OnEntityChanged is internal so I can't do that.

Would it be possible for OnEntityChanged to not be internal?  Or is there some other way I can have the exceptions not be swallowed?

Thanks,

-Stephen

Back to Top
sbelini View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 13-Aug-2010
Location: Oakland
Posts: 786
Post Options Post Options   Quote sbelini Quote  Post ReplyReply Direct Link To This Post Posted: 25-Apr-2011 at 3:58pm

Hi Stephen,

 
What do you exactly intend to do if an exception is thrown? While you can't propagate the exception, you can have a try/catch in your logic and add any found error to the ValidationErrors collection of the entity:
 
myEntity.EntityAspect.ValidationErrors.Add(new VerifierResult(VerifierResultCode.Error, "meaningful msg"));
 
The reason the exception can't be propagated is that a query is an atomic operation and if any exception were to be thrown, the entire thing would fail.
 
Silvio.
Back to Top
stephenmcd1 View Drop Down
DevForce MVP
DevForce MVP


Joined: 27-Oct-2009
Location: Los Angeles, CA
Posts: 166
Post Options Post Options   Quote stephenmcd1 Quote  Post ReplyReply Direct Link To This Post Posted: 25-Apr-2011 at 7:33pm
For us, exceptions thrown while we are doing entity initialization are fatal errors.  In production, fatal errors are logged, displayed to the user and then the application is be brought down to stop the user from continuing when things are in an unstable/unpredictable state (in DEBUG mode, it's a bit different because we don't bring down the whole application but we still want to know about these errors).

In fact, our desired behavior is exactly what you describe: "...if any exception were to be thrown, the entire thing would fail."  We do want the entire thing to fail - that's why we threw an exception :-)

The way it is now, since these exceptions get swallowed, the application continues without any hint that something has gone wrong.  The best solution I've come up with so far is the following but it feels so wrong, I was hoping there would be a better way:

if (e.Action.In(EntityAction.AddOnQuery, EntityAction.AddOnAttach,
                EntityAction.AddOnImport, EntityAction.Add,
                EntityAction.ChangeCurrentAndOriginal))
{
    //HACK: DevForce swallows exceptions in this method if the entity is being added.
    //To get around that, we'll catch any exceptions and re-throw them on a new
    //   thread (in addition to this one) so they will be picked up by the 
    //   exception processing code and will be visible.
    try
    {
        InitializeEntity((AlliantEntity) e.Entity);
    }
    catch (Exception ex)
    {
        //Throw the exception in a new thread
        new Thread(
            () =>
                {
                    throw new AlliantApplicationException(
                        "Exception thrown during entity initialization and may have been swallowed.  See inner exception.",
                        ex);
                }).Start();

        //And throw the exception to our caller
        throw;
    }
}

Thanks
Back to Top
sbelini View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 13-Aug-2010
Location: Oakland
Posts: 786
Post Options Post Options   Quote sbelini Quote  Post ReplyReply Direct Link To This Post Posted: 26-Apr-2011 at 2:39pm
Stephen,
 
In your workaroud, doesn't the exception get "lost/swallowed" in/with the new thread? That'd be the only issue I see with your proposed solution.
 
Another approach would be having a try/catch in your logic and writting to log/exiting the app ( App.Current.Shutdown() ) there.
 
Silvio.
Back to Top
stephenmcd1 View Drop Down
DevForce MVP
DevForce MVP


Joined: 27-Oct-2009
Location: Los Angeles, CA
Posts: 166
Post Options Post Options   Quote stephenmcd1 Quote  Post ReplyReply Direct Link To This Post Posted: 26-Apr-2011 at 2:49pm
It works fine on the client side.  Our client is a Silverlight app and we have some "catch all" error handling in the Application.UnhandledException event (that manages to catch exceptions thrown on any thread).

I imagine this approach won't work so well if it executes on the BOS though.  I don't know if maybe the exception in the new thread will be lost.  Also, the client will not be notified of any problems and won't have any way of knowing that the query/save/etc. threw exceptions on the server.  Is there anything I could do in server-side code so this error won't be hidden from the client?  Something like App.Current.Shutdown only really makes sense on the client but not on the BOS.

Thanks for the help,
-Stephen
Back to Top
stephenmcd1 View Drop Down
DevForce MVP
DevForce MVP


Joined: 27-Oct-2009
Location: Los Angeles, CA
Posts: 166
Post Options Post Options   Quote stephenmcd1 Quote  Post ReplyReply Direct Link To This Post Posted: 27-Nov-2012 at 2:21pm
I'm going to bring back this old thread because I noticed that part of this issue has been addressed in 6.1.9.0.  I saw this in the release notes:

Exceptions thrown in EntityChanging/EntityChanged handlers will not be "eaten" for add/attach actions.  [D2238]

I'm not sure how that fix all of a sudden made it in but I like it.  One thing....that only covers the case where EntityChanging/Changed gets fired because of an Add or Attach.  But what about AddOnQuery?  That is a big one for us where we often do initialization type logic when the entity is first loaded as part of a query - and we do not want exceptions thrown there to be swallowed.  We also do logic for other EntityActions.  Is there a reason that this change was limited to just Add/Attach?  Any chance that this could be extended to more (all?) Entity Actions?

Thanks,
-Stephen
Back to Top
kimj View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 1391
Post Options Post Options   Quote kimj Quote  Post ReplyReply Direct Link To This Post Posted: 27-Nov-2012 at 3:27pm
We added this fix at the request of our Professional Services group, and after much debate it was specifically made only for add and attach actions.  The argument for swallowing exceptions thrown during AddOnQuery (and AddOnImport) was that "failing in the middle of a query is usually not what the developer actually intended" because it was more likely to occur due to a badly written event handler.  We can revisit this, but in truth you're better off leaving your workaround in place for now.
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down