Unwind/Flatten Entity Framework result - c#

Original SQL Query:
SELECT e.id, e.[type_id], e.name
FROM [user] u
JOIN user_group ug ON ug.[user_id] = u.id
JOIN usergroup grp on grp.id = ug.group_id
JOIN access_entity ae ON ae.group_id = grp.id
JOIN entity e on e.id = ae.entity_id
WHERE u.id = 184
GROUP BY e.id, e.[type_id], e.name
UNION
SELECT e.id, e.[type_id], e.name
FROM [user] u
JOIN user_group ug ON ug.[user_id] = u.id
JOIN usergroup grp on grp.id = ug.group_id
JOIN CRUD xs on xs.FK_Group_ID = grp.id
JOIN entity_type et on et.id = xs.FK_TypeID
JOIN entity e on e.[type_id] = et.id
WHERE u.id = 184
AND e.confidential = 0
AND xs.[Read] = 1
GROUP BY e.id, e.[type_id], e.name
Translated to Linq to Sql:
var A = M.users
.Join(M.user_groups, u => u.id, ug => ug.user_id, (u, ug) => new { u = u, ug = ug })
.Join(M.usergroups, x => x.ug.group_id, grp => grp.id, (x, grp) => new { u = x.u, ug = x.ug, grp = grp })
.Join(M.access_entities, x => x.grp.id, ae => ae.group_id, (x, ae) => new { u = x.u, ug = x.ug, grp = x.grp, ae = ae })
.Join(M.entities, x => x.ae.entity_id, e => e.id, (x, e) => new { u = x.u, ug = x.ug, grp = x.grp, ae = x.ae, e = e })
.Where(x => x.u.id == Global.CurrentUser.id);
var B = M.users
.Join(M.user_groups, u => u.id, ug => ug.user_id, (u, ug) => new { u = u, ug = ug })
.Join(M.usergroups, x => x.ug.group_id, grp => grp.id, (x, grp) => new { u = x.u, ug = x.ug, grp = grp })
.Join(M.CRUDs, x => x.grp.id, xs => xs.FK_Group_ID, (x, xs) => new { u = x.u, ug = x.ug, grp = x.grp, xs = xs })
.Join(M.entity_types, x => x.xs.FK_TypeID, et => et.id, (x, et) => new { u = x.u, ug = x.ug, grp = x.grp, xs = x.xs, et = et })
.Join(M.entities, x => x.et.id, e => e.type_id, (x, e) => new { u = x.u, ug = x.ug, grp = x.grp, xs = x.xs, e = e })
.Where(x => x.u.id == Global.CurrentUser.id && x.xs.Read && x.e.confidential == 0);
var RestrictedEntities = A.Select(x => x.e).Union(B.Select(x => x.e));
The problem is that the Entity Framework doesn't show tables like user_group, etc, since it's just a 1:* connection table.
In Entity Framework, I can basically do:
IQueryable<IEnumerable<IEnumerable<entity>>> Entities = this.ObjectContext.users.Select(u => u.usergroups.Select(ug => ug.access_entity.Select(ae => ae.entity)));
Is there a way to have that returned as just a
IQueryable<entity>
?

Is SelectMany what you are after?
I believe
this.ObjectContext.users.SelectMany(
u => u.usergroups.SelectMany(
ug => ug.access_entity.Select(ae => ae.entity)));
should have type IEnumerable<entity>.

Related

SQL to Linq C# EntityFrameWork Query

