Reading SQL query from a resource, with error logging











up vote
4
down vote

favorite












I've created a utility class that expects a logger to be passed at a method level, since I prefer legitimate errors to be written out for troubleshooting later on. Another developer hates passing the logger to the method, because he does not care.




  1. Cannot use optional attribute, since ILogger is not a constant.

  2. Cannot use params because it would be a singleton, not a collection.


So I implemented it in the following manner:



public static class EmbeddedResourceUtility
{
public static string GetSqlQuery(string namespaceAndFileNameWithExtension, ILogger logger)
{
try
{
using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
using(var reader = new StreamReader(stream, Encoding.UTF8))
return reader.ReadToEnd();
}

catch(Exception exception)
{
logger.Error($"Failed to read query file {namespaceAndFileNameWithExtension}. {Environment.NewLine}{exception.HResult}: {exception.Message}");
throw new Exception(exception.Message);
}
}
}


Would be incorrect to expect someone to pass an ILogger even if they do not intend to use it? Or would there be a better way to handle this?










share|improve this question




















  • 1




    I think this question leads to a much bigger problem. You need a standard. This kind of thing can't be half implemented in your system when you add it and your other dev. doesn't. Although I believe 200_success's answer covers your specific problem very well.
    – IEatBagels
    Dec 4 at 18:21















up vote
4
down vote

favorite












I've created a utility class that expects a logger to be passed at a method level, since I prefer legitimate errors to be written out for troubleshooting later on. Another developer hates passing the logger to the method, because he does not care.




  1. Cannot use optional attribute, since ILogger is not a constant.

  2. Cannot use params because it would be a singleton, not a collection.


So I implemented it in the following manner:



public static class EmbeddedResourceUtility
{
public static string GetSqlQuery(string namespaceAndFileNameWithExtension, ILogger logger)
{
try
{
using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
using(var reader = new StreamReader(stream, Encoding.UTF8))
return reader.ReadToEnd();
}

catch(Exception exception)
{
logger.Error($"Failed to read query file {namespaceAndFileNameWithExtension}. {Environment.NewLine}{exception.HResult}: {exception.Message}");
throw new Exception(exception.Message);
}
}
}


Would be incorrect to expect someone to pass an ILogger even if they do not intend to use it? Or would there be a better way to handle this?










share|improve this question




















  • 1




    I think this question leads to a much bigger problem. You need a standard. This kind of thing can't be half implemented in your system when you add it and your other dev. doesn't. Although I believe 200_success's answer covers your specific problem very well.
    – IEatBagels
    Dec 4 at 18:21













up vote
4
down vote

favorite









up vote
4
down vote

favorite











I've created a utility class that expects a logger to be passed at a method level, since I prefer legitimate errors to be written out for troubleshooting later on. Another developer hates passing the logger to the method, because he does not care.




  1. Cannot use optional attribute, since ILogger is not a constant.

  2. Cannot use params because it would be a singleton, not a collection.


So I implemented it in the following manner:



public static class EmbeddedResourceUtility
{
public static string GetSqlQuery(string namespaceAndFileNameWithExtension, ILogger logger)
{
try
{
using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
using(var reader = new StreamReader(stream, Encoding.UTF8))
return reader.ReadToEnd();
}

catch(Exception exception)
{
logger.Error($"Failed to read query file {namespaceAndFileNameWithExtension}. {Environment.NewLine}{exception.HResult}: {exception.Message}");
throw new Exception(exception.Message);
}
}
}


Would be incorrect to expect someone to pass an ILogger even if they do not intend to use it? Or would there be a better way to handle this?










share|improve this question















I've created a utility class that expects a logger to be passed at a method level, since I prefer legitimate errors to be written out for troubleshooting later on. Another developer hates passing the logger to the method, because he does not care.




  1. Cannot use optional attribute, since ILogger is not a constant.

  2. Cannot use params because it would be a singleton, not a collection.


So I implemented it in the following manner:



public static class EmbeddedResourceUtility
{
public static string GetSqlQuery(string namespaceAndFileNameWithExtension, ILogger logger)
{
try
{
using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
using(var reader = new StreamReader(stream, Encoding.UTF8))
return reader.ReadToEnd();
}

catch(Exception exception)
{
logger.Error($"Failed to read query file {namespaceAndFileNameWithExtension}. {Environment.NewLine}{exception.HResult}: {exception.Message}");
throw new Exception(exception.Message);
}
}
}


