Grouping troubles - c#

Hi i am having difficulties to group these data as it has no aggregate function. I have the following data in 2 tables and i would like to Join both by PaymentId and display only 1 row of record.
Question:
How do i display the final result in only 1 ROW groupby CoursePaidForMonthYear.
I would like to get all data from Payment.*, TutorCourseCommissions.* and CoursePaidForMonthYear column in same row displaying (September, October, November)
Example:
referenceId| TutorId| CoursePaidForMonthYear |
1 | 1019 | September, October, November OR 9,10,11|
My work:
var result = from u in db.Users
join p in db.Payments on u.Id equals p.UserId
join tt in db.TutorCourseCommissions on p.Id equals tt.PaymentId into gtt
from tt in gtt.DefaultIfEmpty()
where u.Id == user.Id
GroupBy tt.CoursePaidForMonthYear ??
select new { u, p, tt };
foreach (var r in result)
{
Payment payment = new Payment();
payment.MonthToPay = (r.tt == null) ? null : common.GetMonthName(r.tt.CoursePaidForMonthYear.Month, true);
payment.Amount = r.p.Amount;
output.Add(payment);
}
return output;

What you need to do is group the months by the user and payment, and then perform an aggregation on the grouped months. In this case I used String.Join() to combine the distinct months coming from the commission.
This will give you results along the lines of { User = "John Doe", Payment = ..., Months = "January, February" }
var result = from u in db.Users
where u.UserID == user.Id
join p in db.Payments on u.Id equals p.UserId
join comm in db.TutorCourseCommissions
on p.Id equals comm.PaymentId
group common.GetMonthName(comm.CoursePaidForMonthYear,true)
by new { User = u, Payment = p } into g
select new
{
User = g.Key.User,
Payment = g.Key.Payment,
//...select out other properties here...
Months = String.Join(", ", g.Distinct())
};

Made a class with properties regarding all columns you required and then do the selection using its instance ...
Like
public TutorPayments
{
public int UserID{
get;
set;
}
public int PayType{
get;
set;
}
public int TutorID{
get;
set;
}
//and so on all columns property that you required
}
now you can get all these in your query by creating its instance in this way
var result = from u in db.Users
join p in db.Payments on u.Id equals p.UserId
join tt in db.TutorCourseCommissions on p.Id equals tt.PaymentId into gtt
from tt in gtt.DefaultIfEmpty()
where u.Id == user.Id
GroupBy tt.CoursePaidForMonthYear ??
select new TutorPayments {UserID = u.id,PayType = p.id,TutorID = tt.TutorId, ............ };

Related

How to get the count of values in table using linq

im required to make a query to db to fetch data fro a highchart widget in our site here is the code I use currently,
var highChartsData =
(from a in db.roomdetails
join b in db.ApplySchedule on a.RoomId equals b.RoomID
where b.Status == true
select new HighlinePie
{
Title = a.RoomName,
Date = b.MDate,
Value = db.ApplySchedule.Where(x => x.RoomID == a.RoomId).GroupBy(x=>x.MDate).Count(),
}).ToList();
The problem with this approach is right now get the total count but what i need is the count based on date, for example if there was two entry on date 12/09/20201 and three entry on 14/09/20201 the data should be "Title,12/09/20201,2","Title,14/09/20201,3".
You have to use grouping:
var groupQuery =
from a in db.roomdetails
join b in db.ApplySchedule on a.RoomId equals b.RoomID
where b.Status == true
group b by new { a.RoomName, b.MDate } into g
select new HighlinePie
{
Title = g.Key.RoomName,
Date = g.Key.MDate,
Value = g.Count()
};
var highChartsData = groupQuery.ToList();

c# LINQ how to properly pass a method into the select and return the value