I can't write this query on EntityFrameWork. İt's so simple but I don't know yet EF.* I need 4 table left join on EF.
select ProductId,Name,ValueName,Value from ProductTechnicalInfo p
left join ProductTechnicalInfoParameter pp on pp.ProductTechnicalInfoId = p.Id
left join ProductTechnicalInfoValue v on v.ProductTechicalInfoId = p.Id
left join ProductTechnicalInfoValueParameter vp on vp.TechnicalValuesId=v.Id
where ProductId = 22
My EF code :
var infos = infoProductsRep.Join(transaction.ProductTechnicalInfoParameter, p => p.Id, pp => pp.ProductTechnicalInfoId, (ProductTechnicalInfo, ProductTechnicalInfoParameter) => new
{
ProductTechnicalInfo,
ProductTechnicalInfoParameter
}).Join(transaction.ProductTechnicalInfoValue, p => p.ProductTechnicalInfo.Id, v => v.Id, (Info, Value) => new
{
Info,
Value
}).Join(transaction.ProductTechnicalInfoValueParameter, p => p.Value.Id, vp => vp.TechnicalValuesId, (Info, Result) => new
{
Info,
Result
}).Where(x => x.Info.Info.ProductTechnicalInfo.ProductId == product.Id).ToList();
It can be some issues with property names, but your query is easily convertible to LINQ:
var query =
from p in infoProductsRep
join pp in transaction.ProductTechnicalInfoParameter on p.Id equals pp.ProductTechnicalInfoId into gpp
from pp in gpp.DefaultIfEmpty()
join v in transaction.ProductTechnicalInfoValue on p.Id equals v.ProductTechicalInfoId into gv
from v in gv.DefaultIfEmpty()
join vp in transaction.ProductTechnicalInfoValueParameter on p.Id equals vp.TechnicalValuesId into gvp
from vp in gvp.DefaultIfEmpty()
where p.ProductId == 22
select new
{
p.ProductId,
pp.Name,
v.ValueName,
vp.Value
};
var result = query.ToList();

How to get record with max date with join?

How can I do this in LINQ?
select MAX(d.DepartureDateRange),MAX(d.ReturnDateRange)
from Tour t join
TourCategory tc on t.ID = tc.TourID
join TourDates td on t.ID = td.TourID
join Dates d on d.ID = td.DatesID
where tc.CategoryID = 3 and t.ID = 12
Database diagram is here ->
For example joins is like this but i cannot get Max of DepartureDateRange & ReturnDateRange
var query2 = from t in db.Tour
join tc in db.TourCategory on t.ID equals tc.TourID
join td in db.TourDates on t.ID equals td.TourID
join d in db.Dates on td.DatesID equals d.ID
where tc.CategoryID == 3
select new IndexTour
{
ID = t.ID,
TourName = t.TourName,
//DepartureDateRange =
//ReturnDateRange =
Description = t.SmallDesc,
Price = t.Price,
CoverPhotoUrl = t.CoverPhotoUrl,
TourProgram = t.TourDesc
};
Thanks in advance.
Here it is (dates are grouped by Tour):
var query2 =
from t in db.Tour
join tc in db.TourCategory on t.ID equals tc.TourID
where tc.CategoryID == 3
// join dates aggregates grouped by tour id
join tdates in
from td in db.TourDates
join d in db.Dates on td.DatesID equals d.ID
group d by td.TourID into grp
select new
{
tourID = grp.Key,
departure = grp.Max(g => g.DepartureDateRange),
rtrn = grp.Max(g => g.ReturnDateRange)
}
on t.ID equals tdates.tourID
select new IndexTour
{
ID = t.ID,
TourName = t.TourName,
DepartureDateRange = tdates.departure,
ReturnDateRange = tdates.rtrn,
Description = t.SmallDesc,
Price = t.Price,
CoverPhotoUrl = t.CoverPhotoUrl,
TourProgram = t.TourDesc
};
I think this is what you want?
var dateRanges = tours
.Join(tourCategories,
t => t.Id,
tc => tc.TourId,
(t, tc) => (t, tc))
.Join(tourDates,
ttc => ttc.t.Id,
td => td.TourId,
(ttc, td) => (ttc, td))
.Join(dates,
ttctd => ttctd.td.DateId,
d => d.Id,
(ttctd, d) =>
new {
TourId = ttctd.ttc.t.Id,
CategoryId = ttctd.ttc.tc.CategoryId,
DepartureDateRange = d.DepartureDateRange,
ReturnDateRange = d.ReturnDateRange
});
var filtered = dateRanges
.Where(r => r.CategoryId == 3 && r.TourId == 12);
var maxDepartureDateRange = filtered.Max(d => d.DepartureDateRange);
var maxReturnDateRange = filtered.Max(d => d.ReturnDateRange);

