How to join multiple tables using linq with group by condition - c#

I want to fetch the list of employer with inner list details to show multiple address. I have tried the following code and can able to fetch the EmpConnectionNumber, EmpState. I could able to fetch the StoreID, StoreStaffName, Address, ContactNumber details from store and StoreStaffList tables.
List<Model.ListEmployer.Employer> employer_list = null;
employer_List = (from a in Employer
join b in store on a.EmployerID equals b.EmployerID
join c in StoreAddress on b.StoreID equals c.StoreID
join d in StoreStaffList on c.storeAddressID equals d.StoreAddressID
where a.EmployerType == "Contract"
group new { a, c } by new { a.ConnectionNumber, c.state }
into grp
select new Model.ListEmployer.Employer
{
EmpConnectionNumber = grp.Key.ConnectionNumber,
EmpState = grp.Key.State,
AddressHistory = new List<Model.list Employer.AddressHistory>
{
new Model.ListEmployer.AddressHistory
{
StoreID = b.StoreID,
StoreStaffName = d.StoreStaffName,
Address = d.Address,
ContactNumber = d.ContactNumber
}
}
}). ToList();
Can anyone help on this solution to get it done.
my intension is to show multiple address details inside the same Employer list itself

Related

MongoDb aggregate in c#

I need to join 3 collections and get the desired data. I have written a LINQ query which working fine but I want to write it using mongoDb's Aggregate interface.
Here is my query in LINQ.
var query = from user in userCollection.AsQueryable()
where user.Id == userId
from userDivision in user.Divisions
select new { userDivision.DivisionId } into divisions
join division in divisionCollection.AsQueryable() on divisions.DivisionId equals division.Id
select new { division.CompanyId } into divisionCompany
join company in companyCollection.AsQueryable() on divisionCompany.CompanyId equals company.Id
select new
{
company.Id,
company.Code,
company.Name,
company.Address,
ConcurrencyId = "1_" + "3_" + company.Id
} into c
join concurrency in concurrencyCollection.AsQueryable() on c.ConcurrencyId equals concurrency.Id into concurrencies
from concurrencyEmpty in concurrencies.DefaultIfEmpty()
select new Response.Company
{
Id = c.Id,
Code = c.Code,
Name = c.Name,
CodeAndName = c.Code + " - " + c.Name,
Address = c.Address,
ConcurrencyVersion = concurrencyEmpty.Version
};
Can anybody tell me how to write this query using MongoDb's aggregate interface (using LookUp etc).
Thanks in advance.

Linq EF group by to get latest entries into list of objects

I am trying to move from simple SQL to EF.
But there are some complex queries(joins) that it seems to hard to generate the linq for.
At first I tried to use sqltolinq tool to generate the linq but it gives error as some of the things are not supported in the query.
here is the linq:
var entryPoint = (from ep in dbContext.tbl_EntryPoint
join e in dbContext.tbl_Entry on ep.EID equals e.EID
join t in dbContext.tbl_Title on e.TID equals t.TID
where e.OwnerID == user.UID
select new {
UID = e.OwnerID,
TID = e.TID,
Title = t.Title,
EID = e.EID
});
The table entry has many entries that I would like to group and get the latest for each group. But then I would need to select into a view model object which will be bind to gridview.
I dont know where I can implement the logic to group by and get the latest from each and be able to get values from join table into viewModel object.
somewhere I need to add
group entry by new
{
entry.aID,
entry.bCode,
entry.Date,
entry.FCode
}
into groups
select groups.OrderByDescending(p => p.ID).First()
in the above linq to retrieve latest from each group.
You can insert group by right after the joins:
var query =
from ep in dbContext.tbl_EntryPoint
join e in dbContext.tbl_Entry on ep.EID equals e.EID
join t in dbContext.tbl_Title on e.TID equals t.TID
where e.OwnerID == user.UID
group new { ep, e, t } by new { e.aID, e.bCode, e.Date, e.FCode } into g
let r = g.OrderByDescending(x => x.e.ID).FirstOrDefault()
select new
{
UID = r.e.OwnerID,
TID = r.e.TID,
Title = r.t.Title,
EID = r.e.EID
};
The trick here is to include what you need after the grouping between group and by.
However, the above will be translated to CROSS APPLY with all joins included twice. If the grouping key contains fields from just one table, it could be better to perform the grouping/selecting the last grouping element first, and then join the result with the rest:
var query =
from e in (from e in dbContext.tbl_Entry
where e.OwnerID == user.UID
group e by new { e.aID, e.bCode, e.Date, e.FCode } into g
select g.OrderByDescending(e => e.ID).FirstOrDefault())
join ep in dbContext.tbl_EntryPoint on e.EID equals ep.EID
join t in dbContext.tbl_Title on e.TID equals t.TID
select new
{
UID = e.OwnerID,
TID = e.TID,
Title = t.Title,
EID = e.EID
};

