Place try/catch in business logic or user interface I found the following two types of exception-handling in Business Logic Layer. 

ASP.NET 3.5 Enterprise Application Development uses a similar method like the first one (I read it few years ago).

I also found this on Stack Overflow, but it doesn't answer my question.

I'm wondering which one is better design and efficiency.

Method 1 - in Business Logic Layer

private int InsertUser(string firstname, string lastname, ref List&lt;string&gt; errors)
{
    if (!string.IsNullOrEmpty(firstname))
        errors.Add("First name is required.");

    if (!string.IsNullOrEmpty(lastname))
        errors.Add("Last name is required.");

    if (errors.Count &gt; 0)
        return -1;

    int userId = -1;

    try
    {
        // Insert user and return userId    
    }
    catch (Exception ex)
    {
        // Log error to database
        errors.Add("Error occurs. Please contact customer service.");
    }

    return userId;
}


Method 2 - in Business Logic Layer

private int InsertUser(string firstname, string lastname)
{
    if (!string.IsNullOrEmpty(firstname))
        throw new ArgumentNullException(firstname);

    if (!string.IsNullOrEmpty(lastname))
        throw new ArgumentNullException(lastname);

    int userId = -1;

    // Insert user and return userId. Let user handle the exception in UI.

    return userId;
}


The disadvantage of Method 2 is that the UI has to filter out what to display/not display the error depending on the exception.  For instance, you might not want to display a System.Data.Entity exception to the user.
It can be interesting to convey more information about the error to the end user, but it doesn't mean the UI layer has to be the only one to handle the exception.

You can both log the error into your database from the business layer and relay it to the UI layer if you rethrow the exception:

try {
    // Insert user and return userId...
} catch (Exception ex) {
    // Log error to database...
    throw;  // Relay error to UI layer.
}