LINQ to SQL Get Latest Date from Object

I have read a few items on this, including How to select only the records with the highest date in LINQ but I don't know how to apply it to my case which is slightly more complex.
I am trying to get all AdjusterProfileStatusItem but only select the most recent s.statusDate. Currently, the query just returns all dates for all records; whereas I just want the most recent date for all records.
(from u in db.Users
join a in db.Adjusters
on u.id equals a.userID
join s in db.AdminAdjusterStatus
on a.id equals s.adjusterID
where u.userType.ToLower() == "adjuster"
&& s.status.ToLower() == "approved"
&& s.statusDate.Max() // causes syntax error...
select new AdjusterProfileStatusItem
{
user = u,
adjuster = a
})
Edit:
I have also tried this which gives me a syntax error...
(from u in db.Users
join a in db.Adjusters
on u.id equals a.userID
join s in db.AdminAdjusterStatus
on a.id equals s.adjusterID
where u.userType.ToLower() == "adjuster"
&& s.status.ToLower() == "approved"
group new { u, a, s } by s.adjusterID into x
select new AdjusterProfileStatusItem
{
user = u, // u does not exist in context
adjuster = a, // a does not exist in context
status = x.Max(y => y.statusDate) // anonymous type does not contain definition for 'statusDate'
})
I'm not sure how you feel about Lambda expressions but I would probably do this:
db.Users
.Join(db.Adjusters,
u => u.Id,
a => a.UserId,
(u, a) => new
{
User = u,
Adjuster = a
})
.Join(db.AdminAdjusterStatus,
a => a.Adjuster.Id,
s => s.AdjusterId,
(a, s) => new
{
User = a.User,
Adjuster = a.Adjuster,
AdminAdjusterStatus = s
})
.Where(x => x.User.userType == "adjuster"
&& x.AdminAdjusterStatus.status == "approved"
&& x.AdminAdjusterStatus.statusDate == db.AdminAdjusterStatus
.Where(y => y.AdjusterId ==
x.AdminAdjusterStatus.AdjusterId)
.Max(z => z.statusDate))
.Select(a => new AdjusterProfileStatusItem
{
user = a.User
adjuster = a.Adjuster
})
**EDIT!!!**
(from u in db.Users
join a in db.Adjusters
on u.id equals a.userID
join s in db.AdminAdjusterStatus
on a.id equals s.adjusterID
where u.userType.ToLower() == "adjuster"
&& s.status.ToLower() == "approved"
&& s.statusDate == GetMaxStatusDate(db.AdminAdjusterStatus.ToList(), s.AdjusterID)
select new AdjusterProfileStatusItem
{
user = u,
adjuster = a
})
private DateTime GetMaxStatusDate(List<AdminAdjusterStatus> statuses, int adjusterId)
{
return (from a in statuses
where a.AdjusterId == adjusterId
group a by a.AdjusterId into values
select values.Max(x => x.statusDate)).FirstOrDefault();
}
OR
(from u in db.Users
join a in db.Adjusters
on u.id equals a.userID
join s in db.AdminAdjusterStatus
on a.id equals s.adjusterID
where u.userType.ToLower() == "adjuster"
&& s.status.ToLower() == "approved"
&& s.statusDate == db.AdminAdjusterStatus
.Where(x => x.AdjusterId == s.AdjusterId)
.Select(y => y.statusDate)
.Max();
select new AdjusterProfileStatusItem
{
user = u,
adjuster = a
})

