Concentrating a join into a single column in linq query - c#

I have the following query:
var query = (from wo in _dbContext.WorkOrder
join opr in _dbContext.Operation
on wo.operationID equals opr.operationID
where wo.orderid == selectedorderid
select new {wo.orderid, wo.workOrderID, wo.itemID, wo.operationID, opr.operationName, wo.operationCode}).ToList();
I also have another table,which joins with workorder table,and returns multiple values.
What I want to do is,I want to join the table and get a single column of it as a concentrated column in my query such as (id1,id2,id3) etc. How can I achieve this?

What about:
var query = (from wo in _dbContext.WorkOrder
join opr in _dbContext.Operation
on wo.operationID equals opr.operationID
where wo.orderid == selectedorderid
select new {wo.orderid, wo.workOrderID, wo.itemID, wo.operationID, opr.operationName, wo.operationCode}).ToList();
var orders = queryGroupBy(i => i.workOrderID)
.Select(i => new {WorkOrderId = i.workOrderID, ConcatinatedIds = String.Join(", ", i.Select(j => j.operationID))})
.ToList();

Related

Select IN LINQ to entities with inner joins

I have the follow SQL query
SELECT ob.PK_OBJETIVO,
ev.NM_EVENTO,
ifi.QT_NOTA_IMPACTO,
imi.QT_NOTA_IMPACTO,
ire.QT_NOTA_IMPACTO,
(ifi.QT_NOTA_IMPACTO + imi.QT_NOTA_IMPACTO + ire.QT_NOTA_IMPACTO)/3 AS
Media
FROM AVALIACAO_IMPACTO AS ai
INNER JOIN EVENTO AS EV ON ev.PK_EVENTO = ai.FK_AVALIACAO_IMPACTO_EVENTO
INNER JOIN OBJETIVO AS ob ON ob.PK_OBJETIVO =
ai.FK_AVALIACAO_IMPACTO_OBJETIVO
INNER JOIN IMPACTO_FINANCEIRO AS ifi ON ifi.PK_IMPACTO_FINANCEIRO =
ai.FK_AVALIACAO_IMPACTO_IMPACTO1
INNER JOIN IMPACTO_MISSAO AS imi ON IMI.PK_IMPACTO_MISSAO =
AI.FK_AVALIACAO_IMPACTO_IMPACTO2
INNER JOIN IMPACTO_REPUTACAO AS IRE ON IRE.PK_IMPACTO_REPUTACAO =
AI.FK_AVALIACAO_IMPACTO_IMPACTO3
WHERE ai.FK_AVALIACAO_IMPACTO_OBJETIVO IN
(SELECT OBJ.PK_OBJETIVO
FROM OBJETIVO AS OBJ
WHERE OBJ.FK_OBJETIVO_PROCESSO = 3)
I need to transform that query in a LINQ query, I tried that:
var queryImpactos = await _context.AvaliacaoImpacto
.Where(e => _context.Objetivo.Select(o =>
o.ProcessoID).Contains(planoRiscos.Auditoria.ProcessoID))
.Include(e => e.Evento).Include(e => e.Objetivo)
.Include(e => e.ImpactoFinanceiro).Include(e =>
e.ImpactoMissao).Include(e => e.ImpactoReputacao).ToListAsync();
"planoRiscos.Auditoria.ProcessoID" returns what it takes, the number 3 of the pure SQL query, but the query result is returning all the records in the AVALIACAO_IMPACTO table, however I only need the records where a FK_OBJETIVO in AVALIACAO_IMPACTO exists within the OBJETIVO table, where the FK_PROCESSO in OBJETIVO is equal to the passed parameter (planoRiscos.Auditoria.ProcessoID).
Tip: whenever you need to convert SQL query to a LINQ query, make the query syntax your first choice.
Try this:
var queryImpactos = from ai in AVALIACAO_IMPACTO
join
ev in EVENTO on ai.FK_AVALIACAO_IMPACTO_EVENTO equals ev.PK_EVENTO
join ob in OBJETIVO on ai.FK_AVALIACAO_IMPACTO_OBJETIVO equals ob.PK_OBJETIVO
join ifi in IMPACTO_FINANCEIRO on ai.FK_AVALIACAO_IMPACTO_IMPACTO1 equals ifi.PK_IMPACTO_FINANCEIRO
join imi in IMPACTO_MISSAO on ai.FK_AVALIACAO_IMPACTO_IMPACTO2 equals imi.PK_IMPACTO_MISSAO
join IRE in IMPACTO_REPUTACAO on ai.FK_AVALIACAO_IMPACTO_IMPACTO3 equals IRE.PK_IMPACTO_REPUTACAO
where (from obj in OBJETIVO where obj.FK_OBJETIVO_PROCESSO == 3 select obj.PK_OBJETIVO).Contains(ai.FK_AVALIACAO_IMPACTO_OBJETIVO)
select new
{
ob.PK_OBJETIVO,
ev.NM_EVENTO,
QT_NOTA_IMPACTO1 = ifi.QT_NOTA_IMPACTO,
QT_NOTA_IMPACTO2 = imi.QT_NOTA_IMPACTO,
QT_NOTA_IMPACTO3 = IRE.QT_NOTA_IMPACTO,
Media = (ifi.QT_NOTA_IMPACTO + imi.QT_NOTA_IMPACTO + IRE.QT_NOTA_IMPACTO) / 3
};
Hope it's what you're looking for!

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
};