SQL query into LINQ in asp.net mvc

Please anyone can help me to write this sql query into Linq. i have tried..
this is my sql query
select o.OrderID,o.Nature,o.Date,od.TotalPrice,os.OrderStatus,lo.FirstName,lo.EmailAddress,lo.PhoneNumber
from [dbo].[Order] o
inner join [dbo].[tbl_OrderDetails] od on od.OrderID = o.OrderID
inner join [dbo].[tbl_OrderHistory] oh on oh.OrderID = o.OrderID
inner join [dbo].[tbl_Login] lo on o.UserID = lo.UserID
inner join dbo.tbl_OrderStatus os on oh.OrderStatusID= os.OrderStatusID
group by o.OrderID,o.Nature,od.TotalPrice,o.Date,os.OrderStatus,lo.FirstName,lo.EmailAddress,lo.PhoneNumber
and this is my try
public override orderDetailModel orderDetails(int id)
{
var results = from o in obj.Orders
join od in obj.tbl_OrderDetails on o.OrderID equals od.OrderID
join oh in obj.tbl_OrderHistory on o.OrderID equals oh.OrderID
join l in obj.tbl_Login on o.UserID equals l.UserID
join os in obj.tbl_OrderStatus on oh.OrderStatusID equals os.OrderStatusID
where (od.OrderID == id)
group o by new { o.Nature, o.OrderID } into
select new orderDetailModel
{
OrderID = o.OrderID,
OrderStatus = os.OrderStatus,
Date = o.Date,
DeliveryNature = o.Nature,
EmailAddress = l.EmailAddress,
FirstName = l.FirstName,
PhoneNumber = l.PhoneNumber,
TotalPrice = od.TotalPrice
};
//group o by new {o.OrderID};
orderDetailModel data = (orderDetailModel)results.FirstOrDefault();
return data;
}
but this is wrong query its not working fine please help me
You need to correct the group by clause, like you have in the SQL query like this:-
group new { o, l } by new { o.OrderID,o.Nature,od.TotalPrice,o.Date,os.OrderStatus,
l.FirstName, l.EmailAddress,l.PhoneNumber } into g
select new orderDetailModel
{
OrderID = g.Key.OrderID,
OrderStatus = g.Key.OrderStatus,
Date = g.Key.Date,
..and so on
};
Since you need the grouping on two tables Order & tbl_Login you will have to first project them as anonymous type group new { o, l } then specify all the groupings and finally while projecting use Key to get the respective items.
I guess that actually, also the SQL query is not correct.
I would simply use a SELECT DISTINCT ... instead of Grouping all the columns.
Anyway, first thing to do:
Check if databases is designed correctly. As far as i can see, if you're joining the table with their Ids, i don't understand why you need to group all the data. If you have duplicates, maybe the error is in the Database design.
If you can't change your Database, or you are happy with it, then use the following LINQ approach:
var distinctKeys = allOrderDetails.Select(o => new { o.OrderID, o.Nature, o.TotalPrice, o.Date,o.OrderStatus,o.FirstName, o.EmailAddress,o.PhoneNumber }).Distinct();
var joined = from e in allOrderDetails
join d in distinctKeys
on new { o.OrderID, o.Nature,o.TotalPrice, o.Date,o.OrderStatus, o.FirstName, o.EmailAddress, o.PhoneNumber } equals d select e;
joined.ToList(); // gives you the distinct/grouped list

Multiple join with groupby in linq