Would be incorrect to expect someone to pass an ILogger even if they do not intend to use it? Or would there be a better way to handle this?







c# error-handling logging .net-core






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 4 at 17:14









200_success

128k15149412




128k15149412










asked Dec 4 at 16:59









Greg

43038




43038








  • 1




    I think this question leads to a much bigger problem. You need a standard. This kind of thing can't be half implemented in your system when you add it and your other dev. doesn't. Although I believe 200_success's answer covers your specific problem very well.
    – IEatBagels
    Dec 4 at 18:21














  • 1




    I think this question leads to a much bigger problem. You need a standard. This kind of thing can't be half implemented in your system when you add it and your other dev. doesn't. Although I believe 200_success's answer covers your specific problem very well.
    – IEatBagels
    Dec 4 at 18:21








1




1




I think this question leads to a much bigger problem. You need a standard. This kind of thing can't be half implemented in your system when you add it and your other dev. doesn't. Although I believe 200_success's answer covers your specific problem very well.
– IEatBagels
Dec 4 at 18:21




I think this question leads to a much bigger problem. You need a standard. This kind of thing can't be half implemented in your system when you add it and your other dev. doesn't. Although I believe 200_success's answer covers your specific problem very well.
– IEatBagels
Dec 4 at 18:21










2 Answers
2






active

oldest

votes

















up vote
6
down vote



accepted










The most unforgivable aspect of this code is that it rethrows a degraded exception. The original type of the exception (likely an IOException) and the stack trace information are lost when you throw new Exception(…).



Two acceptable approaches are:





  1. Log the failure (if a non-null logger was passed). Then re-throw the original exception.



     public static string GetSqlQuery(string namespaceAndFileNameWithExtension, ILogger logger)
    {
    try
    {
    using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
    using(var reader = new StreamReader(stream, Encoding.UTF8))
    {
    return reader.ReadToEnd();
    }
    }
    catch (Exception exception)
    {
    logger?.Error($"Failed to read query file {namespaceAndFileNameWithExtension}.{Environment.NewLine}{exception.HResult}: {exception.Message}");
    throw;
    }
    }



  2. Throw a custom exception, wrapping the original exception.



     public static string GetSqlQuery(string namespaceAndFileNameWithExtension)
    {
    try
    {
    using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
    using(var reader = new StreamReader(stream, Encoding.UTF8))
    {
    return reader.ReadToEnd();
    }
    }
    catch (Exception exception)
    {
    throw new EmbeddedResourceException($"Failed to read query file {namespaceAndFileNameWithExtension}", exception);
    }
    }


    In this case, requiring an ILogger just isn't worth it. The caller has all of the information in the EmbeddedResourceException, and can log it if it wants.




I recommend the second approach, because it respects the principle of separation of concerns.






share|improve this answer























  • but the exception would be logged to the event viewer instead of an application specific log file, which does require extra investigation and more information to find the thrown event though correct?
    – Greg
    Dec 4 at 17:43






  • 1




    Who calls this GetSqlQuery() function? At some point, some caller in the stack should catch the exception and handle it in the way that you want.
    – 200_success
    Dec 4 at 17:45










  • Their implemented context class where they read the query resources, so they should be actually handling any exceptions at that point or when they call their context. To know if something failed to enter the database.
    – Greg
    Dec 4 at 17:48


















up vote
4
down vote














Would be incorrect to expect someone to pass an ILogger even if they do not intend to use it?





  • If I wouldn't want to pass an ILogger I would just pass (ILogger)null and your method would throw a NullReferenceException if an exception occurs. If you use C# 6 you could use the Null-conditional operator


  • If you keep the method signature like posted anyone who uses this method needs to pass an ILogger. To overcome this problem you can either make the ILogger argument optional or you implement an overloaded version of this method which doesn't take an ILogger argument.


  • Omitting braces althought they might be optional should be avoided.


  • Throwing throw new Exception(exception.Message) will destroy the stacktrace. It would be better to just throw.


  • By using the ctor of StreamReader which only takes a Stream as argument the default encoding is UTF8Encoding.



Implementing the mentioned points would lead to



