I have a code block that does not return the expected data values.
protected void Page_Load(object sender, EventArgs e)
{
corpEmployee.Employee editEmp = new corpEmployee.Employee();
editEmp.EmployeeID = PatientCustomerID.Value;
corpCustomerMgr.GetEmployeeRecord(editEmp);
tboxFirstName.Text = editEmp.EmpFirstName.ToString();
tboxLastName.Text = editEmp.EmpLastName.ToString();
tboxCity.Text = editEmp.EmpCity.ToString();
tboxAddress.Text = editEmp.EmpAddrLine1.ToString();
}
public static void GetEmployeeRecord(corpEmployee.Employee QueryData)
{
try
{
List<corpEmployee.Employee> empRecord = new List<corpEmployee.Employee>();
corpCustomerDAL.GetEmployeeData(empRecord, QueryData);
}
catch (Exception ex)
{
LogAppError(ex.ToString());
}
}
When corpCustomerDAL.GetEmployeeData(empRecord, QueryData); is executed, empRecord is returned with the Employee object with correct property values. However, when the code comes back to corpCustomerMgr.GetEmployeeRecord(editEmp); the employee object has null values.
How can I get the Employee object values back to the Page_Load routine?
You could either return the object back in the GetEmployeeRecord static method or you could include ref in front of your arguments so that you are passing the employee in as a reference instead of copying the variable.
I would recommend returning your data back vs using ref as your method name seems misleading, among other reasons.
Based on your comments, it looks like you are populating empRecord with the employee data you require. The simplest option is to return the populated record from GetEmployeeRecord:
public static corpEmployee.Employee GetEmployeeRecord(corpEmployee queryData)
{
List<corpEmployee.Employee> empRecord = new List<corpEmployee.Employee>();
corpCustomerDAL.GetEmployeeData(empRecord, QueryData);
return empRecord.Count == 0 ? null : empRecord[0]; //or empRecord.FirstOrDefault()
}
You should then change the start of your Page_Load handler to:
corpEmployee.Employee queryEmp = new corpEmployee.Employee();
queryEmp.EmployeeID = PatientCustomerID.Value;
corpeEmployee.Employee editEmp = corpCustomerMgr.GetEmployeeRecord(queryEmp);
Two immediate thoughts occur:
Your exception handling needs work. You shouldn't be catching Exception, and you shouldn't be silently swallowing exceptions at all. It could well be that an exception is being thrown, and that's why you're not getting the data.
You've got a Get*** method - that should be returning data. It appears you're expecting the results to be put into an object... that's a confusing way of getting data out of a method. It would be clearer if your method signature were something like:
public static Employee GetEmployeeRecord(string employeeId)
Most likely what's happening is that your employee object that you're passing in is being copied, and is destroyed when the function terminates.
To better illustrate, I've added some comments:
public static void GetEmployeeRecord(corpEmployee.Employee QueryData)
{
//QueryData is a newly created Employee here, and is NOT the same one that was passed in.
try
{
List<corpEmployee.Employee> empRecord = new List<corpEmployee.Employee>();
corpCustomerDAL.GetEmployeeData(empRecord, QueryData);//
//QueryData now contains the data you want your original object to contain
}
catch (Exception ex)
{
LogAppError(ex.ToString());
}
} //when this function terminates, QueryData ceases to exist.
In order to fix it, pass the employee by reference (use the ref keyword) instead of passing it by value, which is what you're doing right now.
Related
I am using mvc with Entity framework.
I have one method which is called on button click. method used to get the some value from db. And I am doing some calculation and subtracting the value based on my requirement. At the end I am updating this entity with latest changes.
If I don't have enough value in db for subtraction I want to show the error message to user "Enough value in db". its working fine for single user.
But if that method is called by different user at same time from different-different browser, then its not working.
I have tried with lock the Object or async await but not able to handle this situation. lock is not working on event which is fired by different-2 browser at same time.
Code:
public async Task SaveContainerRoutes(List<ContainerRouteVM> lstCRoute, int cid)
{
//my code
}
Lock code:
public ActionResult SaveContainerRoutes(List<ContainerRouteVM> lstCRoute, int cid)
{
try
{
ContainerRouteBL bl = new ContainerRouteBL();
lock (bl)
{
string note = bl.SaveContainerRoutes(lstCRoute, cid);
}
}
catch (Exception ex)
{
return Json(new { success = false, message = ex.Message });
}
}
Please help. Thanks in advance.
Declare this line in class level
private static Object thisLock = new Object();
use thislock in method
public async Task SaveContainerRoutes(List<ContainerRouteVM> lstCRoute, int cid)
{
lock(thisLock)
{
//place use code
}
}
I'm working on an application that embeds JSON within the page. Some simplified example:
public ViewResult Page(IEnumerable<LolCat> lolCats)
{
var json = new
{
localCats = ToJson(lolCats),
};
return View( json ); // this gets serialized somewhere in the ASP pipeline
}
IEnumerable<object> ToJson(IEnumerable<LolCat> lolCats)
{
foreach ( var lolCat in lolCats )
yield return new { name = lolCat.name };
}
The JSON gets automatically serialized somewhere down the line in the ASP.NET pipeline.
In this example assume that sometimes a NULL slips into lolCats, throwing an exception. Problem is that the ToJson function might be called at a lot of different places throughout the application.
How do I find out which call to ToJson was the one responsible for the exception? The call stack ends in the Serializer that is actually consuming this IEnumerable, and therefore you don't see the 'original stacktrace'.
One simple fix would be to call ToList() within Page. But I'm looking for a way that doesn't break the laziness of the method.
Due to the deferred nature, you will never get which call to ToJson() actually produced the exception. The collection was never inspected in the first place until it was first enumerated (when it was serialized).
You need to inject into your enumerator some info about what called it.
e.g.,
IEnumerable<object> ToJson(IEnumerable<LolCat> lolCats, string id)
{
try
{
foreach (var lolCat in lolCats)
yield return new { name = lolCat.name };
}
catch (Exception ex)
{
throw new Exception(id, ex); // use a more appropriate exception
}
}
Then it's just a matter of generating an id that could help identify the caller.
In my selectUser class I have:
public checkEmail(string email)
{
peopleTableAdapters.PeoplesTableAdapter p = new peopleTableAdapters.PeoplesTableAdapter();
return p.checkEmail(email);
}
In the client side code I have:
protected void Button1_Click(object sender, EventArgs e)
{
selectUser s = new selectUser();
try
{
s.checkEmail(email.Text);
}
catch(Exception e)
{
}
}
I am getting this error with the "return p.checkEmail(email);" the error is:
"Error 307 Since 'authentication.checkEmail(string)' returns void, a return keyword must not be followed by an object expression"
Does anyone understand what I am doing wrong?
I dont want to return any data because its not needed I just want to return something so it succeeds in the try statement.
This has no return type:
public checkEmail(string email)
I'm surprised this even compiles, but maybe the compiler assumes void when nothing is specified? I didn't know it did that. But either way, there's no return type. So this won't work:
return p.checkEmail(email);
If the method doesn't have a return type, then it can't return anything. You also don't do anything with the returned value:
s.checkEmail(email.Text);
So you don't need to return anything at all.
Furthermore, the error also suggests that p.checkEmail(email) itself doesn't return anything. So trying to return something which itself is a void return type is just compounding the problem.
Since nothing in this code returns any value, you can probably resolve this by simply not trying to return anything at all:
public void checkEmail(string email)
{
peopleTableAdapters.PeoplesTableAdapter p = new peopleTableAdapters.PeoplesTableAdapter();
p.checkEmail(email);
}
To exp[and on David's answer, if you don't want either checkEmail method to return a value, then you will need to throw an exception for an invalid e-mail at whatever point in the chain you are determining that it is or isn't valid.
This can be done using throw new ArgumentException() replacing ArgumentException with whatever exception type you feel is appropriate.
How do I know the log the last property that is null?
For example,
var a = "somevalue";
......
......
if(a == null)
{
Log.Error(MethodBase.GetCurrentMethod().Name + "Property : a is null");
//blah blah
}
Like how I use the reflection to get the current method name, there should be some means by which I can log the latest local variables (or a property or fields)
that is being compared ? I use, log4net by the way to log the errors.
1) Is there any method to achieve this or should we manually log it?
2) Is there any custom method that prints the class -> MethodName -> Propertyname(or FieldName) that is null?
Thanks for your time in advance.
As mentioned by #fsimonazzi, "a" would be a local variable.
That being said there is still no way to examine the current compare operation as in MSIL there is no formal concept of an IF block - only conditional jumps.
If you wanted to get really crazy with the reflection, you may be able to find the current executing instruction and look around near that for a variable, but even then, you will not find the name - only a reference - as names are only used prior to compilation.
Either way, reflection is not going to help you here.
Instead, try using Exceptions - specifically ArgumentNullException. This body of code would become:
void doStuff(string param1, int param2)
{
if (param == null)
throw new ArgumentNullException("param1", "param1 must not be null");
if (param2 < 0)
throw new ArgumentOutOfRangeException("param2", "param2 should be non-negative.");
//method body
}
then, when you call the method, you can catch the exception and log it - no matter what it may be.
public static void Main(string[] args)
{
try
{
doStuff(null, 3);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
Tools like FxCop can help make sure that you are properly validating each parameter.
Properties are actually implemented as methods, so reflection could help you there. If, for example, you were validating in a property and wanted to log the position automatically, you could.
private object _cachedObject = null;
public object CachedObject
{
get
{
if (_cachedObject == null)
{
log(MethodBase.GetCurrentMethod().Name, "creating cached object");
_cachedObject = createCachedObject();
}
return _cachedObject;
}
}
The .Net Framework 4.5 also brings with it a new attribute that can be used to replace the MethodBase.GetCurrentMethod().Name construct you are using to get the method name. See [CallerMemberNameAttribute][3].
Hi could you help me with this error?
Cannot access a disposed object.
Object name: 'DataContext accessed after Dispose.'.
in my GUI
private void InitializePage()
{
cbCategory.DataSource = stock.StockCategory.Get();
}
in Datamodel
public IEnumerable<StockCategory> Get()
{
using (leDataContext db = new leDataContext())
{
try
{
var r = from s in db.StockCategories
select s;
return r;
}
catch (Exception ex)
{
Logger.Error(typeof(StockCategory), ex.ToString());
throw;
}
}
}
You're disposing the DataContext but returning something that still depends on it.
Options:
Don't dispose the DataContext. I know this sounds weird, but guidance from the LINQ to SQL team (well, Matt Warren) has indicated that in most cases (i.e. if you're not doing anything out of the ordinary) disposal is not required
Call ToList() inside the Get() method's using block.
Note that using a query expression with just a degenerate query is reasonably pointless. (If this is within your own code, even the implicit Select(s => s) won't actually be useful.)
I would suggest changing your method to:
public IList<StockCategory> GetAllStockCategories()
{
using (leDataContext db = new leDataContext())
{
return db.StockCategories.ToList();
}
}
Because of lazy-loading there, the query isn't really executed on the linq statement line. It is executed when you loop over it, or in this case - when you run ToList on it.
When it is executed it must be inside the data context... which is not the case here. You can either return a List from the Get method or insert the setting of the cbCategory.DataSource value into the using (leDataContext...) scope.