Sum 2 Columns in Linq - c#

I am trying to sum two columns that i have in LINQ. The following is my LINQ statement
var SigmaGood = from n in db.tbl_dppITHr
where n.ProductionHour >= SelectedDateDayShiftStart
where n.ProductionHour <= SelectedDateEnd
select n.part1 + n.part2
ViewData["GoodTotal"] = SigmaGood.Sum();
I am trying to get a total for part1 + part2;
When i try and test the result i dont get any value back i get a blank.
Anyone any ideas what i am doing incorrect?

I would say blank must mean the key you're storing the value against doesn't match the key you are reading/displaying. If it did you would at least see 0, not blank.
Do it in two steps and debug it.
var total = sigmaGood.Sum();
ViewData["GoodTotal"] = total; //breakpoint on this line and check value of total.
Or hardcode a test value, I bet it still comes out blank:
ViewData["GoodTotal"] = 1234;

Are you sure part1 and part2 has value?
var SigmaGood = from n in db.tbl_dppITHr
where n.ProductionHour >= SelectedDateDayShiftStart
where n.ProductionHour <= SelectedDateEnd
select n.part1 ?? 0 + n.part2 ?? 0
ViewData["GoodTotal"] = SigmaGood.Sum();

Try this:
var sum = db.tbl_dppITHr.Where(n => n.ProductionHour >= SelectedDateDayShiftStart
&& n.ProductionHour <= SelectedDateEnd)
.Sum(n => n.part1 + n.part2);

Are you certain you don't have a null in your input data? That may be rendered as a SQL SUM() which would go to null if any input value is null.

Related

I need to run command that in string

