How to do this query using expression in LINQ? - c#

select t.*
from Task t
inner join Project p on a.ProjectId = t.ProjectId
where p.ProjectTypeId IN ( select ptg.ProjectTypeId
from UserGroup ug
inner join ProjectTypeGroup ptg on ug.GroupId = ptg.GroupId
where ug.UserId = 1 -- MUTABLE VALUE
)

In the attempt query given by you, I don't see Task being used.
Since there is no relation between your sub-query and your main query, you should split them in to two queries:
var projTypeIds = (from ug in UserGroup
join ptg in ProjectTypGroup on ug.GroupId equals ptg.GroupId
where ug.UserId == 1
select ptg.ProjectTypeId).ToList()
Once you have your output, check for .Contains
var task = (from t in Task
join p in Project on p.ProjectId equals t.ProjectId
where projTypeIds.Contains(p.ProjectTypeId)
select t).FirstOrDefault();
I assume you need only one object from this query hence used .FirstOrDefault(), if you are expecting a list using .ToList()

You can use this.
from t in Task
join p in Project
on t.ProjectId equals p.ProjectId
let subQ = ( from ug in UserGroup
join ptg in ProjectTypeGroup
on ug.GroupId equals ptg.GroupId
where ug.UserId == 1
select ptg.ProjectTypeId)
where subQ.Contains(p.ProjectTypeId)
select t
or you can use this.
int loggedUserId = 1;
var _userGroups =
UserGroup.Join(ProjectTypeGroup,
t => t.GroupId, p => p.GroupId,
(t, p) => new {t, p})
.Where(n => n.t.UserId == loggedUserId)
.Select(s => s.p.ProjectTypeId);
var projectTypeIds =
Task.Join(Project,
t => t.ProjectId, p => p.ProjectId,
(t, p) => new {t, p})
.Where(n => _userGroups.Contains(n.p.ProjectTypeId) )
.Select(n => n.t);
projectTypeIds.ToList();

Related

navigation property vs using left join

I have this linq statement where I want to convert into navigation property. The linq statement has a left join so I am not sure how to do that with the navigation property. I am using EF 6.0.0.0. I am trying to get all the MeetingPollingResponseTexts if there is values or nulls.
MeetingPollingParticipantsAnswers = (from p in db.MeetingPollingParticipants
join mp in db.MeetingPollings on p.MeetingPollingId equals mp.MeetingPollingId
join pq in db.MeetingPollingQuestions on mp.MeetingPollingId equals pq.MeetingPollingId
join pp in db.MeetingPollingParts on pq.MeetingPollingQuestionId equals pp.MeetingPollingQuestionId
join pv in db.MeetingPollingPartsValues on pp.MeetingPollingPartsId equals pv.MeetingPollingPartsId
join rt in db.MeetingPollingResponseTexts on pv.MeetingPollingPartsValuesId equals rt.MeetingPollingPartsValuesId into lj_rt
from rt in lj_rt.DefaultIfEmpty()
where p.MeetingPollingId == MeetingPollingId && p.CustomerId == CustomerId
select new Model.MeetingPollingParticipantsAnswers
{
QuestionValue = pv.QuestionValue,
MeetingPollingQuestionResponseText = rt.MeetingPollingQuestionResponseText,
}).ToList();
var meetingParticipantsAnswers = db.MeetingPollingParticipants
.Include(x => x.MeetingPolling)
.Include(x => x.MeetingPollingQuestions
.Select(q => q.MeetingPollingParts
.Select(i => i.MeetingPollingPartsValues)))
.Where(p => p.CustomerId == CustomerId && p.MeetingPollingId == MeetingPollingId).ToList();

Add 'where' clausures dynamically to linq query