public static class EmbeddedResourceUtility
{
public static string GetSqlQuery(string namespaceAndFileNameWithExtension)
{
return GetSqlQuery(namespaceAndFileNameWithExtension, (ILogger)null);
}
public static string GetSqlQuery(string namespaceAndFileNameWithExtension, ILogger logger)
{
try
{
using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
using(var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
catch(Exception exception)
{
logger?.Error($"Failed to read query file {namespaceAndFileNameWithExtension}. {Environment.NewLine}{exception.HResult}: {exception.Message}");
throw;
}
}
}





share|improve this answer





















  • In C# 8 when they introduce nothing is null by default unless explicit, would that change your expectation?
    – Greg
    Dec 4 at 17:49










  • Well I did't inform me about C# 8. I usually only work with what is avaible.
    – Heslacher
    Dec 4 at 17:50










  • Oh, fair enough. I just know the paradigm for C# is about to shift. I know the feature is an opt-in, but in essence with the current way everything is null since a state has not been defined, in C# 8 nothing can be assigned as null unless the type explicitly allows it. So I was just curious if that would change your answer or you think this is still the best course of action? I am not trying to demean or dismiss your current answer, simply want to get the most information so I may make the best decision possible for implementation.
    – Greg
    Dec 4 at 17:52










  • Why not use an optional parameter on the ILogger instead of an overload?
    – IEatBagels
    Dec 4 at 18:22










  • Because using an overloaded method is ckearer from the caller side.
    – Heslacher
    Dec 4 at 18:32











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f209007%2freading-sql-query-from-a-resource-with-error-logging%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
6
down vote



accepted










The most unforgivable aspect of this code is that it rethrows a degraded exception. The original type of the exception (likely an IOException) and the stack trace information are lost when you throw new Exception(…).



Two acceptable approaches are:





  1. Log the failure (if a non-null logger was passed). Then re-throw the original exception.



     public static string GetSqlQuery(string namespaceAndFileNameWithExtension, ILogger logger)
    {
    try
    {
    using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
    using(var reader = new StreamReader(stream, Encoding.UTF8))
    {
    return reader.ReadToEnd();
    }
    }
    catch (Exception exception)
    {
    logger?.Error($"Failed to read query file {namespaceAndFileNameWithExtension}.{Environment.NewLine}{exception.HResult}: {exception.Message}");
    throw;
    }
    }



  2. Throw a custom exception, wrapping the original exception.



     public static string GetSqlQuery(string namespaceAndFileNameWithExtension)
    {
    try
    {
    using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
    using(var reader = new StreamReader(stream, Encoding.UTF8))
    {
    return reader.ReadToEnd();
    }
    }
    catch (Exception exception)
    {
    throw new EmbeddedResourceException($"Failed to read query file {namespaceAndFileNameWithExtension}", exception);
    }
    }


    In this case, requiring an ILogger just isn't worth it. The caller has all of the information in the EmbeddedResourceException, and can log it if it wants.




I recommend the second approach, because it respects the principle of separation of concerns.






share|improve this answer























  • but the exception would be logged to the event viewer instead of an application specific log file, which does require extra investigation and more information to find the thrown event though correct?
    – Greg
    Dec 4 at 17:43






  • 1




    Who calls this GetSqlQuery() function? At some point, some caller in the stack should catch the exception and handle it in the way that you want.
    – 200_success
    Dec 4 at 17:45










  • Their implemented context class where they read the query resources, so they should be actually handling any exceptions at that point or when they call their context. To know if something failed to enter the database.
    – Greg
    Dec 4 at 17:48















up vote
6
down vote



accepted










The most unforgivable aspect of this code is that it rethrows a degraded exception. The original type of the exception (likely an IOException) and the stack trace information are lost when you throw new Exception(…).



Two acceptable approaches are:





  1. Log the failure (if a non-null logger was passed). Then re-throw the original exception.



     public static string GetSqlQuery(string namespaceAndFileNameWithExtension, ILogger logger)
    {
    try
    {
    using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
    using(var reader = new StreamReader(stream, Encoding.UTF8))
    {
    return reader.ReadToEnd();
    }
    }
    catch (Exception exception)
    {
    logger?.Error($"Failed to read query file {namespaceAndFileNameWithExtension}.{Environment.NewLine}{exception.HResult}: {exception.Message}");
    throw;
    }
    }



  2. Throw a custom exception, wrapping the original exception.



     public static string GetSqlQuery(string namespaceAndFileNameWithExtension)
    {
    try
    {
    using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
    using(var reader = new StreamReader(stream, Encoding.UTF8))
    {
    return reader.ReadToEnd();
    }
    }
    catch (Exception exception)
    {
    throw new EmbeddedResourceException($"Failed to read query file {namespaceAndFileNameWithExtension}", exception);
    }
    }


    In this case, requiring an ILogger just isn't worth it. The caller has all of the information in the EmbeddedResourceException, and can log it if it wants.




I recommend the second approach, because it respects the principle of separation of concerns.






share|improve this answer























  • but the exception would be logged to the event viewer instead of an application specific log file, which does require extra investigation and more information to find the thrown event though correct?
    – Greg
    Dec 4 at 17:43






  • 1




    Who calls this GetSqlQuery() function? At some point, some caller in the stack should catch the exception and handle it in the way that you want.
    – 200_success
    Dec 4 at 17:45










  • Their implemented context class where they read the query resources, so they should be actually handling any exceptions at that point or when they call their context. To know if something failed to enter the database.
    – Greg
    Dec 4 at 17:48













up vote
6
down vote



accepted







up vote
6
down vote



accepted






The most unforgivable aspect of this code is that it rethrows a degraded exception. The original type of the exception (likely an IOException) and the stack trace information are lost when you throw new Exception(…).



Two acceptable approaches are:





  1. Log the failure (if a non-null logger was passed). Then re-throw the original exception.



     public static string GetSqlQuery(string namespaceAndFileNameWithExtension, ILogger logger)
    {
    try
    {
    using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
    using(var reader = new StreamReader(stream, Encoding.UTF8))
    {
    return reader.ReadToEnd();
    }
    }
    catch (Exception exception)
    {
    logger?.Error($"Failed to read query file {namespaceAndFileNameWithExtension}.{Environment.NewLine}{exception.HResult}: {exception.Message}");
    throw;
    }
    }



  2. Throw a custom exception, wrapping the original exception.



     public static string GetSqlQuery(string namespaceAndFileNameWithExtension)
    {
    try
    {
    using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
    using(var reader = new StreamReader(stream, Encoding.UTF8))
    {
    return reader.ReadToEnd();
    }
    }
    catch (Exception exception)
    {
    throw new EmbeddedResourceException($"Failed to read query file {namespaceAndFileNameWithExtension}", exception);
    }
    }


    In this case, requiring an ILogger just isn't worth it. The caller has all of the information in the EmbeddedResourceException, and can log it if it wants.




I recommend the second approach, because it respects the principle of separation of concerns.






share|improve this answer














The most unforgivable aspect of this code is that it rethrows a degraded exception. The original type of the exception (likely an IOException) and the stack trace information are lost when you throw new Exception(…).



Two acceptable approaches are:





  1. Log the failure (if a non-null logger was passed). Then re-throw the original exception.



     public static string GetSqlQuery(string namespaceAndFileNameWithExtension, ILogger logger)
    {
    try
    {
    using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
    using(var reader = new StreamReader(stream, Encoding.UTF8))
    {
    return reader.ReadToEnd();
    }
    }
    catch (Exception exception)
    {
    logger?.Error($"Failed to read query file {namespaceAndFileNameWithExtension}.{Environment.NewLine}{exception.HResult}: {exception.Message}");
    throw;
    }
    }



  2. Throw a custom exception, wrapping the original exception.



     public static string GetSqlQuery(string namespaceAndFileNameWithExtension)
    {
    try
    {
    using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
    using(var reader = new StreamReader(stream, Encoding.UTF8))
    {
    return reader.ReadToEnd();
    }
    }
    catch (Exception exception)
    {
    throw new EmbeddedResourceException($"Failed to read query file {namespaceAndFileNameWithExtension}", exception);
    }
    }


    In this case, requiring an ILogger just isn't worth it. The caller has all of the information in the EmbeddedResourceException, and can log it if it wants.




I recommend the second approach, because it respects the principle of separation of concerns.







share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 4 at 20:36

























answered Dec 4 at 17:38









200_success

128k15149412




128k15149412












  • but the exception would be logged to the event viewer instead of an application specific log file, which does require extra investigation and more information to find the thrown event though correct?
    – Greg
    Dec 4 at 17:43






  • 1




    Who calls this GetSqlQuery() function? At some point, some caller in the stack should catch the exception and handle it in the way that you want.
    – 200_success
    Dec 4 at 17:45










  • Their implemented context class where they read the query resources, so they should be actually handling any exceptions at that point or when they call their context. To know if something failed to enter the database.
    – Greg
    Dec 4 at 17:48


















  • but the exception would be logged to the event viewer instead of an application specific log file, which does require extra investigation and more information to find the thrown event though correct?
    – Greg
    Dec 4 at 17:43






  • 1




    Who calls this GetSqlQuery() function? At some point, some caller in the stack should catch the exception and handle it in the way that you want.
    – 200_success
    Dec 4 at 17:45










  • Their implemented context class where they read the query resources, so they should be actually handling any exceptions at that point or when they call their context. To know if something failed to enter the database.
    – Greg
    Dec 4 at 17:48
















but the exception would be logged to the event viewer instead of an application specific log file, which does require extra investigation and more information to find the thrown event though correct?
– Greg
Dec 4 at 17:43




but the exception would be logged to the event viewer instead of an application specific log file, which does require extra investigation and more information to find the thrown event though correct?
– Greg
Dec 4 at 17:43




1




1




Who calls this GetSqlQuery() function? At some point, some caller in the stack should catch the exception and handle it in the way that you want.
– 200_success
Dec 4 at 17:45




Who calls this GetSqlQuery() function? At some point, some caller in the stack should catch the exception and handle it in the way that you want.
– 200_success
Dec 4 at 17:45












Their implemented context class where they read the query resources, so they should be actually handling any exceptions at that point or when they call their context. To know if something failed to enter the database.
– Greg
Dec 4 at 17:48




Their implemented context class where they read the query resources, so they should be actually handling any exceptions at that point or when they call their context. To know if something failed to enter the database.
– Greg
Dec 4 at 17:48












up vote
4
down vote














Would be incorrect to expect someone to pass an ILogger even if they do not intend to use it?





  • If I wouldn't want to pass an ILogger I would just pass (ILogger)null and your method would throw a NullReferenceException if an exception occurs. If you use C# 6 you could use the Null-conditional operator


  • If you keep the method signature like posted anyone who uses this method needs to pass an ILogger. To overcome this problem you can either make the ILogger argument optional or you implement an overloaded version of this method which doesn't take an ILogger argument.


  • Omitting braces althought they might be optional should be avoided.


  • Throwing throw new Exception(exception.Message) will destroy the stacktrace. It would be better to just throw.


  • By using the ctor of StreamReader which only takes a Stream as argument the default encoding is UTF8Encoding.



Implementing the mentioned points would lead to



public static class EmbeddedResourceUtility
{
public static string GetSqlQuery(string namespaceAndFileNameWithExtension)
{
return GetSqlQuery(namespaceAndFileNameWithExtension, (ILogger)null);
}
public static string GetSqlQuery(string namespaceAndFileNameWithExtension, ILogger logger)
{
try
{
using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
using(var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
catch(Exception exception)
{
logger?.Error($"Failed to read query file {namespaceAndFileNameWithExtension}. {Environment.NewLine}{exception.HResult}: {exception.Message}");
throw;
}
}
}





share|improve this answer





















  • In C# 8 when they introduce nothing is null by default unless explicit, would that change your expectation?
    – Greg
    Dec 4 at 17:49










  • Well I did't inform me about C# 8. I usually only work with what is avaible.
    – Heslacher
    Dec 4 at 17:50










  • Oh, fair enough. I just know the paradigm for C# is about to shift. I know the feature is an opt-in, but in essence with the current way everything is null since a state has not been defined, in C# 8 nothing can be assigned as null unless the type explicitly allows it. So I was just curious if that would change your answer or you think this is still the best course of action? I am not trying to demean or dismiss your current answer, simply want to get the most information so I may make the best decision possible for implementation.
    – Greg
    Dec 4 at 17:52










  • Why not use an optional parameter on the ILogger instead of an overload?
    – IEatBagels
    Dec 4 at 18:22










  • Because using an overloaded method is ckearer from the caller side.
    – Heslacher
    Dec 4 at 18:32















up vote
4
down vote














Would be incorrect to expect someone to pass an ILogger even if they do not intend to use it?





  • If I wouldn't want to pass an ILogger I would just pass (ILogger)null and your method would throw a NullReferenceException if an exception occurs. If you use C# 6 you could use the Null-conditional operator


  • If you keep the method signature like posted anyone who uses this method needs to pass an ILogger. To overcome this problem you can either make the ILogger argument optional or you implement an overloaded version of this method which doesn't take an ILogger argument.


  • Omitting braces althought they might be optional should be avoided.


  • Throwing throw new Exception(exception.Message) will destroy the stacktrace. It would be better to just throw.


  • By using the ctor of StreamReader which only takes a Stream as argument the default encoding is UTF8Encoding.



Implementing the mentioned points would lead to



public static class EmbeddedResourceUtility
{
public static string GetSqlQuery(string namespaceAndFileNameWithExtension)
{
return GetSqlQuery(namespaceAndFileNameWithExtension, (ILogger)null);
}
public static string GetSqlQuery(string namespaceAndFileNameWithExtension, ILogger logger)
{
try
{
using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
using(var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
catch(Exception exception)
{
logger?.Error($"Failed to read query file {namespaceAndFileNameWithExtension}. {Environment.NewLine}{exception.HResult}: {exception.Message}");
throw;
}
}
}





share|improve this answer





















  • In C# 8 when they introduce nothing is null by default unless explicit, would that change your expectation?
    – Greg
    Dec 4 at 17:49










  • Well I did't inform me about C# 8. I usually only work with what is avaible.
    – Heslacher
    Dec 4 at 17:50










  • Oh, fair enough. I just know the paradigm for C# is about to shift. I know the feature is an opt-in, but in essence with the current way everything is null since a state has not been defined, in C# 8 nothing can be assigned as null unless the type explicitly allows it. So I was just curious if that would change your answer or you think this is still the best course of action? I am not trying to demean or dismiss your current answer, simply want to get the most information so I may make the best decision possible for implementation.
    – Greg
    Dec 4 at 17:52










  • Why not use an optional parameter on the ILogger instead of an overload?
    – IEatBagels
    Dec 4 at 18:22










  • Because using an overloaded method is ckearer from the caller side.
    – Heslacher
    Dec 4 at 18:32













up vote
4
down vote










up vote
4
down vote










Would be incorrect to expect someone to pass an ILogger even if they do not intend to use it?





  • If I wouldn't want to pass an ILogger I would just pass (ILogger)null and your method would throw a NullReferenceException if an exception occurs. If you use C# 6 you could use the Null-conditional operator


  • If you keep the method signature like posted anyone who uses this method needs to pass an ILogger. To overcome this problem you can either make the ILogger argument optional or you implement an overloaded version of this method which doesn't take an ILogger argument.


  • Omitting braces althought they might be optional should be avoided.


  • Throwing throw new Exception(exception.Message) will destroy the stacktrace. It would be better to just throw.


  • By using the ctor of StreamReader which only takes a Stream as argument the default encoding is UTF8Encoding.



Implementing the mentioned points would lead to



public static class EmbeddedResourceUtility
{
public static string GetSqlQuery(string namespaceAndFileNameWithExtension)
{
return GetSqlQuery(namespaceAndFileNameWithExtension, (ILogger)null);
}
public static string GetSqlQuery(string namespaceAndFileNameWithExtension, ILogger logger)
{
try
{
using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
using(var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
catch(Exception exception)
{
logger?.Error($"Failed to read query file {namespaceAndFileNameWithExtension}. {Environment.NewLine}{exception.HResult}: {exception.Message}");
throw;
}
}
}





share|improve this answer













Would be incorrect to expect someone to pass an ILogger even if they do not intend to use it?





  • If I wouldn't want to pass an ILogger I would just pass (ILogger)null and your method would throw a NullReferenceException if an exception occurs. If you use C# 6 you could use the Null-conditional operator


  • If you keep the method signature like posted anyone who uses this method needs to pass an ILogger. To overcome this problem you can either make the ILogger argument optional or you implement an overloaded version of this method which doesn't take an ILogger argument.


  • Omitting braces althought they might be optional should be avoided.


  • Throwing throw new Exception(exception.Message) will destroy the stacktrace. It would be better to just throw.


  • By using the ctor of StreamReader which only takes a Stream as argument the default encoding is UTF8Encoding.



Implementing the mentioned points would lead to



public static class EmbeddedResourceUtility
{
public static string GetSqlQuery(string namespaceAndFileNameWithExtension)
{
return GetSqlQuery(namespaceAndFileNameWithExtension, (ILogger)null);
}
public static string GetSqlQuery(string namespaceAndFileNameWithExtension, ILogger logger)
{
try
{
using(var stream = typeof(EmbeddedResourceUtility).GetTypeInfo().Assembly.GetManifestResourceStream(namespaceAndFileNameWithExtension))
using(var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
catch(Exception exception)
{
logger?.Error($"Failed to read query file {namespaceAndFileNameWithExtension}. {Environment.NewLine}{exception.HResult}: {exception.Message}");
throw;
}
}
}






share|improve this answer












share|improve this answer



share|improve this answer










answered Dec 4 at 17:31









Heslacher

44.8k460155




44.8k460155












  • In C# 8 when they introduce nothing is null by default unless explicit, would that change your expectation?
    – Greg
    Dec 4 at 17:49










  • Well I did't inform me about C# 8. I usually only work with what is avaible.
    – Heslacher
    Dec 4 at 17:50










  • Oh, fair enough. I just know the paradigm for C# is about to shift. I know the feature is an opt-in, but in essence with the current way everything is null since a state has not been defined, in C# 8 nothing can be assigned as null unless the type explicitly allows it. So I was just curious if that would change your answer or you think this is still the best course of action? I am not trying to demean or dismiss your current answer, simply want to get the most information so I may make the best decision possible for implementation.
    – Greg
    Dec 4 at 17:52










  • Why not use an optional parameter on the ILogger instead of an overload?
    – IEatBagels
    Dec 4 at 18:22










  • Because using an overloaded method is ckearer from the caller side.
    – Heslacher
    Dec 4 at 18:32


















  • In C# 8 when they introduce nothing is null by default unless explicit, would that change your expectation?
    – Greg
    Dec 4 at 17:49










  • Well I did't inform me about C# 8. I usually only work with what is avaible.
    – Heslacher
    Dec 4 at 17:50










  • Oh, fair enough. I just know the paradigm for C# is about to shift. I know the feature is an opt-in, but in essence with the current way everything is null since a state has not been defined, in C# 8 nothing can be assigned as null unless the type explicitly allows it. So I was just curious if that would change your answer or you think this is still the best course of action? I am not trying to demean or dismiss your current answer, simply want to get the most information so I may make the best decision possible for implementation.
    – Greg
    Dec 4 at 17:52










  • Why not use an optional parameter on the ILogger instead of an overload?
    – IEatBagels
    Dec 4 at 18:22










  • Because using an overloaded method is ckearer from the caller side.
    – Heslacher
    Dec 4 at 18:32
















In C# 8 when they introduce nothing is null by default unless explicit, would that change your expectation?
– Greg
Dec 4 at 17:49




In C# 8 when they introduce nothing is null by default unless explicit, would that change your expectation?
– Greg
Dec 4 at 17:49












Well I did't inform me about C# 8. I usually only work with what is avaible.
– Heslacher
Dec 4 at 17:50




Well I did't inform me about C# 8. I usually only work with what is avaible.
– Heslacher
Dec 4 at 17:50












Oh, fair enough. I just know the paradigm for C# is about to shift. I know the feature is an opt-in, but in essence with the current way everything is null since a state has not been defined, in C# 8 nothing can be assigned as null unless the type explicitly allows it. So I was just curious if that would change your answer or you think this is still the best course of action? I am not trying to demean or dismiss your current answer, simply want to get the most information so I may make the best decision possible for implementation.
– Greg
Dec 4 at 17:52




Oh, fair enough. I just know the paradigm for C# is about to shift. I know the feature is an opt-in, but in essence with the current way everything is null since a state has not been defined, in C# 8 nothing can be assigned as null unless the type explicitly allows it. So I was just curious if that would change your answer or you think this is still the best course of action? I am not trying to demean or dismiss your current answer, simply want to get the most information so I may make the best decision possible for implementation.
– Greg
Dec 4 at 17:52












Why not use an optional parameter on the ILogger instead of an overload?
– IEatBagels
Dec 4 at 18:22




Why not use an optional parameter on the ILogger instead of an overload?
– IEatBagels
Dec 4 at 18:22












Because using an overloaded method is ckearer from the caller side.
– Heslacher
Dec 4 at 18:32




Because using an overloaded method is ckearer from the caller side.
– Heslacher
Dec 4 at 18:32


















draft saved

draft discarded




















































Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f209007%2freading-sql-query-from-a-resource-with-error-logging%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

mysqli_query(): Empty query in /home/lucindabrummitt/public_html/blog/wp-includes/wp-db.php on line 1924

How to change which sound is reproduced for terminal bell?

Can I use Tabulator js library in my java Spring + Thymeleaf project?