Can't access the fields of non-grouping tables in linq - c#

I'm trying to join few tables using LINQ and retrieve a data set. But my problem is when I group the tables, I cannot access the fields of the non grouped tables in the LINQ query. here is my sample code block. Please help
var query = from sb in db.Surfboards
join csb in db.CustomerSurfBoards on sb.SurfBoardID equals csb.SurfBoardID
join c in db.Customers on csb.CustomerID equals c.CustomerID
where c.IsActive
group new { sb,csb} by new {sb.ID, csb.ComponentId} into g
select new ReportModel()
{
ReceivedDate = g.First().Name,
Number = c.First().Number <------- this cannot be accessed
}
what I'm trying to achieve is something like this
select sb.Id, max(c.Number), cbs.Id from Surfboards as sb
inner join CustomerSurfBoards as cbs on sb.SurfBoardID = csb.SurfBoardID
inner join Customers as c on csb.CustomerID = c.CustomerID
group by sb.Id, csb.ComponentId

Try this:
var query = from sb in db.Surfboards
join csb in db.CustomerSurfBoards on sb.SurfBoardID equals csb.SurfBoardID
join c in db.Customers on csb.CustomerID equals c.CustomerID
where c.IsActive
select new {sb.id, c.number, cbs.componentid} into tmp
from t in tmp
group t by new {t.ID, t.ComponentId} into g
select new
{
g.Key.id, g.Key.componentid, number = g.Select(n=>n.number).OrderByDescending().FirstOrDefault()
}

Related

Need help on Linq-to-SQL query (maybe nested query?)

I am asking for your help regarding a linq query to SQL.
Here is a part of the diagram of my database: https://imgur.com/xFBUm3q
My problem is in the following relationship: tbl_607_bottle and tbl_607_gaz_reporting, I can have several reportings for a bottle but reporting can only have one bottle.
I do this request but it's not satisfying.
var GazReportingWizardViewModel =
(from gr in db.tbl_607_gaz_reporting
join a in db.tbl_607_actors on gr.FK_ID_actors equals a.id
join bo in db.tbl_607_bottle on gr.FK_ID_bottle equals bo.ID
join loc in db.tbl_607_location on bo.FK_ID_location equals loc.ID
join cc in db.tbl_607_conformity_certificate on bo.FK_ID_conformity_certificate equals cc.ID
join j in db.tbl_607_join_bottle_gaz on bo.ID equals j.FK_ID_bottle
join g in db.tbl_607_gaz on j.FK_ID_gaz equals g.ID
join od in db.tbl_607_order_details on g.FK_ID_order_details equals od.ID
where loc.ID == Process
select new GazReportingWizardViewModel
{
bottle_conti_number = bo.bottle_conti_number,
pressure_value = gr.pressure_value,
reporting_date = gr.reporting_date,
first_name = gr.tbl_607_actors.first_name,
last_name = gr.tbl_607_actors.last_name,
expiration_date = cc.expiration_date,
content = od.content_comments
}).Distinct()
.OrderBy(t => t.reporting_date)
.ToList();
I want the last report on each bottle but it return all reports on each bottle.
Would you have an idea of ​​the solution?
Thank you for your time
Thank you so much!
I persisted in trying to solve the problem in a single query when the solution was so simple.
var GazReportingWizardViewModel = (from gr in db.tbl_607_gaz_reporting
join a in db.tbl_607_actors on gr.FK_ID_actors equals a.id
join bo in db.tbl_607_bottle on gr.FK_ID_bottle equals bo.ID
join loc in db.tbl_607_location on bo.FK_ID_location equals loc.ID
join cc in db.tbl_607_conformity_certificate on bo.FK_ID_conformity_certificate equals cc.ID
join j in db.tbl_607_join_bottle_gaz on bo.ID equals j.FK_ID_bottle
join g in db.tbl_607_gaz on j.FK_ID_gaz equals g.ID
join od in db.tbl_607_order_details on g.FK_ID_order_details equals od.ID
where loc.ID == Process
select new GazReportingWizardViewModel
{
bottle_conti_number = bo.bottle_conti_number,
pressure_value = gr.pressure_value,
reporting_date = gr.reporting_date,
first_name = gr.tbl_607_actors.first_name,
last_name = gr.tbl_607_actors.last_name,
expiration_date = cc.expiration_date,
content = od.content_comments
}).ToList();
var res = from element in GazReportingWizardViewModel
group element by element.bottle_conti_number
into groups
select groups.OrderByDescending(p => p.reporting_date).First();

