I have Task.Factory.StartNew in C# code with args argument. I am not quite understand what value will arg be. So what value will args be and how the value is determined?
int count = table.Rows.Count;
Dictionary<int, string> expDic = new Dictionary<int, string>();
List<Task> taskList = new List<Task>();
for (int f = 0; f < count; f++)
{
DataRow tempformula = table.Rows[f];
string formulaSymbol = Convert.ToString(tempformula[Common.Systems.Sustainability.Constants.IndicatorFormula.Symbol]);
var t = Task.Factory.StartNew(new Action<object>((args) => {
int i = (int)args;
_sem.Wait();
StringBuilder expression = new StringBuilder(1024);
DataRow formula = table.Rows[i];
int indID = Convert.ToInt32(formula[Common.Systems.Sustainability.Constants.IndicatorFormula.IndicatorID]);
int sequence = Convert.ToInt32(formula[Common.Systems.Sustainability.Constants.IndicatorFormula.Sequence]);
int? referenceIndID = Common.Util.TryToConvertToInt32(formula, Common.Systems.Sustainability.Constants.IndicatorFormula.ReferenceIndicatorID);
decimal? val = Common.Util.TryToConvertToDecimal(formula, Common.Systems.Sustainability.Constants.IndicatorFormula.Value);
string symbol = Convert.ToString(formula[Common.Systems.Sustainability.Constants.IndicatorFormula.Symbol]);
string formulaOutputUnit = Convert.ToString(formula[Common.Systems.Sustainability.Constants.Indicator.Unit]);
if (!string.IsNullOrWhiteSpace(callerAcceptedUnit)) // added by HC on 2016-05-27
{
formulaOutputUnit = callerAcceptedUnit;
}
if (referenceIndID == null)
{
if (val == null)
{
DataSet indicator = GetIndicatorByIDFromCache(companyID, indID); // added by HC on 2017-05-12, for performance tuning.
//using (DataSet indicator = indicatorMgr.GetIndicatorByID(companyID, indID))
{
DataRow dr = indicator.Tables[0].Rows[0];
int indicatorType = Convert.ToInt32(dr[Common.Systems.Sustainability.Constants.Indicator.IndicatorType]);
if (indicatorType == (int)Common.Systems.Sustainability.Constants.IndicatorTypes.Currency
|| indicatorType == (int)Common.Systems.Sustainability.Constants.IndicatorTypes.Numeric)
{
decimal? total = SumTotal(companyID, indID, indicatorType, fromDate, toDate, formulaOutputUnit, callerIndicatorID, breakToMonthly, specifiedLocations, approvalStatus
, usageDataSet, interval
, indicatorIDsChain
, allowNull
);
expression.Append(total.ToString());
}
else if (symbol == "+"
|| symbol == "-"
|| symbol == "*"
|| symbol == "/")
{
expression.Append(symbol);
}
}
}
else
{
expression.Append(val.ToString());
}
}
else
{
string exp = GetExpression(companyID, fromDate, toDate, referenceIndID.Value.ToString(), indID.ToString(), formulaOutputUnit, breakToMonthly, specifiedLocations, approvalStatus
, usageDataSet, interval
, indicatorIDsChain
);
//expression.Append(exp);
using (DataTable dt = new DataTable())
{
// fault tolerance, for in-case users assigned symbol in the last line of formula
if (exp.EndsWith("+")
|| exp.EndsWith("-")
|| exp.EndsWith("*")
|| exp.EndsWith("/"))
{
exp = exp.Substring(0, exp.Length - 1);
}
object result = dt.Compute(exp, "");
expression.Append(result);
}
} // end if (referenceIndID == null)...
if ("IF".Equals(symbol, StringComparison.OrdinalIgnoreCase)
|| "THEN".Equals(symbol, StringComparison.OrdinalIgnoreCase)
|| "ELSE IF".Equals(symbol, StringComparison.OrdinalIgnoreCase)
|| "ELSE".Equals(symbol, StringComparison.OrdinalIgnoreCase)
|| ">".Equals(symbol, StringComparison.OrdinalIgnoreCase)
|| ">=".Equals(symbol, StringComparison.OrdinalIgnoreCase)
|| "=".Equals(symbol, StringComparison.OrdinalIgnoreCase)
|| "<=".Equals(symbol, StringComparison.OrdinalIgnoreCase)
|| "<".Equals(symbol, StringComparison.OrdinalIgnoreCase)
)
{
//--------------------------------------------------------
// Begin, added by HC on 2016-12-14
// as requested by CQS users, add "IF" statement for GRI indicators
string exp = HandleIFCondition(table, i, companyID, fromDate, toDate, indicatorIDs, callerIndicatorID, callerAcceptedUnit, breakToMonthly, specifiedLocations, approvalStatus, usageDataSet, interval, indicatorIDsChain);
expression.Append(exp);
// End, added by HC on 2016-12-14
//--------------------------------------------------------
// Find End if, added by Alex Poon on 20190306
int ifIndex = i;
for (var j = ifIndex; j < count; j++)
{
string endIfSymbol = Convert.ToString(table.Rows[j][Common.Systems.Sustainability.Constants.IndicatorFormula.Symbol]);
if ("END IF".Equals(endIfSymbol, StringComparison.OrdinalIgnoreCase))
{
i = j;
break;
}
}
}
else
{
if (!string.IsNullOrWhiteSpace(symbol)
&& expression.Length > 0 // added by HC on 2016-06-24
)
{
if (i + 1 >= count && symbol != ")")
{
// ignore the symbol
}
else if (expression.ToString() != symbol)
{
expression.Append(symbol);
}
}
else if (expression.Length == 0 && symbol == "(")
{
expression.Append(symbol);
}
if (symbol == "days")
{
// added by HC on 2017-01-23, a new requirements for calculating average values by days.
if (fromDate != null && toDate != null)
{
int days = toDate.Value.Subtract(fromDate.Value).Days + 1;
expression.Append(days);
}
else
{
expression.Append(1);
}
}
} // end if ("IF".Equals(symbol, StringComparison.OrdinalIgnoreCase)...
if (expDic != null && expression != null)
{
expDic.Add(i, expression.ToString());
}
_sem.Release();
}), f);
taskList.Add(t);
if ("IF".Equals(formulaSymbol, StringComparison.OrdinalIgnoreCase))
{
for (var j = f; j < count; j++)
{
string endIfSymbol = Convert.ToString(table.Rows[j][Common.Systems.Sustainability.Constants.IndicatorFormula.Symbol]);
if ("END IF".Equals(endIfSymbol, StringComparison.OrdinalIgnoreCase))
{
f = j;
break;
}
}
}
}
Task.WaitAll(taskList.ToArray());
List<int> keys = expDic.Keys.ToList();
keys.Sort();
string finalExpression = "";
foreach (var key in keys)
{
finalExpression += expDic[key];
}
return finalExpression;
}
args in your case is data that will be passed to a delegate specified by Action<object> parameter.
See docs.
When using overload of StartNew with Action<object>, you need to supply next argument of type object, which will be used in passed delegate.
Task.Factory.StartNew((o) => {/* 1 will be used here */}, 1, token, options, scheduler);
MSDN
The args argument (referred to as "state" in the documentation) is a parameter you need to specify when you call to Task.Factory.StartNew.
state (Object): An object containing data to be used by the action delegate.
Sample:
object param = somevalue;
Task.Factory.StartNew( (arg) =>
{ /* get the arg value here.*/
}, param);
Related
I'm currently trying to get my method to return an error message if a condition isn't valid. But I am uncertain how to go about this in a void method.
I have a method that looks like this
[HttpPost]
[ValidateAntiForgeryToken]
[Audit]
public void AddUnits(int so_id, int site_id, int[] addItem_id, int[] addItem_qty, int[] addItem_disc)
{
// Loop however many times is necessary to iterate through the largest array
for (int i = 0; i < Math.Max(Math.Max(addItem_id.Length, addComp_id.Length), addPart_id.Length); i++)
{
foreach (SODetails sod in db.SalesOrders.Find(so_id).SalesDetails)
{
if (i < addItem_id.Length && addItem_qty[i] != 0 && sod.ItemID == addItem_id[i] && addItem_id[i] != 365 && addItem_id[i] != 410)
{
sod.item_qty += addItem_qty[i];
sod.item_discount = addItem_disc[i];
addItem_id[i] = 0;
addItem_qty[i] = 0;
addItem_disc[i] = 0;
}
}
db.SaveChanges();
if(i < addItem_qty.Length && addItem_qty[i] != 0)
{
SODetails sODetails = new SODetails
{
SalesOrderID = so_id,
SiteID = site_id
};
// Only add a unit to the SODetails object if it's not null and has an id and quanitity specified
if(i < addItem_id.Length && addItem_id[i] != 0 && addItem_qty[i] != 0)
{
sODetails.ItemID = addItem_id[i];
sODetails.item_qty = addItem_qty[i];
sODetails.item_discount = addItem_disc[i];
}
if (sODetails.SiteID == 0)
sODetails.SiteID = null;
SalesOrder SO = db.SalesOrders.Find(sODetails.SalesOrderID);
SODetails salesOrderDetails = db.SODetails.Add(sODetails);
salesOrderDetails.SalesOrder = SO;
Item SO_Item = db.Items.Find(sODetails.ItemID);
Component SO_Component = db.Components.Find(sODetails.ComponentID);
Part SO_Part = db.Parts.Find(sODetails.PartID);
if (SO_Item != null)
{
if (SO.OrderType == SOType.OffSiteInventory && sODetails.InventorySite == "Main Inventory" && SO_Item.On_Hand < salesOrderDetails.item_qty)
{
ModelState.AddModelError(string.Empty, "Not enough stock in inventory");
//TempData["SalesOrderMessage"] = SO_Item.SalesOrderMessage;
}
sODetails.item_qty = sODetails.item_qty == null ? 0 : sODetails.item_qty;
int qtyOrdered = sODetails.item_qty == null ? 0 : (int)sODetails.item_qty;
salesOrderDetails.dynamicItem_qty = qtyOrdered;
if (SO_Item.SalesOrderMessage != null)
TempData["SalesOrderMessage"] = SO_Item.SalesOrderMessage;
}
db.SODetails.Add(sODetails);
}
}
db.SaveChanges();
}
Here is the part of the code where I am doing the validation check
if (SO.OrderType == SOType.OffSiteInventory && sODetails.InventorySite == "Main Inventory" && SO_Item.On_Hand < salesOrderDetails.item_qty)
{
ModelState.AddModelError(string.Empty, "Not enough stock in inventory");
//TempData["SalesOrderMessage"] = SO_Item.SalesOrderMessage;
}
If the condition is valid I want it to return to the screen with an error message showing up. But with the method being Void, I don't know how I can make it do this, or I don't know if it is even possible.
You could create a specific exception class that you can throw in your void function. You then handle this exception in the calling function.
class NotEnoughStockException : Exception {}
Then in your method:
If no stock ...
throw new NotEnoughStockException();
In the calling method
try {
call the stock method
} catch NotEnoughStockException {
whatever you want to do
}
Create a wrapper function that will call your stock function. You do try catch in that new function and return an error message. Your Ajax should call the new function.
I have C# code; when run to a line, it throws a System.NullReferenceException.
Here is the line of the code that cause the exception
if (expDic != null && expression != null)
{
expDic.Add(i, expression.ToString())
}
Here is the stack trace in the code
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
at Sustainability.BusinessObject.CalculationManager.<>c__DisplayClass18_0.<HandleFormulaInner>b__0(Object args) in D:\HK\Desktop\VSTS_2\Sustainability.BusinessObject\Classes\CalculationManager.cs:line 1410
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
I found that both expDic and expression are not null, however it throws a null reference exception.
Here is my code:
int count = table.Rows.Count;
Dictionary<int, string> expDic = new Dictionary<int, string>();
List<Task> taskList = new List<Task>();
for (int f = 0; f < count; f++)
{
DataRow tempformula = table.Rows[f];
string formulaSymbol = Convert.ToString(tempformula[Common.Systems.Sustainability.Constants.IndicatorFormula.Symbol]);
var t = Task.Factory.StartNew(new Action<object>((args) => {
int i = (int)args;
_sem.Wait();
StringBuilder expression = new StringBuilder(1024);
using (DataTable dt = new DataTable())
{
// symbol in the last line of formula
if (exp.EndsWith("+")
|| exp.EndsWith("-")
|| exp.EndsWith("*")
|| exp.EndsWith("/"))
{
exp = exp.Substring(0, exp.Length - 1);
}
object result = dt.Compute(exp, "");
expression.Append(result);
}
}
{
if (!string.IsNullOrWhiteSpace(symbol)
&& expression.Length > 0)
{
if (i + 1 >= count && symbol != ")")
{
}
else if (expression.ToString() != symbol)
{
expression.Append(symbol);
}
}
else if (expression.Length == 0 && symbol == "(")
{
expression.Append(symbol);
}
if (symbol == "days")
{
// calculating average values by days.
if (fromDate != null && toDate != null)
{
int days = toDate.Value.Subtract(fromDate.Value).Days + 1;
expression.Append(days);
}
else
{
expression.Append(1);
}
}
}
//Here is the code will have problem
if (expDic != null && expression != null)
{
expDic.Add(i, expression.ToString());
}
_sem.Release();
}), f);
taskList.Add(t);
}
I am doubting it is caused by the StartNew multithreading pattern,
so what is wrong in my code and how can I fix it?
I want to make my code short and simple using linq.
I have a list that contains leaveDates and every leaveDates contain number of leavelist.
Something like this:
{ leaves_date = {07-05-2018 18:30:00}, LeaveList = {System.Collections.Generic.List<TimeClock.Model.LeaveManagementModel>} }
{ leaves_date = {08-05-2018 18:30:00}, LeaveList = {System.Collections.Generic.List<TimeClock.Model.LeaveManagementModel>} }
{ leaves_date = {21-05-2018 18:30:00}, LeaveList = {System.Collections.Generic.List<TimeClock.Model.LeaveManagementModel>} }
leaveList contains UserId, LeaveType, Status fields
Now all I want is to count the number of leavedates per user who's status is 1 and leave type != 3
I have already tried using a for loop, but I want to do it with linq.
Here is my code with the for loop:
for (var i = 0; i < leavesresult.Count; i++) {
for (var a = 0; a < leavesresult[i].LeaveList.Count; a++) {
if (leavesresult[i].LeaveList[a].status == 1.ToString() && leavesresult[i].LeaveList[a].leave_type != 3.ToString()) {
var compair1 = leavesresult[i].LeaveList[a].user_id;
var compair2 = attendancelist.Any(z = >z.user_id == leavesresult[i].LeaveList[a].user_id);
if (attendancelist.Any(z = >z.user_id == leavesresult[i].LeaveList[a].user_id)) {
int index = attendancelist.FindIndex(y = >y.user_id == leavesresult[i].LeaveList[a].user_id);
if (leavesresult[i].LeaveList[a].check_halfday == 1) {
attendancelist[index].days = attendancelist[index].days
}
else {
attendancelist[index].days = attendancelist[index].days + 1;
}
}
else {
if (leavesresult[i].LeaveList[a].check_halfday == 1) {
attendancelist.Add(new AttendanceModel {
user_id = leavesresult[i].LeaveList[a].user_id,
days = 0.5
});
}
else {
attendancelist.Add(new AttendanceModel {
user_id = leavesresult[i].LeaveList[a].user_id,
days = 1
});
}
}
}
}
}
I could give you the query and you would learn nothing. Instead learn how to do this transformation yourself. The trick is to not try to do it all at once. Rather, we make a series of small, obviously correct transformations each one of which gets us closer to our goal.
Start by rewriting the inner for loop as a foreach:
for (var i = 0; i < leavesresult.Count; i++)
{
foreach (var leavelist in leavesresult[i].LeaveList)
{
if (leavelist.status == 1.ToString() && leavelist.leave_type != 3.ToString())
{
var compair1 = leavelist.user_id;
var compair2 = attendancelist.Any(z => z.user_id == leavelist.user_id);
if (attendancelist.Any(z => z.user_id == leavelist.user_id))
{
int index = attendancelist.FindIndex(y => y.user_id == leavelist.user_id);
if (leavelist.check_halfday == 1)
attendancelist[index].days = attendancelist[index].days
else
attendancelist[index].days = attendancelist[index].days + 1;
}
else
{
if (leavelist.check_halfday == 1)
attendancelist.Add(
new AttendanceModel {user_id = leavelist.user_id, days = 0.5});
else
attendancelist.Add(
new AttendanceModel {user_id = leavelist.user_id, days = 1});
}
}
}
}
Already your code is about 100 times easier to read with that change.
Now we notice a few things:
if (leavelist.status == 1.ToString() && leavelist.leave_type != 3.ToString())
That is a crazy way to write this check. Rewrite it into a sensible check.
var compair1 = leavelist.user_id;
var compair2 = attendancelist.Any(z => z.user_id == leavelist.user_id);
Neither of these variables are ever read, and their initializers are useless. Delete the second one. Rename the first one to user_id.
if (leavelist.check_halfday == 1)
attendancelist[index].days = attendancelist[index].days
else
attendancelist[index].days = attendancelist[index].days + 1;
The consequence makes no sense. Rewrite this.
OK, we now have
for (var i = 0; i < leavesresult.Count; i++)
{
foreach (var leavelist in leavesresult[i].LeaveList)
{
if (leavelist.status == "1" && leavelist.leave_type != "3")
{
var user_id= leavelist.user_id;
if (attendancelist.Any(z => z.user_id == leavelist.user_id))
{
int index = attendancelist.FindIndex(y => y.user_id == leavelist.user_id);
if (leavelist.check_halfday != 1)
attendancelist[index].days = attendancelist[index].days + 1;
}
else
{
if (leavelist.check_halfday == 1)
attendancelist.Add(
new AttendanceModel {user_id = leavelist.user_id, days = 0.5});
else
attendancelist.Add(
new AttendanceModel {user_id = leavelist.user_id, days = 1});
}
}
}
}
Use the helper variable throughout:
for (var i = 0; i < leavesresult.Count; i++)
{
foreach (var leavelist in leavesresult[i].LeaveList)
{
if (leavelist.status == "1" && leavelist.leave_type != "3")
{
var user_id = leavelist.user_id;
if (attendancelist.Any(z => z.user_id == user_id))
{
int index = attendancelist.FindIndex(y => y.user_id == user_id);
if (leavelist.check_halfday != 1)
attendancelist[index].days = attendancelist[index].days + 1;
}
else
{
if (leavelist.check_halfday == 1)
attendancelist.Add(
new AttendanceModel {user_id = user_id, days = 0.5});
else
attendancelist.Add(
new AttendanceModel {user_id = user_id, days = 1});
}
}
}
}
We realize that the Any and the FindIndex are doing the same thing. Eliminate one of them:
for (var i = 0; i < leavesresult.Count; i++)
{
foreach (var leavelist in leavesresult[i].LeaveList)
{
if (leavelist.status == "1" && leavelist.leave_type != "3")
{
var user_id = leavelist.user_id;
int index = attendancelist.FindIndex(y => y.user_id == user_id);
if (index != -1)
{
if (leavelist.check_halfday != 1)
attendancelist[index].days = attendancelist[index].days + 1;
}
else
{
if (leavelist.check_halfday == 1)
attendancelist.Add(
new AttendanceModel {user_id = user_id, days = 0.5});
else
attendancelist.Add(
new AttendanceModel {user_id = user_id, days = 1});
}
}
}
}
We notice that we are duplicating code in the final if-else. The only difference is days:
for (var i = 0; i < leavesresult.Count; i++)
{
foreach (var leavelist in leavesresult[i].LeaveList)
{
if (leavelist.status == "1" && leavelist.leave_type != "3")
{
var user_id = leavelist.user_id;
int index = attendancelist.FindIndex(y => y.user_id == user_id);
if (index != -1)
{
if (leavelist.check_halfday != 1)
attendancelist[index].days = attendancelist[index].days + 1;
}
else
{
double days = leavelist.check_halfday == 1 ? 0.5 : 1;
attendancelist.Add(new AttendanceModel {user_id = user_id, days = days});
}
}
}
}
Now your code is 1000x easier to read than it was before. Keep going! Rewrite the outer loop as a foreach:
foreach (var lr in leavesresult)
{
foreach (var leavelist in lr.LeaveList)
{
if (leavelist.status == "1" && leavelist.leave_type != "3")
{
var user_id = leavelist.user_id;
int index = attendancelist.FindIndex(y => y.user_id == user_id);
if (index != -1)
{
if (leavelist.check_halfday != 1)
attendancelist[index].days = attendancelist[index].days + 1;
}
else
{
double days = leavelist.check_halfday == 1 ? 0.5 : 1;
attendancelist.Add(new AttendanceModel {user_id = user_id, days = days});
}
}
}
}
And we notice a couple more things: we can put check_halfday into an explanatory variable, and eliminate days. And we can simplify the increment:
foreach (var lr in leavesresult)
{
foreach (var leavelist in lr.LeaveList)
{
if (leavelist.status == "1" && leavelist.leave_type != "3")
{
var user_id = leavelist.user_id;
int index = attendancelist.FindIndex(y => y.user_id == user_id);
bool halfday= leavelist.check_halfday == 1;
if (index != -1)
{
if (!halfday)
attendancelist[index].days += 1;
}
else
{
attendancelist.Add(new AttendanceModel {user_id = user_id, days = halfday ? 0.5 : 1});
}
}
}
}
Now we begin transforming this to a query. The key thing to understand is that mutations must not go in queries. Mutations only go into loops, never queries. Queries ask questions, they do not perform mutations.
You have a mutation of attendancelist, so that's got to stay in a loop. But we can move all the query logic out of the loop by recognizing that the nested foreach with a test inside the inner loop is equivalent to:
var query = from lr in leaveresult
from ll in lr.LeaveList
where ll.status == "1"
where ll.leave_type != "3"
select ll;
Excellent. Now we can use that in our foreach:
foreach(var ll in query)
{
var index = attendancelist.FindIndex(y => y.user_id == ll.user_id);
var halfday = ll.check_halfday == 1;
if (index != -1)
{
if (!halfday)
attendancelist[index].days += 1;
}
else
{
attendancelist.Add(
new AttendanceModel {user_id = ll.user_id, days = halfday? 0.5 : 1 });
}
}
Now that we have the loop in this extremely simple form, we notice that we can re-order the if to simplify it:
foreach(var ll in query)
{
var index = attendancelist.FindIndex(y => y.user_id == ll.user_id);
var halfday = ll.check_halfday == 1;
if (index == -1)
attendancelist.Add(
new AttendanceModel {user_id = ll.user_id, days = halfday? 0.5 : 1 });
else if (!halfday)
attendancelist[index].days += 1;
}
And we're done. All the computation is done by the query, all the mutations are done by the foreach, as it should be. And your loop body is now a single, extremely clear conditional statement.
This answer is to answer your question, which was how to convert an existing bunch of hard-to-read loops into an easy-to-read query. But it would be better still to write a query that clearly expressed the business logic you're trying to implement, and I don't know what that is. Create your LINQ queries so that they make it easy to understand what is happening at the business level.
In this case what I suspect you are doing is maintaining a per-user count of days, to be updated based on the leave lists. So let's write that!
// dict[user_id] is the accumulated leave.
var dict = new Dictionary<int, double>();
var query = from lr in leaveresult
from ll in lr.LeaveList
where ll.status == "1"
where ll.leave_type != "3"
select ll;
foreach(var ll in query)
{
var halfday = ll.check_halfday == 1;
if (!dict.ContainsKey(ll.user_id))
dict[ll.user_id] = halfday? 0.5 : 1;
else if (!halfday)
dict[ll.user_id] = dict[ll.user_id] + 1;
}
That seems like a nicer way to represent this than a list that you are constantly having to search.
Once we are at this point we can then recognize that what you are really doing is computing a per-user sum! The answer by JamieC shows that you can use the Aggregate helper method to compute a per-user sum.
But again, this is based on the assumption that you have built this whole mechanism to compute that sum. Again: design your code so that it clearly implements the business process in the jargon of that process. If what you're doing is computing that sum, boy, does that ever not show up in your original code. Strive to make it clearer what your code is doing.
This is basically 1 line of linq with a groupby, I'm not sure ill get it spot on with 1 try, but something along the lines of:
var attendancelist = leavesresult
.SelectMany(a => a.LeaveList) // flatten the list
.Where(a => a.status == "1" && a.type != "3") // pick the right items
.GroupBy(a => a.user_id) // group by users
.Select(g => new AttendanceModel(){ // project the model
user_id = g.Key,
days = g.Aggregate(0, (a,b) => a + (b.check_halfday == 1 ? 0.5 : 1))
})
.ToList();
Let me know any issues, and i'll try to fix as necessary.
edit1: Assuming AttendanceModel.days is an int you need to decide what to do as it is calculating a float.
Perhaps something like:
...
days = (int)Math.Ceiling(g.Aggregate(0, (a,b) => a + (b.check_halfday == 1 ? 0.5 : 1)))
...
Not a linq version but used foreach to simplify and make it more readable
var userLeaves = new Dictionary<int, double>();
foreach( var lr in leavesresult)
{
foreach (var leave in lr.LeaveList)
{
if (leave.Status == "1" && leave.LeaveType != "3")
{
var leaveDay = leave.check_halfday ==1 ? 0.5 : 1;
if (userLeaves.ContainsKey(leave.UserID))
userLeaves[leave.UserID] = userLeaves[leave.UserID] + leaveDay;
else
userLeaves.Add(leave.UserID, leaveDay);
}
}
}
i started with this! and i would like to avoid this
private IQueryable<Customer> FilterResult(string search, List<Customer> dtResult, List<string> columnFilters)
{
IQueryable<Customer> results = dtResult.AsQueryable();
results = results.Where(p => (search == null || (p.Name != null && p.Name.ToLower().Contains(search.ToLower()) || p.City != null && p.City.ToLower().Contains(search.ToLower())
&& (columnFilters[0] == null || (p.Name != null && p.Name.ToLower().Contains(columnFilters[0].ToLower())))
&& (columnFilters[1] == null || (p.City != null && p.City.ToLower().Contains(columnFilters[1].ToLower())))
);
return results;
}
by using reflection maybe.... because imagine i have 100 properties it would be easy to mess up ...so i tried this way i would like to use reflection to loop on all properties instead of making references to each of them(properties)
public IQueryable<Aangifte> FilterColumn<T>()
{
try
{
List<Aangifte> v = AangifteGetData.GetData(StartDate, EndDate);
List<Aangifte> v2 = new List<Aangifte>();
Aangifte Foo = new Aangifte();
List<string> propertEntity = new List<string>();
var search = Request.Form.GetValues("search[value]").FirstOrDefault();
int count = -1;
var results = v.AsQueryable();
List<string> columnName = new List<string>();
foreach (var prop in Foo.GetType().GetProperties())
{
var t = "";
if (!prop.Name.Contains("FORMAT"))
{
TVALUE = prop.GetValue(Foo, null);
t= prop.Name;
propertEntity.Add(t);
count++;
}
if (count < propertEntity.Count())
{
var newt = t;
var Z = Request.Form.GetValues("columns[" + count + "][search][value]").FirstOrDefault();
results = results.Where
(
p => (search == null || (t != null && t.ToLower().Contains(search.ToLower())))
&& (Request.Form.GetValues("columns[" + count + "][search][value]").FirstOrDefault() == null || (t != null && t.ToLower().Contains(Request.Form.GetValues("columns[" + count + "][search][value]").FirstOrDefault().ToLower())))
);
}
}
return results;
}
catch (Exception EX)
{
throw EX;
}
}
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Is there a string math evaluator in .NET?
Can C# parse mathematical expressions such as y=3*x + 3 into string? If so, ho?
I appreciate your help.
Here's a bit of code I wrote a while ago to parse infix (operator operand operator) equations.
There are some small classes and helper functions missing, but it should be fairly easy to implement them. If you need them or any help with it, let me know and I can upload them somewhere.
It's a basic implementation of Dijkstra's Shunting-yard algorithm
public Operand ExpressionTree
{
get;
private set;
}
private Stack<Operands.Operand> stack = new Stack<InfixParser.Operands.Operand>();
private Queue<Operands.Operand> outputQueue = new Queue<InfixParser.Operands.Operand>();
private void ParseFormulaString()
{
//Dijkstra's Shunting Yard Algorithm
Regex re = new Regex(#"([\+\-\*\(\)\^\/\ ])");
List<String> tokenList = re.Split(formulaString).Select(t => t.Trim()).Where(t => t != "").ToList();
for (int tokenNumber = 0; tokenNumber < tokenList.Count(); ++tokenNumber)
{
String token = tokenList[tokenNumber];
TokenClass tokenClass = GetTokenClass(token);
switch (tokenClass)
{
case TokenClass.Value:
outputQueue.Enqueue(new Value(token));
break;
case TokenClass.Function:
stack.Push(new Function(token, 1));
break;
case TokenClass.Operator:
if (token == "-" && (stack.Count == 0 || tokenList[tokenNumber - 1] == "("))
{
//Push unary operator 'Negative' to stack
stack.Push(new Negative());
break;
}
if (stack.Count > 0)
{
String stackTopToken = stack.Peek().Token;
if (GetTokenClass(stackTopToken) == TokenClass.Operator)
{
Associativity tokenAssociativity = GetOperatorAssociativity(token);
int tokenPrecedence = GetOperatorPrecedence(token);
int stackTopPrecedence = GetOperatorPrecedence(stackTopToken);
if (tokenAssociativity == Associativity.Left && tokenPrecedence <= stackTopPrecedence ||
tokenAssociativity == Associativity.Right && tokenPrecedence < stackTopPrecedence)
{
outputQueue.Enqueue(stack.Pop());
}
}
}
stack.Push(new BinaryOperator(token, Operator.OperatorNotation.Infix));
break;
case TokenClass.LeftParen:
stack.Push(new LeftParenthesis());
break;
case TokenClass.RightParen:
while (!(stack.Peek() is LeftParenthesis))
{
outputQueue.Enqueue(stack.Pop());
}
stack.Pop();
if (stack.Count > 0 && stack.Peek() is Function)
{
outputQueue.Enqueue(stack.Pop());
}
break;
}
if (tokenClass == TokenClass.Value || tokenClass == TokenClass.RightParen)
{
if (tokenNumber < tokenList.Count() - 1)
{
String nextToken = tokenList[tokenNumber + 1];
TokenClass nextTokenClass = GetTokenClass(nextToken);
if (nextTokenClass != TokenClass.Operator && nextTokenClass != TokenClass.RightParen)
{
tokenList.Insert(tokenNumber + 1, "*");
}
}
}
}
while (stack.Count > 0)
{
Operand operand = stack.Pop();
if (operand is LeftParenthesis || operand is RightParenthesis)
{
throw new ArgumentException("Mismatched parentheses");
}
outputQueue.Enqueue(operand);
}
String foo = String.Join(",", outputQueue.Select(t => t.Token).ToArray());
String bar = String.Join("", tokenList.ToArray());
Stack<Operand> expressionStack = new Stack<Operand>();
while (outputQueue.Count > 0)
{
Operand operand = outputQueue.Dequeue();
if (operand is Value)
{
expressionStack.Push(operand);
}
else
{
if (operand is BinaryOperator)
{
BinaryOperator op = (BinaryOperator)operand;
Operand rightOperand = expressionStack.Pop();
Operand leftOperand = expressionStack.Pop();
op.LeftOperand = leftOperand;
op.RightOperand = rightOperand;
}
else if (operand is UnaryOperator)
{
((UnaryOperator)operand).Operand = expressionStack.Pop();
}
else if (operand is Function)
{
Function function = (Function)operand;
for (int argNum = 0; argNum < function.NumArguments; ++argNum)
{
function.Arguments.Add(expressionStack.Pop());
}
}
expressionStack.Push(operand);
}
}
if (expressionStack.Count != 1)
{
throw new ArgumentException("Invalid formula");
}
ExpressionTree = expressionStack.Pop();
}
private TokenClass GetTokenClass(String token)
{
double tempValue;
if (double.TryParse(token, out tempValue) ||
token.Equals("R", StringComparison.CurrentCultureIgnoreCase) ||
token.Equals("S", StringComparison.CurrentCultureIgnoreCase))
{
return TokenClass.Value;
}
else if (token.Equals("sqrt", StringComparison.CurrentCultureIgnoreCase))
{
return TokenClass.Function;
}
else if (token == "(")
{
return TokenClass.LeftParen;
}
else if (token == ")")
{
return TokenClass.RightParen;
}
else if (binaryInfixOperators.Contains(token))
{
return TokenClass.Operator;
}
else
{
throw new ArgumentException("Invalid token");
}
}
private Associativity GetOperatorAssociativity(String token)
{
if (token == "^")
return Associativity.Right;
else
return Associativity.Left;
}
private int GetOperatorPrecedence(String token)
{
if (token == "+" || token == "-")
{
return 1;
}
else if (token == "*" || token == "/")
{
return 2;
}
else if (token == "^")
{
return 3;
}
else
{
throw new ArgumentException("Invalid token");
}
}
Possibly a duplicate of:
Is there a string math evaluator in .NET?
The short answer is no, for the long answer see the link. ( I recommend 'coppercoders' solution. )
Why don't you use Simple Math Parser or something is same?
link text
I took a cheap way out in a recent Silverlight application by scrubbing the string with a regex (for safety) and passing it to the JavaScript evaluator. It actually works very well but it's a hack I admit.
http://josheinstein.com/blog/index.php/2010/03/mathevalconverter