I'm trying to return a value from a function. The function WcfProvider.MetalsPrices may throw an exception. I want to avoid it.
public IEnumerable<PriceOfMetal> GetPrice(int id, DateTime time)
{
bool condition = false;
DateTime timenew = time.AddDays(-1);
var allPrice = from c in db.PriceOfMetal
select c;
foreach (var i in allPrice)
{
if (i.Date.Date == timenew.Date && i.ListOfMetaL_Id==id)
{
condition = true;
}
}
try
{
if (condition == false)
{
var price = WcfProvider.MetalsPrices(id, time, time).Tables[0].AsEnumerable()
.Select(
a =>
new PriceOfMetal()
{
Date = a.Field<DateTime>("Date"),
ListOfMetaL_Id = a.Field<int>("MetalId"),
Value = a.Field<System.Double>("Price")
})
.ToList().Single();
db.PriceOfMetal.Add(price);
db.SaveChanges();
}
}
finally
{
var all = from c in db.PriceOfMetal select c;
return all;
}
I want to return the value of the block finally. Is it possible? I get an error.
You have to decide whether your function should return normally or abnormally if an exception occurs inside.
If abnormally (your caller will see the exception):
try {
// do stuff
return answer;
}
finally {
// cleanup stuff
}
If normally, you need to handle the exception:
try {
// do stuff
}
catch {
// recover stuff
}
// cleanup stuff
return answer;
You can never put a return statement in a finally block, because finally runs when there is an uncaught exception, and when your function ends (abnormally) due to uncaught exception, there is no return value.
you may need a pattern like this
try
{
return here
}
catch(Exception ex)
{
// Catch any error
// re throw if you choose,
// or you can return if you choose
return here
}
finally
{
// allways do whats here
}
You might want to read a couple of the pages around here : try-catch-finally (C# Reference)
Just to build on this a bit more, Imagine if we could return within a finally block
You could have a nasty piece of code like below, which would be confusing at best
try
{
return 10;
}
catch (Exception e)
{
return 20;
}
finally
{
return 30;
}
What would the compiler return?
I'm sorry to say this but your question is vague and hard to answer. Your code looks over complicated. Anyway it's holiday time. Maybe below will help you along. No guarantees though.
public IEnumerable<PriceOfMetal> GetPrice(int id, DateTime time)
{
DateTime timenew = time.AddDays(-1);
var allPrice = from c in db.PriceOfMetal
select c;
where c.Date.Date == timenew.Date
and c.ListOfMetal_Id == id
if (!allPrice.Any())
{
try
{
var price = WcfProvider.MetalsPrices(id, time, time).Tables[0].AsEnumerable()
.Select(a =>new PriceOfMetal
{
Date = a.Field<DateTime>("Date"),
ListOfMetaL_Id = a.Field<int>("MetalId"),
Value = a.Field<System.Double>("Price")
})
.ToList().Single();
db.PriceOfMetal.Add(price);
db.SaveChanges();
}
catch
{
// Eating exceptions like this is really poor. You should improve the design.
}
}
return db.PriceOfMetal;
}
Related
I'm trying a booking system, I want to put controls on the booking aspect. I want to use If and then cases. I want to control in such a way that if number of booking is 4, then it will throw an exception and stop inserting in the database.
public ApiResult<TimeModelExtended> SaveBooking(Booking booking)
{
AchimotaGCDb repo = new AchimotaGCDb();
var result = new ApiResult<TimeModelExtended>();
try
{
booking.PlayDate = getPlayDate(booking.RefCode);
Int16 nb = getNbBooked(booking.RefCode);
if (nb == 4)
{
Exception ex = new Exception();
result.Successfull = 0;
result.InternalError = ex.Message;
result.Error = "Booking slot is full";
}
else if (nb == 0)
{
booking.BookingStatus = 1;//Booked already
}
else
{
booking.BookingStatus = 0;//Reservation already
}
repo.Insert(booking);
result.Successfull = 1;
result = GetOneteeTime(booking.RefCode);
}
catch (Exception ex)
{
result.Successfull = 0;
result.InternalError = ex.Message;
result.Error = "Error from server";
}
finally
{
repo.Dispose();
}
return result;
}
help to solve that.
If you want to throw an exception, you need to really throw it:
if (nb == 4)
{
throw new Exception("Booking slot is full.");
}
But I don't think throwing an exception is a good idea. Throwing an exception and validation is a different thing.
Here is my suggestion:
if (nb == 4)
{
return result = new ApiResult<TimeModelExtended>()
{
Successfull = 0,
InternalError = "Other messages",
Error = ""Booking slot is full."
};
}
This will return as result message that nothing will continue unless you satisfy that nb != 4
Well, i have a Model with a collection saving changes in a loop structure
foreach(Customer objCustomer in listCustomer)
{
try
{
db.Customer.Add(objCustomer);
db.SaveChanges();
}
catch(Exception ex)
{
db.Entry(objCustomer).State = EntityState.Detach;
}
}
When it throws me any exception in a collection related to entity, the next ones keeps throwing exceptions.
I tried to detach the entire collection but it didn't work
foreach(Customer objCustomer in listCustomer)
{
try
{
db.Customer.Add(objCustomer);
db.SaveChanges();
}
catch(Exception ex)
{
for (int i = 0; i < objCustomer.Address; i++)
{
db.Entry(objCustomer.Address[i]).State = EntityState.Detach;
}
db.Entry(objCustomer).State = EntityState.Detach;
}
}
Any suggestion?
I don't know why but it works, i used like it refers in this post
EntityCollection Clear() and Remove() methods
objCustomer.Address.ToList().ForEach(x => db.Entry(x).State = EntityState.Detached);
It is almost as i did before using "for"
Thanks anyway everyone
i thought that the exception of second code maybe has been never occurred?
In addition,your code has any transaction ?
Try this? Warning not tested!
using(var db = new Context())
{
foreach(Customer objCustomer in listCustomer)
{
var exists = db.Customer.FirstOrDefault(x => x.CustomerID == objCustomer.CustomerID;
if( exists = null)
{
db.Customer.Add(objCustomer);
}
else
{
db.Entry(objCustomer).State = EntityState.Modified;
}
db.SaveChanges();
}
}
I am implementing some performance counters and I would like to know your opinion.
The question is should I declare response and return it outside try block or Is it OK to return it directly in the try block. Is there a difference and If so, what sample code is valid (if any).
With best regards, no9.
public string TestMethod(string document)
{
try
{
WebService ws = new WebService();
string response = null;
var startTime = PerformanceCounter.GetPerformanceCounterStartTimeHandle();
try
{
response = ws.InsertDocument(document);
}
catch (Exception ex)
{
PerformanceCounterHelper.Increment(PerformanceCounterEnum.NumberOfExternalWsCallsExceptionOnSec);
throw;
}
finally
{
PerformanceCounterHelper.IncrementPerformanceCounterByElapsedTime(PerformanceCounterEnum.DurationOfExternalCallsInSec, startTime);
PerformanceCounterHelper.Increment(PerformanceCounterEnum.NumberOfExternalCallsOnSec);
}
return response;
}
catch (Exception ex)
{
log.EventError(ex);
throw new DocumentGeneralException();
}
}
versus:
public string TestMethod(string document)
{
try
{
WebService ws = new WebService();
var startTime = PerformanceCounter.GetPerformanceCounterStartTimeHandle();
try
{
return ws.InsertDocument(document);
}
catch (Exception ex)
{
PerformanceCounterHelper.Increment(PerformanceCounterEnum.NumberOfExternalWsCallsExceptionOnSec);
throw;
}
finally
{
PerformanceCounterHelper.IncrementPerformanceCounterByElapsedTime(PerformanceCounterEnum.DurationOfExternalCallsInSec, startTime);
PerformanceCounterHelper.Increment(PerformanceCounterEnum.NumberOfExternalCallsOnSec);
}
}
catch (Exception ex)
{
log.EventError(ex);
throw new DocumentGeneralException();
}
}
As long as there isn't a difference because of not exiting (i.e. it runs additional/different code), then the code is identical. Actually, at the IL level it is illegal to ret from inside a try/catch, so one of the things the compiler does is to do exactly what you have done: introduce a local, assign the local inside the try/catch, then return that value when outside the try/catch.
Basically, go with whatever is simplest and most convenient to read. In your case, I would say "the first one".
public static string GetContentFromSPList(string cValueToFind)
{
string cValueFound = "";
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite("http://mysite"))
{
site.AllowUnsafeUpdates = true;
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPList oListAbout = web.Lists["About"];
SPQuery oQuery = new SPQuery();
oQuery.Query = "<OrderBy><FieldRef Name='myField' /></OrderBy><Where><Eq><FieldRef Name='myField' /><Value Type='Choice'>" + cValueToFind + "</Value></Eq></Where>";
SPListItemCollection collListItems = oListAbout.GetItems(oQuery);
foreach (SPListItem oListItem in collListItems)
{
cValueFound = (oListItem["FieldContents"] != null ? oListItem["FieldContents"].ToString() : "");
}
}
}
return cValueFound;
});
//return cValueFound;
}
catch (Exception ex)
{
}
finally
{
//return cValueFound;
}
}
Above is the piece of code.
Problem is not allowing to return the string. It keeps on giving compilation errors. I am sure I am doing something wrong!!.
Thanks.
I suppose it's something like:
"not all codes return value".
If so, just add
public static string GetContentFromSPList(string cValueToFind)
{
string cValueFound = "";
try
{
//code
}
catch (Exception ex)
{
}
finally
{
//some cleanup
}
return cValueFound ;
}
Put this at the bottom of your method because you don't return if an exception is caught.
catch (Exception ex)
{
return cValueFound;
}
finally
{
}
}
You cannot return from finally,
(control cannot leave the body from finally clause or something)
move the return either after finally or from catch
just add your return statement below finally block.
Dont return in try blck.
I have seen developers missing this lot of times. Reason this happens is because once you define the return type of a function, then function should have a return statement at all exit points. In this case a function should have a return statement one at the end of the try block and one inside a catch block or just one right at the bottom as Tigran has defined. If you do not intend to return any thing from the catch block then just return null;
public static string GetContentFromSPList(string cValueToFind)
{
string value= "";
try
{
//code
return value;
}
catch (Exception ex)
{
return null;
}
finally
{
//some cleanup
}
}
I'd like to get a list of all the Azure Table errors and figure out a clean way to handle them in a try...catch block.
For example, I'd like to not have to directly code and compare the InnerException message to String.Contains("The specified entity already exists"). What is the right way to trap these errors?
You could try looking at the values in the Response, rather that the inner exception. This is an example of one of my try catch blocks:
try {
return query.FirstOrDefault();
}
catch (System.Data.Services.Client.DataServiceQueryException ex)
{
if (ex.Response.StatusCode == (int)System.Net.HttpStatusCode.NotFound) {
return null;
}
throw;
}
Obviously this is just for the item doesn't exist error, but I'm sure you can expand on this concept by looking at the list of Azure error codes.
To handle errors while adding objects to a table you can use the following code:
try {
_context.AddObject(TableName, entityObject);
_context.SaveCangesWithRetries();
}
catch(DataServiceRequestException ex) {
ex.Response.Any(r => r.StatusCode == (int)System.Net.HttpStatusCode.Conflict)
throw;
}
As said in other answer you can find a list of TableStorage errors at: http://msdn.microsoft.com/en-us/library/dd179438.aspx
See my code here: http://blog.smarx.com/posts/testing-existence-of-a-windows-azure-blob. The pattern is to catch a StorageClientException, and then use the .ErrorCode property to match against the constants in StorageErrorCode.
Here is code that is provided in the Azure Table Whitepaper, but I'm not sure if this gives any value over smark's reply.
/*
From Azure table whitepaper
When an exception occurs, you can extract the sequence number (highlighted above) of the command that caused the transaction to fail as follows:
try
{
// ... save changes
}
catch (InvalidOperationException e)
{
DataServiceClientException dsce = e.InnerException as DataServiceClientException;
int? commandIndex;
string errorMessage;
ParseErrorDetails(dsce, out commandIndex, out errorMessage);
}
*/
-
void ParseErrorDetails( DataServiceClientException e, out string errorCode, out int? commandIndex, out string errorMessage)
{
GetErrorInformation(e.Message, out errorCode, out errorMessage);
commandIndex = null;
int indexOfSeparator = errorMessage.IndexOf(':');
if (indexOfSeparator > 0)
{
int temp;
if (Int32.TryParse(errorMessage.Substring(0, indexOfSeparator), out temp))
{
commandIndex = temp;
errorMessage = errorMessage.Substring(indexOfSeparator + 1);
}
}
}
void GetErrorInformation( string xmlErrorMessage, out string errorCode, out string message)
{
message = null;
errorCode = null;
XName xnErrorCode = XName.Get("code", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
XName xnMessage = XName.Get ( "message", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
using (StringReader reader = new StringReader(xmlErrorMessage))
{
XDocument xDocument = null;
try
{
xDocument = XDocument.Load(reader);
}
catch (XmlException)
{
// The XML could not be parsed. This could happen either because the connection
// could not be made to the server, or if the response did not contain the
// error details (for example, if the response status code was neither a failure
// nor a success, but a 3XX code such as NotModified.
return;
}
XElement errorCodeElement = xDocument.Descendants(xnErrorCode).FirstOrDefault();
if (errorCodeElement == null)
{
return;
}
errorCode = errorCodeElement.Value;
XElement messageElement = xDocument.Descendants(xnMessage).FirstOrDefault();
if (messageElement != null)
{
message = messageElement.Value;
}
}
}