I have a problem with code.
I want to implement radix sort to numbers on c# by using ling.
I give as input string and give 0 in the start of the number:
foreach(string number in numbers){<br>
if(number.lenth > max_lenth) max_lenth = number.lenth;<br><br>
for(int i = 0; i < numbers.lenth; i++){<br>
while(numbers[i].length < max_lenth) numbers[i] = "0" + numbers[i];<br><br>
after this I need to order by each number in string, but it doesn't work with my loop:
var output = input.OrderBy(x => x[0]);
for (int i = 0; i < max_lenth; i++)
{
output = output.ThenBy(x => x[i]);
}
so I think to create a string that contain "input.OrderBy(x => x[0]);" and add "ThenBy(x => x[i]);"
while max_length - 1 and activate this string that will my result.
How can I implement it?
I can't use ling as a tag because its my first post
If I am understanding your question, you are looking for a solution to the problem you are trying to solve using Linq (by the way, the last letter is a Q, not a G - which is likely why you could not add the tag).
The rest of your question isn't quite clear to me. I've listed possible solutions based on various assumptions:
I am assuming your array is of type string[]. Example:
string[] values = new [] { "708", "4012" };
To sort by alpha-numeric order regardless of numeric value order:
var result = values.OrderBy(value => value);
To sort by numeric value, you can simply change the delegate used in the OrderBy clause assuming your values are small enough:
var result = values.OrderBy(value => Convert.ToInt32(value));
Let us assume though that your numbers are arbitrarily long, and you only want the values in the array as they are (without prepending zeros), and that you want them sorted in integer value order:
string[] values = new [] { "708", "4012" };
int maxLength = values.Max(value => value.Length);
string zerosPad = string
.Join(string.Empty, Enumerable.Repeat<string>("0", maxLength));
var resultEnumerable = values
.Select(value => new
{
ArrayValue = value,
SortValue = zerosPad.Substring(0, maxLength - value.Length) + value
}
)
.OrderBy(item => item.SortValue);
foreach(var result in resultEnumerable)
{
System.Console.WriteLine("{0}\t{1}", result.SortValue, result.ArrayValue);
}
The result of the above code would look like this:
0708 708
4012 4012
Hope this helps!
Try Array.Sort(x) or Array.Sort(x,StringComparer.InvariantCulture).

'accessibilityobject' threw an exception of type 'system.invalidoperationexception'

There are a lot of questions on SO about 'system.invalidoperationexception' but none of them have helped me figure this out.
I have a datatable (tab2tableExtra) that gets its values from another datatable (tab2table), which in turn gets is values from a database. tab2tableExtra only contains 4 rows and 8 columns and all its values (barring column [0]) are calculated from tab2table. Specifically two columns in tab2table are used to drive a for loop and those seem to be at the crux of the problem. These are MLevel and RLevel, which are shown in the code below.
Everything works perfectly when both the MLevel column and RLevel column have some non-null values. But if one of those columns is all nulls (DBNull.Value -which can happen on occasion), then something seems to go wrong. Interestingly, it doesn't actually cause the code to break, but it seems to mess with the calculated values in tab2tableExtra, as the entire table is null (except for column [0], which is just 1, 2, 3, 4).
Upon debugging, when either MLevel or RLevel (but not both) contains all null I see a 'system.invalidoperationexceptionfromthis`, as shown in the figure below. What causes the code to do is break out of the for loop after one iteration, and then not perform any of the rest of calculations.
This message comes from the following code:
// Add values to tab2tableExtra
// Add Levels columns
DataRow row = tab2tableExtra.NewRow();
for (int i = 1; i < 5; i++)
{
row = tab2tableExtra.NewRow();
row["Level"] = i;
tab2tableExtra.Rows.Add(row);
}
// Add participation rate column values
DataRow dr = tab2tableExtra.Rows[0];
int rowCount = tab2table.Rows.Count;
/*int countnumM = tab2table.AsEnumerable().Where(x => int.Parse(x["MLevel"].ToString()) == 1 ||
int.Parse(x["MLevel"].ToString()) == 2 || int.Parse(x["MLevel"].ToString()) == 3 ||
int.Parse(x["MLevel"].ToString()) == 4).ToList().Count;*/
int countnumM = tab2table.AsEnumerable().Select(x => int.TryParse(x["MLevel"].ToString(), out var d) ? d : (int?)null).Where(x => x >= 1 && x <= 4).Count();
int countnumRW = tab2table.AsEnumerable().Select(x => int.TryParse(x["RLevel"].ToString(), out var d) ? d : (int?)null).Where(x => x >= 1 && x <= 4).Count();
/*int countnumRW = tab2table.AsEnumerable().Where(x => int.Parse(x["RLevel"].ToString()) == 1 || int.Parse(x["RLevel"].ToString()) == 2 ||
int.Parse(x["RLevel"].ToString()) == 3 || int.Parse(x["RLevel"].ToString()) == 4).ToList().Count;*/
for (int i = 1; i < 5; i++)
{
if (countnumM > 0)
{
float levelPercM = Convert.ToInt32(tab2table.Compute("COUNT(MLevel)", "MLevel =" + i.ToString()));
tab2tableExtra.Rows[i - 1][1] = Math.Round(100 * levelPercM / countnumM, 2);
}
else
tab2tableExtra.Rows[i - 1][1] = null;
if (countnumRW > 0)
{
decimal levelPercRW = Convert.ToDecimal(tab2table.Compute("COUNT([RLevel])", "RLevel =" + i.ToString()));
tab2tableExtra.Rows[i - 1][2] = Math.Round(100 * levelPercRW / countnumRW, 2);
}
else
tab2tableExtra.Rows[i - 1][2] = null;
}
// Add the rest of the column values that only require a single number
tab2tableExtra.Rows[0][3] = rowCount;
if (countnumM > 0)
tab2tableExtra.Rows[0][4] = 100*countnumM/rowCount;
else
tab2tableExtra.Rows[0][4] = null;
if (countnumRW > 0)
tab2tableExtra.Rows[0][5] = 100*countnumRW/rowCount;
else
tab2tableExtra.Rows[0][5] = null;
decimal RWavg = Convert.ToDecimal(tab2table.Compute("AVG([ROverall])", ""));
decimal Mavg = Convert.ToDecimal(tab2table.Compute("AVG([MOverall])", ""));
tab2tableExtra.Rows[0][6] = RWavg;
tab2tableExtra.Rows[0][7] = Mavg;
For reference, when I debug with a tab2table that has at least one non-null value in both MLevel and RLevel, I see this:
If anyone knows how to solve this, or even just why this happening, it would be very useful.
In these lines of code:
int countnumM = tab2table.AsEnumerable()
.Select(x => int.TryParse(x["MLevel"].ToString(), out var d) ? d : (int?)null)
.Where(x => x >= 1 && x <= 4).Count();
int countnumRW = tab2table.AsEnumerable()
.Select(x => int.TryParse(x["RLevel"].ToString(), out var d) ? d : (int?)null)
.Where(x => x >= 1 && x <= 4).Count();
You're using int.TryParse to read the value of x["MLevel"].
If x["MLevel"].ToString() doesn't return a string that can be parsed as an int then int.TryParse will return false. That includes if x is DBNull.Value. That won't get parsed as an int.
Then, after the TryParse, you have this: ? d : (int?)null)
In other words, if TryParse returned true - it was able to parse, then you're selecting d - the parsed value.
But if it couldn't parse the value - TryParse returned false - then you're returning (int?)null - which is effectively null.
At the end you're filtering the results for values between 1 and 4, and then counting the number of those results:
.Where(x => x >= 1 && x <= 4).Count();
Just as you described, if there were some non-null values then that Count will probably return one or more. But if there are all null values then .Count will equal 0, because no values were between 1 and 4.
In that case countnumM and/or countnumRW would equal 0.
Further down you're setting some additional values if countnumM > 0 and if countnumRW > 0. But they're not greater than 0. They are 0. If they are 0, you're code will do what you expect:
for (int i = 1; i < 5; i++)
{
if (countnumM > 0) // this is == 0
{
float levelPercM = Convert.ToInt32(tab2table.Compute("COUNT(MLevel)", "MLevel =" + i.ToString()));
tab2tableExtra.Rows[i - 1][1] = Math.Round(100 * levelPercM / countnumM, 2);
}
else // This is what's happening
tab2tableExtra.Rows[i - 1][1] = null;
if (countnumRW > 0) // this is == 0
{
decimal levelPercRW = Convert.ToDecimal(tab2table.Compute("COUNT([RLevel])", "RLevel =" + i.ToString()));
tab2tableExtra.Rows[i - 1][2] = Math.Round(100 * levelPercRW / countnumRW, 2);
}
else // This is what's happening
tab2tableExtra.Rows[i - 1][2] = null;
}
To clarify around the other part - the InvalidOperationException:
When you're in the debugger and you inspect the properties of a variable, it's going to try to display the value of each property. That's what the list of properties is in your image - it's all the properties of this.
Some of them might be properties you don't use or care about, but when it tries to read the properties so it can show them to you, the property throws an exception. So now instead of a property value it shows you the exception it got when trying to read the property.
This is understandably confusing because you're debugging trying to figure out what's going on in your code, and then you see exceptions. You wonder if they might be related to the problem.
Generally they aren't because if your code throws an exception then it stops execution of your code. That's an exception you would need to figure out. But if it doesn't stop your code from running and it's a property on some framework class (like Form.AccessibilityObject) that you aren't even using, then you can usually ignore it.
As Scott Hannen said, the problem here has nothing to do with the 'system.invalidoperationexception' exception. For anyone who comes across a similar problem, the actually issue was with the null.
It turns out, in C# datatables cannot handle null values. And instead of giving an error, it simply just stops filling the datatable once it encounters one. In order to fix this, one has to make sure to use DBNull.Value. So in the code in question, for example, changing all null to DBNull.Value will fix the issue.

Accessing and Querying Event Log in Windows

I was wondering how I could reach event Log entries. I have a client server application and it executes without problems. What i am looking for is all instances of log with the id of 1149. This log is of the remote connection entries. I have taken a piece of code, here it is.
string logType = "System";
string str = "";
EventLog ev = new EventLog(logType, System.Environment.MachineName);
int LastLogToShow = ev.Entries.Count;
if (LastLogToShow <= 0)
Console.WriteLine("No Event Logs in the Log :" + logType);
// Read the last 2 records in the specified log.
int i;
for (i = ev.Entries.Count; i >= LastLogToShow - 1000 ; i--)
{
EventLogEntry CurrentEntry = ev.Entries[i];
if (CurrentEntry.InstanceId == 1149)
{
str += "Event type: " + CurrentEntry.EntryType.ToString() + "\n" +
"Event Message: " + CurrentEntry.Message + CurrentEntry + "\n" +
"Event Time: " + CurrentEntry.TimeGenerated.ToShortTimeString() + "\n" +
"Event : " + CurrentEntry.UserName +"\n" +"\n";
}
}
ev.Close();
return str;
The thing is I get the 42567 index is out of bounds exception everytime. I also dont know if it will work after that, so questions may follow.
EDIT:
Indeed, the problem was me reaching out of the eventlog with my index like you guys said. Using this line for the loop solved my problem here and I am able to reach the eventlog now, if anyone is looking around, this solution worked for me, so thank you all so much.
for (i = ev.Entries.Count - 1; i >= 0; i--)
This for (i = ev.Entries.Count; i >= LastLogToShow - 1000 ; i--) is causing your error. I don't really get what you're trying to do here. For one if you have less than 1000 entries, your i can be negative. When you use a negative value as the index of an array you will get "index is out of bounds exception". When you are trying to process only the last 2 records (as your commentary above the for-loop suggests) you should just use this:
for (i = ev.Entries.Count - 1; i >= ev.Entries.Count - 2; i--)
Of course you will still have to check if there is more than 2 entries because if there are 0 entries, the code will still go into the for-loop and try to access the array with negative indexes:
if(ev.Entries.Count < 2)
return str;
for (i = ev.Entries.Count - 1; i >= ev.Entries.Count - 2; i--)
Edit: Also just noticed even if there are more than 1000 records, when you go into the for-loop for the first time you will have ev.Entries[ev.Entries.Count]. Since array-indexes are zero-based you have to substract 1 from the count to get the last element of an array.
I highly suggest you use C# Linq for this.
Add this namespace
using System.Linq;
Linq is very similar to SQL in how it works with the data. In your case:
List<string> stringLogs =
ev.Entries
.Where(t => t.InstanceId == 1149)
.Select(t => GenerateLogString(t))
.ToList();
public string GenerateLogString(EventLogEntry CurrentEntry)
{
return
string.Format("Event type: {0}\nEvent Message: {1}\nEvent Time: {2}\nEvent: {3}\n",
CurrentEntry.EntryType.ToString(),
CurrentEntry.Message + CurrentEntry,
CurrentEntry.TimeGenerated.ToShortTimeString(),
CurrentEntry.UserName)
}
You can then convert the string logs into a single string, like you have there.
string str = string.Join("/n", stringLogs);
If you want to select the top 2 logs (as your commentary suggests), add a .Take(2) to the query, like below.
List<string> stringLogs =
ev.Entries
.Where(t => t.InstanceId == 1149)
.Take(2)
.Select(t => GenerateLogString(t))
.ToList();
You just need to equal i to ev.Entries.Count -1.
i = (ev.Entries.Count -1)

"value must be a number less than infinity" error when the variable is a integer

I'm not sure if I should ask this, but the details might help on finding out :p
I have a table like this
And I'm using compute to get the interval where a double variable stands in the Variavel column
double value = 6;
double max Convert.ToDouble(DataAccess.Instance.tabela1vert0caso1W.Compute("MIN(Variavel)", "Variavel >= " + value.ToString(CultureInfo.InvariantCulture)));
double min = Convert.ToDouble(DataAccess.Instance.tabela1vert0caso1W.Compute("MAX(Variavel)", "Variavel <= " + value.ToString(CultureInfo.InvariantCulture)));
The problem here is that I get the inifity error on the double min line, however it only happens when I'm between 5 and 15, if I choose any other value, i get the program to work properly.
Any hint?
By the way I checked the value of value just before the lines, and it's still 6.
I'm not sure what the actual problem is, however, you could always use Linq-To-DataTable which is more powerful (supports the whole .NET framework) and also more readable:
var variavels = DataAccess.Instance.tabela1vert0caso1W.AsEnumerable()
.Select(row => row.Field<int>("Variavel"));
double max = variavels.Where(d => d >= value).Max();
double min = variavels.Where(d => d <= value).Min();
Its possible for the compute method to return DBNull.Value. It seems unclear when if at all the Max() function will return this, but possibly your select returns 0 rows?
I suggest you add a check for DBNull.Value and set min to value when it occurs

Comparing values of a column C# list all together

I have a C# list named AxiomSubset with 6 columns in which there are several rows of data and I would like to check if all the values of a particular column in the list are equal if they are equal then it should return true and go to the next column and check their equality and so on.
For Example, I have the following rows of data in the list
CC Mon str stg rate units
HP 15-Mar 4.0800 4
HP 15-Feb 4.0800 4
HP 15-Jan 4.0800 4
LN 15-Mar 3.25 Put 0.0500 50
LN 15-Feb 3.25 Put 0.0500 50
LN 15-Jan 3.25 Put 0.0500 50
LN 15-Mar 3.50 Put 0.1000 50
LN 15-Feb 3.50 Put 0.1000 50
LN 15-Jan 3.50 Put 0.1000 50
In the above data when checking the equality for column CC it should return false as they are all not equal
I tried doing it as follows which compares one row with the earlier row which doesn't give expected results obviously
for (int i = 0; i < AxiomSubSet.Count; i++)
{
if (AxiomSubSet[i].CC.ToString() == AxiomSubSet[i + 1].CC.ToString())
{
result = true;
if (AxiomSubSet[i].term.ToString() == AxiomSubSet[i + 1].ToString())
{
//So On
}
}
}
Above code compares two values at a time and will return true if they are equal without considering other values which is something unwanted.
Is there a better way to do it?
You can do something like this for each column.
if((AxiomSubSet.Select(x => x.CC).Distinct().ToList()).Count > 1)
You can change your IComparer as you would like but I am giving you here as a quick example:
public class AxiomSubset : IComparer<AxiomSubset>
{
public int Compare(AxiomSubset x, AxiomSubset y)
{
if (x.CC.CompareTo(y.CC) != 0)
{
return x.CC.CompareTo(y.CC);
}
else if (x.term.CompareTo(y.term) != 0)
{
return x.term.CompareTo(y.term);
}
else
{
return 0;
}
}
}
I would think about using linq. Take the first value to find all matching values in the list, if the counts match between the lists all values are the same.
var listMatch = AxiomSubSet.Where(x => x.CC == AxiomSubSet[0].CC).Select(x => x);
result = listMatch.Count == AxiomSubSet.Count;
or more concise
if (AxiomSubSet.Where(x => x.CC == AxiomSubSet[0].CC).Select(x => x).Count == AxiomSubSet.Count)
from a in AxiomSubSet
group a by a.CC into g
select g.Count
You can group by the column, if the count is more than 1 you know there are different values. You can convert that to lambda, I prefer that syntax for readability.

Categories