Hi Need some help with LINQ query.
I have entity called Shift. This entity has several value field but the ones I am intressted in are ShiftID (int), ShiftDate (DateTime) and GrossMount (decimal(10,2). And this needs to be grouped by month (binding this to a graph in ASP.NET).
I need data for the last 12 months grouped by month.
I have come a bit on the way with this post: Linq to Entity, selecting group without value but not quite all the way.
This is my code for now:
public IQueryable<Shift> GetPastMonths(int months, string accountNumber)
{
_context = new EtaxiEnteties();
var _date = DateTime.Today;
var _firstOfMonth = new DateTime(_date.Year, _date.Month, 31);
var _twelveMonthAgoFirstOfMonth = _firstOfMonth.AddMonths(-12);
// Generate a collection of the months and years for the last 12 months
var _monthYears = Enumerable.Range(-12, 12).Select(monthOffset => { var monthDate = _firstOfMonth.AddMonths(monthOffset); return new { y = monthDate.Year, m = monthDate.Month }; });
var _data = (from _monthYear in _monthYears
join _i in
(from _i in _context.Shifts.Where(acc => acc.Account.AccountNumber == accountNumber)
where _i.ShiftDate >= _twelveMonthAgoFirstOfMonth && _i.ShiftDate < _firstOfMonth
group _i by new { y = _i.ShiftDate.Year, m = _i.ShiftDate.Month } into g
select new { ShiftID = g.Key, GrossAmount = g.Count() }) on _monthYear equals _i.ShiftID into j
from _k in j.DefaultIfEmpty()
select new Shift() { ShiftDate = new DateTime(_monthYear.y, _monthYear.m, 1), GrossAmount = _k != null ? _k.GrossAmount : 0 });
return _data as IQueryable<Shift>;
}
Now I have in return a collection of Shift objects, grouped by month but still missing the GrossAmount. Althoug i would need this from today date (only getting from 1 of current month).
Believe this is my main problem: GrossAmount = g.Count(), but I am not sure
Any LINQ specialist out there that could give me a push?
Use GrossAmount = g.Sum(x => x.GrossAmount) to calculate total GrossAmount value of grouped Shift entities. I believe you have typo in GrossAmount (GrossMount) property name.
Related
I have this query:
var months = dates.GroupBy(
x => x.Value.Month).Select(g => new { Month = g.Key, Count = g.Count()});
lbl1.Text = string.Join(",", months);
How do I assign key and count to two different labels?
Try this
lblMonth.Text=months.Month;
lblCount.Text=months.Count;
Also you have to call FirstOrDefault() or ToList() in order to select data. Currently you code will not select data.
var months = dates.GroupBy(x => x.Value.Month).Select(g => new { Month = g.Key, Count = g.Count() }).FirstOrDefault();
OR
var months = dates.GroupBy(x => x.Value.Month).Select(g => new { Month = g.Key, Count = g.Count() }).ToList();
if you use ToList() than you will have to get values by index like
lblMonth.Text=months[0].Month;
lblCount.Text=months[0].Count;
I'm new to linq.
In c# I'm doing as follows to get the count of one column.
SELECT DispatcherName,
ActivityType,
CONVERT(BIGINT,COUNT(ActivityType)) AS Total
FROM ACTIVITYLOG
GROUP BY DispatcherName,
ActivityType
ORDER BY Total DESC
Can any one tell m,how I can achieve the same thing using LINQ.
Update:
HI I did as follows and got the reslut.
But I'm not able to convert result to datatable.
this is how I did.
here dt is datatabe with two columns Dispatchername and ActivityType.
var query1 = from p in dt.AsEnumerable()
group p by new
{
DispatcherName = p.Field<string>("Dispatchername"),
Activity = p.Field<string>("ActivityType"),
}
into pgroup
let count = pgroup.Count()
orderby count
select new
{
Count = count,
DispatcherName = pgroup.Key.DispatcherName,
Activity = pgroup.Key.Activity
};
pls help me out asap.
from c in ACTIVITYLOG
group c by new {c.DispatcherName, c.ActivityType} into g
orderby g.Count() descending
select new { g.Key.DispatcherName, g.Key.ActivityType, Total = g.Count() }
If you want your results returned back to a DataTable, one option is to use the CopyToDataTable method.
Here's a live example: http://rextester.com/XHX48973
This method basically requires you to create a dummy table in order to use its NewRow method - the only way to create a DataRow, which is required by CopyToDataTable.
var result = dt.AsEnumerable()
.GroupBy(p => new {
DispatcherName = p.Field<string>("DispatcherName"),
Activity = p.Field<string>("ActivityType")})
.Select(p => {
var row = dummy.NewRow();
row["Activity"] = p.Key.Activity;
row["DispatcherName"] = p.Key.DispatcherName;
row["Count"] = p.Count();
return row;
})
.CopyToDataTable();
Perhaps a better way might be just fill in the rows directly, by converting to a List<T> and then using ForEach.
DataTable dummy = new DataTable();
dummy.Columns.Add("DispatcherName",typeof(string));
dummy.Columns.Add("Activity",typeof(string));
dummy.Columns.Add("Count",typeof(int));
dt.AsEnumerable()
.GroupBy(p => new { DispatcherName = p.Field<string>("DispatcherName"),
Activity = p.Field<string>("ActivityType")})
.ToList()
.ForEach(p => {
var row = dummy.NewRow();
row["Activity"] = p.Key.Activity;
row["DispatcherName"] = p.Key.DispatcherName;
row["Count"] = p.Count();
dummy.Rows.Add(row);
});
Live example: http://rextester.com/TFZNEO48009
This should do the trick:
IList<ACTIVITYLOG> allActivityLogs;
var result = (from c in allActivityLogs
select new
{
DispatcherName = c.DispatcherName,
ActivityType = c.ActivityType,
Total = c.ActivityType.Count
}).OrderByDescending(x => x.Total)
.GroupBy(x => new { x.DispatcherName, x.ActivityType });
You only need to substitute the allActivityLogs collection with the actual collection of your entities.
I having a trouble with a query
I need to take out the SHIPMENT from GetAllOrderData - the same place where you can find POD_DATE and RECEIVE_NAME...but I get an error
Error 1 The name 'x' does not exist in the current context
My code is:
public IEnumerable<ReportItemDTO> GetTaskProgress(DateTime targetDate)
{
try
{
var startDate = targetDate.Date;
var endDate = startDate.AddDays(1);
OrderDataRepository rep = new OrderDataRepository();
var query = rep.GetAllOrderData()
.Where(x => x.POD_DATE >= startDate && x.POD_DATE <= endDate)
.GroupBy(o => o.User)
.Select(g => new ReportItemDTO
{
DriverId = g.Key.Id,
PdriverName = g.Key.Name,
OrderCount = g.Count(),
ReportedOrdersCount = g.Count(o => o.RECEIVE_NAME != null),
SHIPMENT = (x.SHIPMENT)
} );
return query;
SHIPMENT = (x.SHIPMENT)
Well you are within a grouping when you try to make that assignment - there are many shipments in each grouping not just one - in fact all shipments for that particular user. Assuming you want a collection of them you could do:
Shipments = g.Select( x=> x.SHIPMENT)
Edit:
If you just want the first shipment for each user (somewhat illogical but fits your data model):
SHIPMENT = g.Select( x=> x.SHIPMENT).First()
I have develop a small web application in that i'm using entity frame work .i want get the records based on the date range and bind that data in gridview how can i write a query using linq..please help me..Here i have post my code what i have try to get records please .....
var query = from p in entity.Payments
join D in entity.Debit_Method on p.Debit_Method_ID equals D.Debit_Method_ID
join pt in entity.Payment_Type on p.Payment_Type_ID equals pt.Payment_Type_ID
where p.Client_Pmt_Date >='1998-12-01' && p.Client_Pmt_Date<='1999-08-01' && p.Loan_ID=loanid
select new
{
p.Pmt_ID,
p.Loan_ID,
p.Client_Pmt_Date,
p.MtgSvr_Pmt_Start_Date2,
D.Debit_Method_Desc,
p.Total_Debit_Amt,
p.CreditAmt,
p.LenderAmt,
pt.Payment_Type_Desc,
p.Return_Code,
p.Returned_Date
//p.Pmt_ID,
// D.Debit_Method_Desc,
// pt.Payment_Type_Desc,
// p.Client_Pmt_Date,
// p.MtgSvr_Pmt_Start_Date2,
// p.Amt,
// p.CreditAmt,
// p.Loan_ID,
// p.Pmt_Comments
// p.Loan_ID,
};
grdPayments.DataSource = query.ToList();
grdPayments.DataBind();
}
You will need to compare the Date to a DateTime object rather than a string. Here is a LINQ example with POCO (Plain Old CLR Objects):
var dates = new List<DateTime> { new DateTime(2011, 1, 1), new DateTime(2010, 1, 1), new DateTime(2009, 1, 1) };
var result1 = from x in dates where x < new DateTime(2011, 1, 1) && x > new DateTime(2009,1,1) select x;
var result2 = dates.Where(x => x < new DateTime(2011, 1, 1) && x > new DateTime(2009,1,1));
I have a class called Person, which contains various properties such as first name, last name, etc.
I have a List that contains n instances of Person.
List<Person> lstPerson = new List<Person>();
What I need to be able to do is search lstPerson for a given person, and having found that person then obtain the previous and next person relative to the person's item position in lstPerson.
Person p = lstPerson.Find(delegate(Person o) { return o.FirstName == "Joe"; });
// Then use an accessor to get the previous and next persons
Person prevPerson = p.Previous();
Person nextPerson = p.Next();
Is there a better way to do this then the one that I stated above? What I don't like about the above solution is that I have to construct the previous and next pointers at the time that I build the Person List.
You could do something like the following:
int personIndex = lstPerson.FindIndex(delegate(Person o) { return o.FirstName == "Joe" });
Person p = lstPerson[personIndex];
// verify that personIndex+1 and personIndex-1 still fall within the list
Person prevPerson = lstPerson[personIndex-1];
Person nextPerson = lstPerson[personIndex+1];
Hmm.. why not simply using the LinkedList class?
It comes with Next and Previous built in.
You could do this, which skips elements until the next element matches or it has gone through the entire list:
var list = (new List<Person>() { null }).Concat(lstPerson);
var p = list.SkipWhile((x, index) => { var n = list.ElementAtOrDefault(index + 1); return n == null || n.FirstName != name; }).Take(3);
Person previous = p.FirstOrDefault();
Person person = p.ElementAtOrDefault(1);
Person next = p.ElementAtOrDefault(2);
Although this (similar to #marcind's answer) might be clearer:
Person person = lstPerson.Find(p => p.FirstName == name);
Person previous = null;
Person next = null;
if (person != null)
{
int index = lstPerson.IndexOf(person);
previous = lstPerson.ElementAtOrDefault(index - 1);
next = lstPerson.ElementAtOrDefault(index + 1);
}