sum column with linq to sql - c#

I have a DataView in which I would like to sum a column called "Amount"
Now I know I can iterate thru the columns and get the sum but I was wondering if is possible using Linq to Sql?
String sum = Linq to Sql stuff here (doesn't have to be a string, can be any type)
Thanks,
rodchar

Assuming the Amount column is a double (could be another type)
double sum = Table.Select(t => t.Amount ?? 0).Sum();
Or
double sum = Table.Sum(t => t.Amount ?? 0).Sum();
Using the null coelescing operator will give you a default of 0 if t.Amount is null.

we can do this using the entity framework var sum=dbcontext.table.select(a=>a.columnname).Sum();

Excuse me for dataContext call syntax...
var sum = dataContext.Sum(x => x.Amount);
If you want to sum strings, you may want to use
var sum = string.Join(", ", dataContext.Select(x => x.StringColumn).ToArray());
Hope this works.

Related

using dt.AsEnumerable().Sum for columns having string/null value

I an using following way to get total of a column from a datatable
string total = dt.AsEnumerable().Sum(x => x.Field<decimal>("col1")).ToString();
This works fine when all the values of col1 are number.
My question is- lets consider if any one value of col1 is string or null or anything else other than number, the above code will throw error obviously.
Is there any way to check whether the value is number and use '0' instead if value is not number.
I tried -
string total = dt.AsEnumerable().Sum(x => x.Field<decimal>("col1") is int ? x.Field<decimal>("col1") : 0).ToString();
but not sure if it the correct way.
Please help
If it's not a decimal but a string you would even get a InvalidCastException in the Field<T> method. So you have to know what type it is.
I assume that Col1 can be null, Field<T> supports nullable types:
decimal total = dt.AsEnumerable()
.Sum(r => r.Field<decimal?>("Col1") ?? 0);
or without replacing null with 0:
decimal? total = dt.AsEnumerable()
.Sum(r => r.Field<decimal?>("Col1")); // use total.HasValue and total.Value
Presuming string, you could use decimal.TryParse:
decimal d = 0;
decimal total = dt.AsEnumerable()
.Where(r => decimal.TryParse(r.Field<string>("Col1"), out d))
.Sum(r => d);
If you don't know what type it is you could use object.ToString:
decimal total = dt.AsEnumerable()
.Where(r => !r.IsNull("Col1") && decimal.TryParse(r["Col1"].ToString(), out d))
.Sum(r => d);
Apart from that, why do you store the converted number again in a string variable?

Sorting a DataRow Collection with a value closest to certain value

I have a DataRow[] consisting of 3 columns I want to sort the collection based on a columns value closest to some given value. i.e. Abs(column - given_value).
Can somebody please give me some idea how I can accomplish that ?
You could try this:
var results = collection.OrderBy(
row => Math.Abs(Convert.ToInt32(row["ColumnName"]) - given_value));
Or Convert.ToDouble, i don't know the type you are using.
Note: Is the column allows null, you should check it for DBNULL first before Converting.
You can use Linq and Math.Abs
IEnumerable<DataRow> orderedRows = rows
.OrderBy(r => Math.Abs(r.Field<int>("column") - given_value));
If you want to create a new array: rows = orderedRows.ToArray();
Replace r.Field<int> with the actual type. If it's just a string you need to convert it first:
IEnumerable<DataRow> orderedRows = rows
.OrderBy(r => Math.Abs(int.Parse(r.Field<string>("column")) - given_value));

How to load just the last record from entity with LINQ?

I want to fetch value of field named "Gram" from the last record and put its value into a variable, without using any conditions.
First I tried
int value = int.Parse(Entity.TblGold.LastOrDefault().Gram.ToString());
Second I tried
int value = int.Parse(Entity.TblGold.Select(p => p.Gram).Last().ToString());
I just receive this exception:
LINQ to Entities does not recognize the method 'DataModel.TblGold LastOrDefault[TblGold](System.Linq.IQueryable``1[DataModel.TblGold])' method, and this method cannot be translated into a store expression.
Last or LastOrDefault are not supported in LINQ to Entities. You can either iterate your query using ToList or ToArray and then apply Last or you can order by descending and then use the First like:
int value = int.Parse(Entity.TblGold
.OrderByDescending(p => p.Gram)
.Select(r => r.Gram)
.First().ToString());
You can't do it in one query, but you can do it in two.
var countOfRows = tbl.Count();
var lastRow = tbl.Skip(countOfRows - 1).FirstOrDefault();
If you have an incremental id:
int idx = tb.Max(i => i.Id);
var row = tb.FirstOrDefault(i => i.Id == idx);
It is your answer and you don't need to convert.
int value = Entity.TblGold.OrderByDescending(p => p.Id).First().Gram;
You can use order by 1 == 1 and it works
var countOfRows = tbl.Count();
var lastRow = tbl.OrderBy(c => 1 == 1).Skip(countOfRows - 1).FirstOrDefault();

Generic List Object OrderBy dynamic Column name

I am trying to sort data which is from Generic List object.
By using below code, I can sort my data according to Title column.
But what I would like to do is I would like to sort data according to parameter value called sidx.
public ActionResult ListingGridData(string sidx, string sord, int page, int rows)
{
int currentPage = Convert.ToInt32(page) - 1;
int totalRecords = 0;
var SeminarList = (List<Seminar>)null;
if(sord.Equals("asc"))
SeminarList = seminarRepository.AllSeminarList().Seminar_Masters
.OrderBy(x => x.Title )
.Skip(currentPage * rows)
.Take(rows)
.ToList();
else
SeminarList = seminarRepository.AllSeminarList().Seminar_Masters
.OrderByDescending(x => x.Title)
.Skip(currentPage * rows)
.Take(rows)
.ToList();
totalRecords = seminarRepository.AllSeminarList().Seminar_Masters.Count;
var totalPages = (int)Math.Ceiling((float)totalRecords / (float)rows);
....
}
So I have modified my code like that, but it does not work.
It does not sort as I have expected.
SeminarList = seminarRepository.AllSeminarList().Seminar_Masters
.OrderBy(x => sidx)
.Skip(currentPage * rows)
.Take(rows)
.ToList();
The object which I now use is pure List object, not IQueryable object.
As for sorting purpose, I don't want to go back to SQL select statement, I would like to sort data at Controller layer.
Please let me get any suggestions.
You must order by a column that is in your result set. If the sidx is not part of your resultset then it is like ordering by a constant. Thus every row will be the same and it will not REALLY be ordered. Let's assume sidx's value is 10, then it would be like ordering this resultset:
Row 1 | 10
Row 2 | 10
Row 3 | 10
...
You can see how the ordering would be pointless
What you need to do is add sidx to your result set if that is what you want:
SeminarList = seminarRepository.AllSeminarList().Seminar_Masters
.OrderBy(x => x.sidx)
.Skip(currentPage * rows)
.Take(rows)
.ToList();
See answer for dynamic where and orderby using some helper
methods here
where can I find a good example of using linq & lambda expressions to generate dynamic where and orderby sql?
So you're saying that the calling method will provide a Property name via the sidx parameter, and you want to sort by that property?
The easiest way is to use the Dynamic LINQ library. Another option would be to use reflection to find the property you're looking for, then build a lambda expression from it.

LINQ to Entities does not recognize the method 'System.String ToString()' method when converting Nullable DateTime

I'm trying to get the Day of the week from a Nullable DateTime and then Joining on a list of days.
My solution was to convert it to a DateTime first, but Linq to Entities doesn't like it.
LIST is an IEnumerable<string>
suggestions?
var result = from X in model.X
where X.StartDate.HasValue
join item in LIST on
Convert.ToDateTime(X.StartDate).DayOfWeek.ToString() equals item
select X;
Converting to a methods chain is no help:
var result = model.X.Where(x => x.StartDate.HasValue).Join(LIST,x => Convert.ToDateTime(x.StartDate).DayOfWeek.ToString(), item => item, (x, item) => x);
var result = from X in model.X
where X.StartDate.HasValue &&
List.Contains(SqlFunctions.DatePart("weekday", X.StartDate))
select X;
weekday returns an int so you should have a list of integers not strings
this will work if you use .ToList() before the convertion take place.
Entity 4.0 Casting Value As DateTime
var result = model.X.Where(x => x.StartDate.HasValue).ToList().Join(LIST,x => Convert.ToDateTime(x.StartDate).DayOfWeek.ToString(), item => item, (x, item) => x);
.ToString() is not supported by Linq-To-Entities, as are a number of other extension methods.
The short (and probably inaccurate to some degree) reason is that the .ToString() in the context above is sent to Sql Server to run in a query. Sql Server has no idea what .ToString() is, and so it fails when Sql Server's query parser tries to execute it.
also, FYI
http://msdn.microsoft.com/en-us/library/bb738550.aspx
EDIT: Do not use this code. It has been left here to show you what will not work and so you can see Chris' reasons why and how to solve.
Untested:
var result = from X in model.X
where ((X.StartDate != null) && X.StartDate.HasValue)
join item in LIST on
Convert.ToDateTime(X.StartDate).DayOfWeek.ToString() equals item
select X;
If you have declared StartDate as a Nullable field, it follows you should check for null values.

Categories

Resources