i have 5 table from which i want to get some information using linq.i am using following query for reading data from data .
var query = (from GRD in _tblStudents.GetQueryable()
join apt in _tblApplicants.GetQueryable()
on GRD.ApplicantID equals apt.ApplicantID
join cls in _tblClasses.GetQueryable()
on GRD.CityID equals cls.ClassID
join prg in _tblPrograms.GetQueryable()
on cls.ProgramID equals prg.ProgramID
join city in _tblCities.GetQueryable()
on GRD.CityID equals city.CityID
where GRD.AcademicYearID == yearId && cls.ProgramID == programId
group apt by new{apt.Gender} into grouped
select new CityWiseStudentModel
{
CityName=city.CityName,
//'city' does not exist in the current context
Gender = grouped.Count(),
programName=prg.Program,
//'prg' does not exist in the current context
}
);
How i can get City name from city table and program name from prg table
group <--> by <--> into <--> is changed your scope to IGrouping<a,b>
My opinion is not only apt.Gender is your key but city.CityName and prg.Program
try this (or some similar):
group apt by new{apt.Gender, city, prg} into grouped
select new CityWiseStudentModel
{
CityName = grouped.Key.city.CityName,
Gender = grouped.Count(), //rename GenderCount
programName = grouped.Key.prg.Program,
// Gender = grouped.Key.Gender,
}
Remember that grouped will only hold the things you've grouped. If you only group adt, then city and prg will not be available in your select.
So you'll need to:
Include city and program into grouped (otherwise they're not available)
Access CityName and Program inside the grouped collection
Something like this should do the trick:
...
group new { apt, cls, prg, city } by new{apt.Gender} into grouped
select new CityWiseStudentModel
{
CityNames = grouped.Select(g => g.city.CityName),
...
programNames = grouped.Select(g => g.prg.Program)
}

LINQ: combining join and group by

I have a query that combines a join and a group, but I have a problem. The query is like:
var result = from p in Products
join bp in BaseProducts on p.BaseProductId equals bp.Id
group p by p.SomeId into pg
select new ProductPriceMinMax {
SomeId = pg.FirstOrDefault().SomeId,
CountryCode = pg.FirstOrDefault().CountryCode,
MinPrice = pg.Min(m => m.Price),
MaxPrice = pg.Max(m => m.Price),
BaseProductName = bp.Name <------ can't use bp.
};
As you see, it joins the Products table with the BaseProducts table, and groups on an id of the Product table. But in the resulting ProductPriceMinMax, I also need a property of the BaseProducts table: bp.Name, but it doesn't know bp.
Any idea what I'm doing wrong?
Once you've done this
group p by p.SomeId into pg
you no longer have access to the range variables used in the initial from. That is, you can no longer talk about p or bp, you can only talk about pg.
Now, pg is a group and so contains more than one product. All the products in a given pg group have the same SomeId (since that's what you grouped by), but I don't know if that means they all have the same BaseProductId.
To get a base product name, you have to pick a particular product in the pg group (As you are doing with SomeId and CountryCode), and then join to BaseProducts.
var result = from p in Products
group p by p.SomeId into pg
// join *after* group
join bp in BaseProducts on pg.FirstOrDefault().BaseProductId equals bp.Id
select new ProductPriceMinMax {
SomeId = pg.FirstOrDefault().SomeId,
CountryCode = pg.FirstOrDefault().CountryCode,
MinPrice = pg.Min(m => m.Price),
MaxPrice = pg.Max(m => m.Price),
BaseProductName = bp.Name // now there is a 'bp' in scope
};
That said, this looks pretty unusual and I think you should step back and consider what you are actually trying to retrieve.
We did it like this:
from p in Products
join bp in BaseProducts on p.BaseProductId equals bp.Id
where !string.IsNullOrEmpty(p.SomeId) && p.LastPublished >= lastDate
group new { p, bp } by new { p.SomeId } into pg
let firstproductgroup = pg.FirstOrDefault()
let product = firstproductgroup.p
let baseproduct = firstproductgroup.bp
let minprice = pg.Min(m => m.p.Price)
let maxprice = pg.Max(m => m.p.Price)
select new ProductPriceMinMax
{
SomeId = product.SomeId,
BaseProductName = baseproduct.Name,
CountryCode = product.CountryCode,
MinPrice = minprice,
MaxPrice = maxprice
};
EDIT: we used the version of AakashM, because it has better performance
I met the same problem as you.
I push two tables result into t1 object and group t1.
from p in Products
join bp in BaseProducts on p.BaseProductId equals bp.Id
select new {
p,
bp
} into t1
group t1 by t1.p.SomeId into g
select new ProductPriceMinMax {
SomeId = g.FirstOrDefault().p.SomeId,
CountryCode = g.FirstOrDefault().p.CountryCode,
MinPrice = g.Min(m => m.bp.Price),
MaxPrice = g.Max(m => m.bp.Price),
BaseProductName = g.FirstOrDefault().bp.Name
};

Categories