I have this linq query:
var query = (from dc in context.Table1.Include(d => d.Doc)
join u in _context.Table2 on dc.IDDoc equals u.IDDoc
where dc.ID == id && u.IDUser == user.IDUser
select dc)
.Union(from dc in context.Table1.Include(d => d.Doc)
join p in _context.Table3 on dc.IDDoc equals p.IDDoc
where dc.ID == id
select dc);
And I want to add more where conditions dynamically depends of a list (List ids)
What I want to achieve is something like this:
Imagine that I have a List ids = new(){1, 2, 5, 27);
What I want to do is to add that info into this part of the query to have something like this:
.Union(from dc in context.Table1.Include(d => d.Doc)
join p in _context.Table3 on dc.IDDoc equals p.IDDoc
where dc.ID == id && p.ID == 1 || p.ID == 2 || p.ID == 5 || p.ID = 27
select dc)
But if next time list is List ids = new(){4}, query should look like:
.Union(from dc in context.Table1.Include(d => d.Doc)
join p in _context.Table3 on dc.IDDoc equals p.IDDoc
where dc.ID == id && p.ID == 4
select dc)
Is it even possible? If not, what would be a possible solution?
Thank you
EDIT: I made up with this query because I have no clue about how to add it to my main query.
What I really have is this:
var mainQuery = _context.RootTable
.Include(i => i.Items).ThenInclude(dc => dc.Docs)
.Include(i => i.Items).ThenInclude(sg => sg.Signs)
.FirstOrDefault(m => m.ID== id);
And what I want to do is to filter the ".ThenInclude(dc => dc.Docs) with the other query. I can't figure out how to do it in a better and efficient way that with two sepparate queries.
Use Enumerable.Contains:
List<int> ids = new(){4};
....
.Union(from dc in context.Table1.Include(d => d.Doc)
join p in _context.Table3 on dc.IDDoc equals p.IDDoc
where dc.ID == id && ids.Contains(p.ID) // here
select dc)
....

What is the linq equivalent for the TSQL with join and group by?

I'm trying to create a linq query from the following sql.
Couldn't find an example that had a join in it with multiple tables and a group by that had different fields from different tables.
select t2.field1, t1.field1, count(t2.field1) from Table1 t1
join Table2 t2 on t1.pkfield = t2.pkfield
group by t2.field1, t1.field1
having count(*) > 1
order by t2.pkfield1
Tried the following:
var test =
from t1 in db.Table1
join t2 in db.Table2 on t1.pkfield equals t2.pkfield
group x by (t1.field1, t2.field1)
select t1.field1, t2.field2
You do not post entity classes and input examples so I can't verify my code. But I hope that concept is clear
db.Table1.SelectMany(t1 => db.Table2.Select(t2 => new { t2.field1, t1.field1, t2.pkfield1 }))
.GroupBy(x => new { t1Field1 = t2.field1, t2Field1 = t1.field1 })
.Where(g => g.Count() > 1)
.OrderBy(g => g.Min(x => x.pkfield1))
.Select(g => new { g.Key.t1Field1, g.Key.t2Field1, g.Count() });
In code above db is your custom DbContext and SelectMany will be translated into inner join
I don't know how to do it in a single query, but I have accomplished something similar as follows. Hope it helps you or at least points you in the right direction.
var result = from p in person
join o in orders on p.OrderId equals o.OrderId
// build your custom object with columns from multiple tables.
select new { o.OrderId, p.OrderId};
// now group the result
var grouped = result.GroupBy(x => x.OrderId)
.Where(y=> y.Count() > 1);

Select multiple joined tables into multiple variables in SQL queries or LINQ