linq-sql join two tables and select columns

I'm new to sql-linq and I'm trying to join two tables using their common id which is motherid. I have done that but when I try to convert the returned value into list it throws an exception saying "The query contains references to items defined on a different data context." Here is the code.
var todaySecondVisitProfile = (from a in _maternalvisitvaluedb.Value
join b in _maternalcarevaluedb.Value on a.MotherId equals b.MotherID
where (DateTime)a.SecondVisit.Date == DateTime.Now.Date
select new
{
FirstName = b.FirstName,
LastName = b.LastName,
PhoneNo = b.PhoneNo
}).ToList();
If I can't convert the result into list how can I access my result? tnx for the help.
I think you are trying to do a Linq on two different databases. If so then you should so something like this:
var firstQuery = (from s in _maternalvisitvaluedb.Value select s).ToList();
var secondQuery = (from t in _maternalcarevaluedb.Value select t).ToList();
var result = (from s in firstQuery
join k in secondQuery
on s.MotherId equals k.MotherId
where (DateTime)s.SecondVisit.Date == DateTime.Now.Date
select s).ToList();

How do I write an Entity Framework 4 query for the following SQL?

I have an Entity Framework 4 model in my application. I need it to generate the following SQL:
SELECT *
FROM Reads AS R
INNER JOIN Images AS I ON R.ReadId = I.ReadId AND I.ImageTypeId = 2
LEFT OUTER JOIN Alarms AS A ON R.ReadId = A.ReadId AND A.DomainId IN (103,102,101,2,1,12) AND A.i_active = 1
LEFT OUTER JOIN ListDetails AS L ON L.ListDetailId = A.ListDetailId
WHERE R.i_active = 1
Here's what I have now for this query in my code:
var items = from read in query
join plate in context.Images on read.ReadId equals plate.ReadId
join temp1 in context.Alarms on read.ReadId equals temp1.ReadId into alarms from alarm in alarms.DefaultIfEmpty()
join temp2 in context.ListDetails on alarm.ListDetailId equals temp2.ListDetailId into entries from entry in entries.DefaultIfEmpty()
where plate.ImageTypeId == 2 && plate.IActive == 1
select new { read, plate, alarm, entry.OfficerNotes };
How do I modify the Entity Framework query to get the SQL query I need?
For Left Joins - I suggest using a from with a where instead of join, I find it makes it cleaner
For Inner Joins with multiple join conditions - you need to join on two matching anonymous types, or use a from with where conditions
For x IN list, you need to specify your list outside the query and use the Any method or Contains method
List<int> domainIds = new List<int>() { 103,102,101,2,1,12 };
var items = from read in query
join plate in context.Images
on new { read.ReadId, ImageTypeId = 2 } equals new { plate.ReadId, plate.ImageTypeId }
from alarm in context.Alarms
.Where(x => x.IActive == 1)
.Where(x => domainIds.Any(y => y == x.DomainId))
.Where(x => read.ReadId == x.ReadId)
.DefaultIfEmpty()
from entry in context.ListDetails
.Where(x => alarm.ListDetailId == x.ListDetailId)
.DefaultIfEmpty()
select new { read, plate, alarm, entry.OfficerNotes };

Add Join to this LINQ Query

I'm using the following query and am having trouble figuring out how to add a join into it:
var chi = Lnq.attlnks.Where(a => a.ownerid == emSysid)
.Select(c => new { sysid });
How can I join this to the "attach" table (ON attlnks.sysid = attach.sysid) and select "name" where sysid is the row id?
For joins in Linq the query expression form is typically more readable than lambda syntax - I believe this is what you are asking for:
var chi = from t in Lnq.attach
join a in Lnq.attlnks
on t.sysid equals a.sysid
where a.ownerid == emSysid
select t.name;
If there is only a single entry that should match at most, you can chain a FirstOrDefault() in this case (or other alternatives like SingleOrDefault, Single, First etc.):
var chi = (from t in Lnq.attach
join a in Lnq.attlnks
on t.sysid equals a.sysid
where a.ownerid == emSysid
select t.name).FirstOrDefault();
If I understood your problem, this should work fine:
var query = from a in attlinks
join aa in attach on a.sysid equals aa.sysid into a2
where a2.sysid == a2.ownerid
select a2.Name;

Categories