I have a LINQ query that I'm trying to pass a method into it and then return the results back to the select statement.
There are no errors being thrown but UpdatedYesterday contains nothing even through GetUpdatedValue(int r) is returning a yes or no. Is a way to get the returned value in the select statement ?
For example
var result = (from r in reportOne
join l in logs on r.id equals l.id into g
select new TestReport
{
UserID = r.UserID,
UpdatedDate = r.UpdatedDate,
UpdatedYesterday = g.Where(x => x.LogDate == r.WorkDate)
.Select(x => GetUpdatedValue(x.updatedYesterday)).FirstOrDefault()
}).ToList();
public string GetUpdatedValue(int r)
{
var value = r > 0 ? "Yes" : "No";
return value;
}
I think that your WorkDate can not be the same as LogDate, it's better to use just date difference, without time.
Try this
var result = (from r in reportOne
join l in logs
on r.Id equals l.Id into lg
from l in lg.DefaultIfEmpty()
where EF.Functions.DateDiffDay(r.WorkDate, r.LogDate )==0
select new TestReport
{
UserID = r.UserID,
UpdatedDate = r.UpdatedDate,
UpdatedYesterday=l.UpdatedYesterday > 0 ? "Yes" : "No"
}).ToList();
but if for some reasons you still want to use your method, the easiest way is to add one extra property to TestReport
public UpdatedYesterdayInt int {get; set;}
code
var query=
.....
select new TestReport
{
UserID = r.UserID,
UpdatedDate = r.UpdatedDate,
UpdatedYesterdayInt=l.UpdatedYesterday
}).ToList();
var result=query.ForEach(i=> i.UpdatedYesterday=GetUpdatedValue(i.UpdatedYesterdayInt));

Join two linq queries on one key column to get one result set

