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();
Related
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)
....
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
};
I'm writing an application where I need the EvaluationRounds with a particular student.
Everything starts with the project. A project has many groups. A group has many members, but one member can also be in many groups. This is done by the associative table ProjectGroupMembers On the other hand, a project has many evaluation rounds.
Currently I have this linq statement:
from r in _context.EvaluationRounds.Include(e => e.EvaluationRoundProject.ProjectGroups.Select(pg => pg.Persons))
.Include(e => e.Evaluations)
join g in _context.ProjectGroups on r.ProjectId equals g.ProjectId
join m in _context.ProjectGroupMembers on g.ProjectGroupId equals m.GroupId
where m.PersonId == studentId && r.EvaluationRoundStartTime < DateTime.Now && r.EvaluationRoundEndTime > DateTime.Now
select r
We use the using statement to dispose of the dbcontext as soon as we have the list.
The problem is that the EvaluationRoundProject and its relatives are not loaded with the EvaluationRounds. This is what we get:
'((System.Data.Entity.DynamicProxies.EvaluationRound_7400F2ED13550F1E92655A802808E4B94D454A30979C80D0EEED31D0CB7D7005)(new System.Collections.Generic.Mscorlib_CollectionDebugView(activeEvaluationrounds).Items[0])).EvaluationRoundProject'
threw an exception of type 'System.ObjectDisposedException'
I have tried:
from r in _context.EvaluationRounds.Include("EvaluationRoundProject").Include(e => e.EvaluationRoundProject.ProjectGroups.Select(pg => pg.Persons)).Include(e => e.Evaluations)
join g in _context.ProjectGroups on r.ProjectId equals g.ProjectId
join m in _context.ProjectGroupMembers on g.ProjectGroupId equals m.GroupId
where m.PersonId == studentId && r.EvaluationRoundStartTime < DateTime.Now && r.EvaluationRoundEndTime > DateTime.Now
select r
and also
from r in _context.EvaluationRounds.Include(a => a.EvaluationRoundProject).Include(e => e.EvaluationRoundProject.ProjectGroups.Select(pg => pg.Persons)).Include(e => e.Evaluations)
join g in _context.ProjectGroups on r.ProjectId equals g.ProjectId
join m in _context.ProjectGroupMembers on g.ProjectGroupId equals m.GroupId
where m.PersonId == studentId && r.EvaluationRoundStartTime < DateTime.Now && r.EvaluationRoundEndTime > DateTime.Now
select r
Edit: The evaluations also do not load into the evaluationround
Edit2: this is the whole using code
using (_context = new PeerEvaluationContext())
{
var activeEvaluationrounds = from r in _context.EvaluationRounds.Include(e => e.EvaluationRoundProject.ProjectGroups.Select(pg => pg.Persons)).Include(e => e.Evaluations)
join g in _context.ProjectGroups on r.ProjectId equals g.ProjectId
join m in _context.ProjectGroupMembers on g.ProjectGroupId equals m.GroupId
where m.PersonId == studentId && r.EvaluationRoundStartTime < DateTime.Now && r.EvaluationRoundEndTime > DateTime.Now
select r;
return activeEvaluationrounds.ToList();
}
Edit 3: this problem occurs because lazy loading is used. But I went looking on the internet and they said the include part would take care of this.
I suspected that the error occured because of lazy loading. EvaluationRound or EvaluationRoundProject entities have navigation properties which is virtual and EF is attempting to load data in somewhere after _context already disposed. So, would you try to use another class to select query;
var activeEvaluationrounds = from r in _context.EvaluationRounds.Include(e => e.EvaluationRoundProject.ProjectGroups.Select(pg => pg.Persons)).Include(e => e.Evaluations)
join g in _context.ProjectGroups on r.ProjectId equals g.ProjectId
join m in _context.ProjectGroupMembers on g.ProjectGroupId equals m.GroupId
where m.PersonId == studentId && r.EvaluationRoundStartTime < DateTime.Now && r.EvaluationRoundEndTime > DateTime.Now
select new EvaluationRoundDto
{
EvaluationRoundId = r.EvaluationRoundId,
ProjectId = r.ProjectId
//etc.
};
I think you should check virtual navigation properties and where are they used after context already disposed.
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();
here is my linq code:
BOOK entity = db.BOOKS
.Where(s => s.ID == (from p in db.LIBRARY
from b in db.BOOKS
where (p.ID == 123) && (p.idpage == b.idpage)
select b.fields));
My actual oracle code is:
SELECT DISTINCT BOOKS.ID
FROM LIBRARY,BOOKS
WHERE LIBRARY.ID = 123 AND LIBRARY.ID = BOOKS.ID
But its showing the error in s.ID that..
Delegate 'System.Func Project.Models.BOOKS,int,bool' does not take 1 arguments
Why does this happen? Are there any workarounds?
Your SQL is using a join, so you can do the same thing in LINQ. Either of these approaches will suffice:
// join
var query = (from b in db.BOOKS
join p in db.LIBRARY on b.IdPage equals p.IdPage
where p.ID == 123
select b.Id).Distinct();
// 2 from statements (SelectMany) can also be used as a join
var query = (from b in db.BOOKS
from p in db.LIBRARY
where p.ID == 123 && b.IdPage == p.IdPage
select b.Id).Distinct();
// fluent syntax
var query = db.BOOKS
.Where(b => db.LIBRARY.Any(p =>
p.ID == 123 && b.IdPage == p.IdPage))
.Select(b => b.Id)
.Distinct();
s.ID is comparing to an Enumerable, so you get the error.
At the end of the LINQ query, add a SingleOrDefault().
Your subquery returns a sequence of values, not a single values, so you can't compare it to a scalar property like ID. You should use First on the result of the subquery to get the first result (or Single if there should be only one)
BOOK entity = db.BOOKS
.Where(s => s.ID == (from p in db.LIBRARY
from b in db.BOOKS
where (p.ID == 123) && (p.idpage == b.idpage)
select b.fields).First());
You should be able to use the navigation properties on your BOOKS class to do something like this:
var bookIds = db.BOOKS.Where(b => b.LIBRARIES.Any(l => l.ID == 123))
.Select(b => b.ID)