Complicated SQL query to Linq

I need to convert the following complicated sql query to Linq in C#:
Select Empleador.NombreComercial as Empresa,
Vacante.Puesto as Vacante,
Vacante.Actividades,
COUNT(Vacante.CveVacante) as Visitas
from Vacante
LEFT JOIN Empleador on Empleador.CveEmpleador=Vacante.CveEmpleador
LEFT JOIN VisitaVacante on Vacante.CveVacante = VisitaVacante.CveVacante
GROUP BY Empleador.NombreComercial,Vacante.Puesto, Vacante.Actividades,
Vacante.CveVacante HAVING COUNT(*) > 1 ORDER BY Visitas DESC
For the moment I already have the following:
var Visitas = (from tvacante in db.VacanteT
join tEmpleador in db.EmpleadorT on tvacante.CveEmpleador equals tEmpleador.CveEmpleador
join tVisitaVacante in db.VisitaVacanteT on tvacante.CveVacante equals tVisitaVacante.CveVacante
select new
{
Empresa = tEmpleador.NombreComercial,
Vacante = tvacante.Puesto,
tvacante.Actividades,
Visitas = tvacante.CveVacante
}).GroupBy( );
How can I add the COUNT(Vacante.CveVacante) as Visitas and also the
GROUP BY Empleador.NombreComercial,Vacante.Puesto, Vacante.Actividades,
Vacante.CveVacante HAVING COUNT(*) > 1 ORDER BY Visitas DESC
to my linq query? I can't find information about how to complete this. The tables are tvacante, templeador, and tvisitaVacante.
Try this:
var Visitas =(from tvacante in db.VacanteT
join tEmpleador in db.EmpleadorT on tvacante.CveEmpleador equals tEmpleador.CveEmpleador
join tVisitaVacante in db.VisitaVacanteT on tvacante.CveVacante equals tVisitaVacante.CveVacante
group new{tEmpleador.NombreComercial,tvacante.Puesto, tvacante.Actividades} by new {tEmpleador.NombreComercial,tvacante.Puesto, tvacante.Actividades} into g
where g.Count()>1
select new
{
Empresa = g.Key.tEmpleador.NombreComercial,
Vacante = g.Key.tvacante.Puesto,
Actividades= g.Key.tvacante.Actividades,
Visitas = g.Count()
}).OrderByDescending(e=>e.Visitas);
If you want to do it using only linq query syntax and not merging both syntax then you could also do this:
var Visitas = from tvacante in db.VacanteT
join tEmpleador in db.EmpleadorT on tvacante.CveEmpleador equals tEmpleador.CveEmpleador
join tVisitaVacante in db.VisitaVacanteT on tvacante.CveVacante equals tVisitaVacante.CveVacante
group new{tEmpleador.NombreComercial,tvacante.Puesto, tvacante.Actividades} by new {tEmpleador.NombreComercial,tvacante.Puesto, tvacante.Actividades} into g
where g.Count()>1
orderby g.Count() descending
select new
{
Empresa = g.Key.tEmpleador.NombreComercial,
Vacante = g.Key.tvacante.Puesto,
Actividades= g.Key.tvacante.Actividades,
Visitas = g.Count()
};

Why don't my SQL results match my Linq results?