Here I want to join the out put of the first query(one column) to the result of the 2nd query to get a one result set. How can I merge them.(CONCAT doesn't work as required. eg: var query2 = query.concat(query1);)
var query = (from PP in _db.paymentPlans
join APP in _db.Applications on PP.applicationID equals APP.ApplicationId
join C in _db.Courses on APP.courseID equals C.courseID
where PP.active == true && APP.agentID == agentID
orderby C.courseID ascending
group new {C,PP} by new {C.courseID} into totalRecievable
select new PdPpAppCourseModel
{
courseID = totalRecievable.Key.courseID,
totalAmount = totalRecievable.Sum(x => x.PP.totalAmount)
}).ToList();
var query1=(from PD in _db.paymentDetails
join PP in _db.paymentPlans on PD.paymentPlanID equals PP.paymentPlanID
join APP in _db.Applications on PP.applicationID equals APP.ApplicationId
join C in _db.Courses on APP.courseID equals C.courseID
where PP.active == true && APP.agentID == agentID
orderby C.courseID ascending
group new { C,PD } by new { C.courseID, C.cricosCode, C.courseName } into paymentsCourseWise
select new PdPpAppCourseModel
{
courseID = paymentsCourseWise.Key.courseID,
cricosCode = paymentsCourseWise.Key.cricosCode,
courseName = paymentsCourseWise.Key.courseName,
paidAmount = paymentsCourseWise.Sum(x => x.PD.paidAmount)
}).ToList();
You could join query1 and query like this
var result = (from q1 in query1
join q in query on q1.courseID = q.courseID
select new PdPpAppCourseModel
{
courseID = q1.Key.courseID,
cricosCode = q1.Key.cricosCode,
courseName = q1.Key.courseName,
paidAmount = q1.Sum(x => x.PD.paidAmount),
totalAmount = q.totalAmount
}).ToList();

Group by multiple tables to List

I have 4 tables
- User
- UserId
- UserName
- Device
- DeviceId
- DeviceTypeId (FK DeviceType)
- DeviceType
- DeviceTypeId
- UserDevice
- UserId (FK User)
- DeviceId (FK Device)
I would like to get list of devices that 1 user has, grouped by DeviceType. So result class should be something like this
class m
{
int DeviceTypeId;
List<Device> devices;
}
I did try few tricks in LINQ but didnt get desired result. It has been years since I used LINQ last time.
You were almost there with your comment:
var data = from d in db.Devices
join dt in db.DeviceType on d.DeviceTypeId equals dt.DeviceTypeId
join du in db.UserDevices on d.DeviceId equals du.DeviceId
where (du.UserId == currentUser)
group d by d into g
select new m
{
DeviceTypeId = g.Key.DeviceTypeId,
devices = (from d in g select d).ToList()
};
If you add public string TypeName { get; set; } to your m class, you can populate it with this query:
var data = from d in devices
join dt in deviceTypes on d.DeviceTypeId equals dt.DeviceTypeId
join du in userDevices on d.DeviceId equals du.DeviceId
where (du.UserId == 1)
group d by dt into g
select new m
{
DeviceTypeId = g.Key.DeviceTypeId,
TypeName = g.Key.TypeName,
devices = (from d in g select d).ToList()
};
I guess you want something like this:
return
userDevices
.Where(ud => ud.UserId == myUserId)
.SelectMany(ud => devices.Where(d => d.DeviceId == ud.DeviceId))
.GroupBy(d => d.DeviceTypeId)
.Select(g => new m { DeviceTypeId = g.Key, devices = g.ToList() });
of course I cannot test this but it should be about right (minus some spelling problems)
BTW: I did not even try to give you some ORM like syntax as I have no clue what you are using here - this might be a rather poor performing solution but you should get the idea ...

Linq query multiple tables with different attributes

I have a search that looks for two things. Items and Contacts. They each have their own table with their own unique attributes. I am able to successfully search each independent of eachother and return the results to two list views. But is it ugly and paging has become a issue so I have to convert these two tables into a like result that I can display as a search result. These results have no relationship directly with eachother.
The group t3 by new is throwing me off. Do I have to group them to have it become a like result? The results currently get displayed in a ListView using for example <%#Eval("ItemName") %>
ItemContext db = new ItemContext(); //DB connection (Item,Contact)
var q = (from t1 in db.Item
join t2 in db.Categories on t1.CategoryID equals t2.CategoryID
join t7 in db.Divisions on t1.DivisionID equals t7.DivisionID
from t3 in db.Contacts
join t4 in db.Categories on t3.CategoryID equals t4.CategoryID
join t5 in db.Divisions on t3.DivisionID equals t5.DivisionID
join t6 in db.ContactTitle on t3.ContactTitlesID equals t6.ContactTitlesID
where
(DDLInt == 1 || t3.DivisionID == DDLInt) &&
//Contains
(
t3.ContactName.Contains(keyword) ||
t3.ContactEmail.Contains(keyword) ||
t3.ContactOPhone.Contains(keyword) ||
t3.ContactID.Equals(searchID)
)
group t3 by new
{
t3.ContactID,
t3.ContactName,
t3.ContactOPhone,
t3.ContactCell,
t3.ContactEmail,
t3.DivisionID,
t3.CategoryID,
t4.CategoryName,
t5.DivisionName,
t6.ContactTitlesName
}
into i
select new
{
i.Key.ContactID,
i.Key.ContactName,
i.Key.ContactOPhone,
i.Key.ContactEmail,
i.Key.ContactCell,
i.Key.CategoryName,
i.Key.DivisionName,
i.Key.CategoryID,
i.Key.DivisionID,
i.Key.ContactTitlesName
});
return q.ToList<dynamic>();
}
Use Union():
var contacts = from c in db.Contacts
select new {
Id = c.ContactID,
Name = c.ContactName,
Phone = c.ContactOPhone,
...
CategoryName = c.Category.CategoryName,
DivisionName = c.Division.DivisionName,
ContactTitlesName = c.ContactTitle.ContactTitlesName
}
var items = from t1 in db.Item
select new {
Id = t1.ItemID,
Name = t1.ItemName,
Phone = t1.??, // string.Empty?
... // more properties corresponding
// with the ones above
CategoryName = t1.Category.CategoryName,
DivisionName = t1.Division.DivisionName,
ContactTitlesName = string.Empty
}
var all = contacts.Union(items);

Categories