SELECT O.*, U.*, C.*, P.*, S.*
INTO OV, Usuarios, Clientes, Proposta, Status
FROM[dbo].[TB_OV] O
INNER JOIN dbo.TB_Usuarios U on U.id = O.userinsert
INNER JOIN dbo.TB_Clientes C on C.id = O.ENDFAT
INNER JOIN dbo.TB_Status S on S.id = O.status
LEFT JOIN TB_Proposta P on P.id = O.ID_PROP
WHERE O.status = 214 ORDER BY O.DTSOL, O.DtdeFaturamento
I am developing a web system in C# and one of the queries that I am trying to do is this one...
I want to know what is the correct syntax to do that or something like this.
What I need to know exactly is how to select this five tables into five different variables like an object to each one that I can cast later in C# to turn into object typed.
Otherwise, I've tried to do it with LINQ to SQL from C# and I still did not get any results from queries in LINQ to SQL to these tables.
Lambda:
var query = db.TB_OV
.Join(db.TB_Usuarios, OV => OV.USERINSERT, U => U.ID, (OV, U) => new { OV, U })
.Join(db.TB_Clientes, Z => Z.OV.ENDFAT, CL => CL.ID, (Z, CL) => new { Z, CL })
.Join(db.TB_Status, Z => Z.Z.OV.STATUS, ST => ST.ID, (Z, ST) => new { Z, ST })
.Join(db.TB_Proposta, Z => Z.Z.Z.OV.ID_PROP, P => P.ID, (Z, P) => new { Z, P })
.Where(Z => Z.Z.Z.Z.OV.STATUS == 214)
.Select(Z => new OperacoesListaSolFaturamento
{
OV = Z.Z.Z.Z.OV,
Usuarios = Z.Z.Z.Z.U,
Clientes = Z.Z.Z.CL,
Status = Z.Z.ST,
Proposta = Z.P
});
Fluent:
var query = from O in db.TB_OV
join U in db.TB_Usuarios on O.USERINSERT equals U.ID
join C in db.TB_Clientes on O.ENDFAT equals C.ID
join S in db.TB_Status on O.STATUS equals S.ID
join P in db.TB_Proposta on O.ID_PROP equals P.ID
where O.STATUS == 214
select new OperacoesListaSolFaturamento
{
OV = O,
Usuarios = U,
Clientes = C,
Status = S,
Proposta = P
};
Is there any way to do that? Either by LINQ or SQL queries.
For translating SQL to LINQ query comprehension:
Translate FROM subselects as separately declared variables.
Translate each clause in LINQ clause order, translating monadic and aggregate operators (DISTINCT, TOP, MIN, MAX etc) into functions applied to the whole LINQ query.
Use table aliases as range variables. Use column aliases as anonymous type field names.
Use anonymous types (new { ... }) for multiple columns.
LEFT JOIN is simulated by using into joinvariable and doing another from from the joinvariable followed by .DefaultIfEmpty().
Replace COALESCE with the conditional operator (?:)and a null test.
Translate IN to .Contains() and NOT IN to !...Contains().
Translate x BETWEEN low AND high to low <= x && x <= high.
SELECT * must be replaced with select range_variable or for joins, an anonymous object containing all the range variables.
SELECT fields must be replaced with select new { ... } creating an anonymous object with all the desired fields or expressions.
Proper FULL OUTER JOIN must be handled with an extension method.
So the main problem with your fluent query is you didn't translate the LEFT JOIN properly:
var query = from O in db.TB_OV
where O.STATUS == 214
join U in db.TB_Usuarios on O.USERINSERT equals U.ID
join C in db.TB_Clientes on O.ENDFAT equals C.ID
join S in db.TB_Status on O.STATUS equals S.ID
join P in db.TB_Proposta on O.ID_PROP equals P.ID into Pj
from P in Pj.DefaultIfEmpty()
orderby O.DTSOL, O.DtdeFaturamento
select new OperacoesListaSolFaturamento
{
OV = O,
Usuarios = U,
Clientes = C,
Status = S,
Proposta = P
};

How can I write a linq query for this?

I need to write following query in Linq to SQL but not sure what is the best way of doing, given it has two derived tables. Any suggestions.
SELECT A.ID
FROM
(
SELECT *
FROM Orders
WHERE ProductID = 5
) A
JOIN
(
SELECT CustomerID, MAX(Price) Price
FROM Orders
WHERE ProductID = 5
GROUP BY CustomerID
) B
ON A.CustomerID = B.CustomerID and A.Price = B.Price
var b = (
from o in db.Orders
where o.ProductID == 5
group o by o.CustomerID into og
select new {
CustomerID = og.Key
Price = Max(og.Price)
}
);
var a = (
from o in db.Orders
join p in b on new {a.CustomerID, a.Price} equals
new {b.CustomerID, b.Price}
where o.ProductID == 5
select a.ID
);
var r = a.ToString();
These two links are invaluable when forming things like this:
http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
http://msdn.microsoft.com/en-us/vstudio/bb688085
Can you simplify this with LINQ, especially if you use method syntax instead of query syntax.
orders.Where(o => o.ProductID == 5)
.GroupBy(o => o.CustomerID)
.SelectMany(g => g.Where(o => o.Price == g.Max(m => m.Price)));
My advice when writing LINQ, do not simply attempt to convert a SQL statement exactly. Think about the desired result and develop a solution designed for LINQ.
Something along these lines:
var result = from a in context.Orders
join b in (context.Orders.Where(o => o.ProductID == 5).GroupBy(o => o.CustomerID).Select(g => new { CustomerID = g.Key, Price = g.Max(o => o.Price)))
on new {a.CustomerID, a.Price} equals new {b.CustomerID, b.Price}
where a.ProductID == 5
select a.ID;

Categories

Resources