10

I am a new ASP.NET developer and this is my first time to use Linq-to-Entities and Entity Framework. My problem now is about using the best practice of connecting to the Entities or Database. I know that try-catch block is very expensive. But should I use them whenever I need to connect to the database? I am asking this question because I have around 20 entities and in my Data Access Layer, I have all the GetData() methods for each one of these entities. Could you please advise on this?

C# code:

public static IEnumerable<Items> getData()
{
    List<Items> itemsList = new List<Items>();
    try
    {
        using (ItemsDBEntities context = new ItemsDBEntities())
        {
            itemsList = (from item in context.Items
                         select new Items()
                         {
                             ID = item.ID,
                             Code = item.Code,
                             Name = item.Name,
                             StatusID = item.StatusID
                         }).ToList();
        }
    }
    catch (EntityException ex)
    {
        //something wrong about entity
    }
    catch (Exception ex)
    {
        //Don't know what happend... 
    }
    return itemsList;
}
i3arnon
  • 113,022
  • 33
  • 324
  • 344
Technology Lover
  • 259
  • 1
  • 7
  • 19
  • "*I know that try-catch block is very expensive*" - I wouldn't say *very* expensive, however, there is some overhead. – James Jan 03 '14 at 16:37

3 Answers3

9

You definitely don't want to catch Exception here because you could mask other (possibly bigger) problems with your code.

Generally, you should only catch exceptions if you intend on handling them in some way. For example, in your scenario you might want to display a UI message if the connection fails. The best approach for this is to let the exception bubble up to the layer in which you actually want to handle it in.

To avoid coupling between your layers a good approach is to catch the storage-specific exception in the DAL and raise a more application-specific exception which you can then handle in the upper layers e.g.

DAL

public static IEnumerable<Items> getData()
{
    List<Items> itemsList = new List<Items>();
    try
    {
        using (ItemsDBEntities context = new ItemsDBEntities())
        {
            itemsList = (from item in context.Items
                         select new Items()
                         {
                             ID = item.ID,
                             Code = item.Code,
                             Name = item.Name,
                             StatusID = item.StatusID
                         }).ToList();
        }
    }
    catch (EntityException ex)
    {
        throw new ConnectionFailedException(ex);
    }
    return itemsList;
}

UI

try
{
    var items = Repo.getData();
    ...
}
catch (ConnectionFailedException)
{
    MessageBox.Show("There was a problem accessing the database, please try again.");
}

If you need guidance on how to go about implementing a custom exception, see this answer.

Community
  • 1
  • 1
James
  • 80,725
  • 18
  • 167
  • 237
  • thank you for your help and I really appreciate your clear explanation. One more question, in case I have a custom error logging class, where should I use it in your answer? Should I include it in the DAL or UI? – Technology Lover Jan 04 '14 at 09:00
  • @TechnologyLover that's really down to you, however, a logging framework is generally ingrained into your application therefore it can go anywhere. – James Jan 04 '14 at 11:47
6

try-catch block is very expensive.

Try is cheap, catch is cheap, throw is expensive. So, if code execution follows normal path (does not produce exceptions), try-catch's are no problem. (BTW, expensive throw is one reason why you should avoid exception-based logical flows in your code) Even if you avoid try-catch block, throwing is still expensive.

should I use them whenever I need to connect to the database?

This comes down to your judgement call. Generally, it is a bad idea to have naked throws between layers of your app. It is equally bad idea to have multiple catches within a single block of your app.

I'd say you definitely want to catch Exception on top level of your DAL: client should not care about your internal problems (DB connections, timeouts, bad logins, etc.).

And here I have to basically just quote previous answer:

to avoid coupling between your layers... raise a custom, application specific, exception which you can then handle in the upper layers

Two good ideas for your catch's is to (1) log exception (so DAL's side knows about it afterwards), (2) have unit tests in place (pre-execute SQL to write known data into DB, then invoke GetData()) so that you can detect general problems prior releasing DAL for client's use

user270576
  • 987
  • 10
  • 16
  • "*It is equally bad idea to have multiple catches within a single block of your app*" - what's your reasoning for multiple catches being a bad idea? – James Jan 04 '14 at 11:46
  • Just to clarify, by "multiple" I meant several with one being enclosed in another. And the reason is quite simple - having code paths that lead from inner **catch** to outer **catch** would mean throwing, and throwing is expensive. And if there are no code paths that lead to outer catch then it is simply redundant. – user270576 Jan 20 '14 at 21:00
1

Do not catch an exception unless you intend to do something with it. For example maybe you want to retry connecting to the db x number of times before allowing the exception to bubble up. I would suggest not bothering wrapping you code in a try catch unless you are going to do something special.

Leigh Ciechanowski
  • 1,297
  • 17
  • 33
  • I will add an error message in the catch block. Is it a good way of doing it? I think if I don't use try-catch, then the user will see an error message and this is not a good way of handling it. What do you think? – Technology Lover Jan 03 '14 at 17:21
  • @TechnologyLover you really don't want to be putting error messages inside your DAL. – James Jan 03 '14 at 18:03
  • @James, so what do you suggest? Should I use try-catch block? or using block will be enough? – Technology Lover Jan 03 '14 at 18:04