Entity Framework with Linq, inner Join, Group By, Order By

I have a SQL Query
select Firma.Name as companyName,
Taetigkeit.Taetigkeit as skillName,
SUM(Zeit) as time
from Zeiterfassung
inner join Firma On ZEiterfassung.FirmenID = Firma.ID
inner join Taetigkeit on Zeiterfassung.TaetigkeitID = Taetigkeit.ID
group by Taetigkeit, Firma.Name
order by Firma.Name
And want to "translate" it to linq. Here is what I tried:
var query = db.Zeiterfassung
.Where(x => x.Firma.ID == x.FirmenID && x.TaetigkeitID == x.Taetigkeit.ID)
.GroupBy(x => x.Taetigkeit.Taetigkeit1)
.Select(x => new Evaluation() { skillName = x.Key, time = x.Sum(y => y.Zeit), //skillName = x.Sum(x => x.Zeit), })
.OrderBy(x => x.skillName);
I dont know who to solve this with joins and the group by because all the time when i do a groupBy i cant access the other members.
From data you provided, I think query should look like
from z in db.Zeiterfassung
join f in db.Firma on z.FirmenID equals f.ID
join t in db.Taetigkeit on z.TaetigkeitID equals t.ID
select new { f.Name, t.Taetigkeit, z.Zeit) into x
group x by new { x.Taetigkeit, f.Name } into g
select new {
CompanyName = g.Key.Name,
SkillName = g.Key.Taetigkeit,
Time = g.Sum(i => i.Zeit)
}
Or with navigation properties:
db.Zeiterfassung
.Select(z => new { z.Zeit, z.Taetigkeit.Taetigkeit1, z.Firma.Name })
.GroupBy(x => new { x.Taetigkeit1, x.Name })
.Select(g => new Evaluation {
companyName = g.Key.Name,
skillName = g.Key.Taetigkeit1,
time = g.Sum(y => y.Zeit)
});

Convert aggregate SQL query to LINQ

I decided to try my hand at LINQ and so far its been a miserable failure. I need to convert the following SQL query to LINQ:
SELECT
MAX(A.NEXTPAYMENTDATE) as NextPaymentDate
, SUM(B.PurchasePrice) - SUM(A.Amount) AS BALANCE
, c.FirstName
, c.LastName
, b.[year]
, b.make
, b.model
FROM Payments A
JOIN Vehicles B ON A.VehicleId = B.Id
JOIN Customers C ON b.CustomerId = c.Id
GROUP BY VehicleId, c.FirstName, c.LastName, b.[year], b.make, b.model
HAVING SUM(B.PurchasePrice) - SUM(A.Amount) > 0
This is what I have so far. It seems to work to a certain extent, but I don't know how to progress from here.
var groupedpayments =
from payments in db.Payments
group payments by new { payments.VehicleId }
into paymentGroup
let maxDate = paymentGroup.Max(x => x.NextPaymentDate)
let paid = paymentGroup.Sum(x => x.Amount)
select
new { Payments = paymentGroup.Where(x => x.NextPaymentDate == maxDate)};
I think that is what you need.
var query =
Payments.Join(Vehicles, p => p.VehicleId, v => v.Id, (p, v) => new {p, v})
.Join(Customers, d => d.v.CustomerId, c => c.Id, (d, c) => new {d, c})
.GroupBy(r =>
new {
r.d.p.VehicleId,
r.d.v.year,
r.d.v.make,
r.d.v.model,
r.c.FirstName,
r.c.LastName
},
(g, data) =>
new {
FirstName = g.FirstName,
LastName = g.LastName,
Year = g.year,
Make = g.make,
Model = g.model,
NextPaymentDate = data.Max(dd => dd.d.p.NEXTPAYMENTDATE),
Balance = data.Sum(dd => dd.d.v.PurchasePrice)
- data.Sum(dd => dd.d.p.Amount)})
.Where(r => r.Balance > 0);

Categories

Resources