When I run this Query in SQL I get what I want:
SELECT Auckland_Park.Formative.[Formative Name]
FROM Auckland_Park.LearningUnit
INNER JOIN Auckland_Park.Formative
ON Auckland_Park.LearningUnit.ID = Auckland_Park.Formative.FK_LU
INNER JOIN Auckland_Park.Reference
INNER JOIN Auckland_Park.Course
ON Auckland_Park.Reference.FK_Course = Auckland_Park.Course.ID
ON Auckland_Park.LearningUnit.ID = Auckland_Park.Reference.FK_LU
WHERE Auckland_Park.Course.Name = 'BI'
My result:
Querying SQL Build
Report Develop
Java App Develop
Andriod App Set up
SharePoint Server
But when I work with my C# app I'm using LINQ to SQL, my LINQ Query looks like this:
//LINQ Query to fill Foramtive Name ComboBox
CTUDataContext data = new CTUDataContext();
var course = (from r in data.LearningUnits
join a in data.Formatives
on r.ID equals a.FK_LU
join f in data.References
on r.ID equals f.FK_LU
join g in data.Courses
on f.FK_LU equals g.ID
where g.Name == ("BI")
select new
{
formativeName = a.Formative_Name,
ID = a.ID
}
).ToList();
txtFormativeName.ItemsSource = course;
txtFormativeName.DisplayMemberPath = "formativeName";
txtFormativeName.SelectedValuePath = "ID";
It seems the same, but I'm not getting the same result that I'm getting with the SQL Query above.
//LINQ Query to fill Foramtive Name ComboBox
CTUDataContext data = new CTUDataContext();
var course = (from r in data.LearningUnits
join a in data.Formatives
on r.ID equals a.FK_LU
join f in data.References
on r.ID equals f.FK_LU
join g in data.Courses
on f.FK_LU equals g.ID
where g.Name == ("BI")
select new
{
formativeName = a.Formative_Name,
ID = a.ID
}
).ToList();
txtFormativeName.ItemsSource = course;
txtFormativeName.DisplayMemberPath = "formativeName";
txtFormativeName.SelectedValuePath = "ID";
ANSWER:
on f.FK_LU equals g.ID
f.FK_LU
must be replaced with
f.FK_Course

How to write LINQ left join

var query = from r in db.Resource
join c in db.ResourceProjectedCapacity on r.ID equals c.ResourceID into ps
from c in ps.DefaultIfEmpty(null)
join p in db.Project on c.ProjectID equals p.ID
select new
{
Capacity = c,
Resource = r,
Project = p
};
I have this linq query but it is only returning resources that have a matching row on ResourceProjectedCapacity table. How can I get all resources and in case they dont have a matching record the Capacity object to be null?
from i in db.Resource
let c = db.ResourceProjectedCapacity.Where(cc => i.id == cc.ResourceID).FirstOrDefault()
let p = db.Project.Where(pp => c.ProjectID == pp.ID).FirstOrDefault()
select new
{
Capacity = C,
Resource = i,
Project = p
}
try above code
I think the secondary inner join messes up the left outer join above it. I think a way to work around it is to break the join into a seperate query, and then left join on that, something like this:
var subquery = from c in db.ResourceProjectedCapacity
join p in db.Project on c.ProjectID equals p.ID
select new { c, p };
var query = from r in db.Resource
join c in subquery on r.ID equals c.c.ResourceID into ps
from c in ps.DefaultIfEmpty(null)
select new
{
Capacity = c.c,
Resource = r,
Project = c.p
};
NB don't worry, it won't do two db queries, it'll only execute against your db once you evaluate query with a .ToList() or something like that.

Linq to sql Distinct after join

I have a join query and i want to filter the result of this query by using distinct. I want to get only one of the shoes which has same brand, model, primary color and secondary color. How can i make this ? Here is my join query.
var query = from b in db.BrandTbls.AsQueryable()
join m in db.ShoeModelTbls on b.BrandID equals m.BrandID
join s in db.ShoeTbls on m.ModelID equals s.ModelID
join i in db.ShoeImageTbls on s.ShoeID equals i.ShoeID
where s.Quantity > 0
orderby m.ModelName
select new
{
s.ShoeID,
m.ModelName,
m.Price,
b.BrandName,
i.ImagePath
};
I found the solution. This query does approximately what i want to do
var query = from b in db.BrandTbls.AsQueryable()
join m in db.ShoeModelTbls on b.BrandID equals m.BrandID
join s in db.ShoeTbls on m.ModelID equals s.ModelID
join i in db.ShoeImageTbls on s.ShoeID equals i.ShoeID
group new {b,m,s,i} by new {b.BrandName,m.ModelName,m.Price,s.ShoeID,s.PrimaryColor,s.SecondaryColor,i.ImagePath} into g
select new {g.Key.ShoeID,g.Key.BrandName,g.Key.ModelName,g.Key.ImagePath,g.Key.Price};
Remove price from the output and use Distinct() like this:
var query = (from b in db.BrandTbls.AsQueryable()
join m in db.ShoeModelTbls on b.BrandID equals m.BrandID
join s in db.ShoeTbls on m.ModelID equals s.ModelID
join i in db.ShoeImageTbls on s.ShoeID equals i.ShoeID
where s.Quantity > 0
orderby m.ModelName
select new
{
s.ShoeID,
m.ModelName,
b.BrandName,
i.ImagePath
}).Distinct();

Categories