I need to construct a linq like this in regular sql query command:
select t1.vendorcode, t1.location, sum(t1.sales)
from table1 t1
where t1(vendorCode, location) in
(select t2.vendorCode, t2.location from table2 t2)
groupby t1.vendorCode, t1.location
I construct the linq as following:
query = from t1 in table1
where ...
join t2 in table2 on new
{
t2.vendorcode, t2.location
} equals new
{
t1.vendorcode, t1.location
}
The question I have is: How should I construct this linq? Do I need another subquery or can i add more group by and select statement to complete this linq?
You don't need to add another group by clause - you just need to select the sum:
var query = from t1 in table1
join t2 in table2
on new { t1.vendorcode, t1.location } equals
new { t2.vendorcode, t2.location }
group t1 by new { t1.vendorcode, t1.location } into g
select new {
g.Key.vendorcode,
g.Key.location,
g.Sum(t1 => t1.sale)
};
That will work if there's only a single record in table2 with any particular vendorcode/location pair. However, if there can be multiple records like that, then it doesn't work - and you probably want something more like:
var query = from t1 in table1
where table2.Select(t2 => new { t2.vendorcode, t2.location })
.Contains(new { t1.vendorcode, t1.location })
group t1 by new { t1.vendorcode, t1.location } into g
select new {
g.Key.vendorcode,
g.Key.location,
g.Sum(t1 => t1.sale)
};
That's logically your "exists" version.
This should do it
var query =
from t1 in table1
join t2 in table2
on new { vc = t1.vendorcode, lc = t1.location }
equals new { vc = t2.vendorcode, lc = t2.location }
group t1 by new { vc = t1.vendorcode, lc = t1.location };
Related
I have this Linq to entity query that returns a list of visitors with joins.
I want a similar query to return a single record without the query being a List collection, but changing it to a basic select with FirstOrDefaultAsync gets the error "A query body must end with a select clause or a group clause"
public async Task<List<VisitorDetail>> GetOneVisitor(int visitorId)
{
var query = await (from v in _context.Visitors
where v.Id == visitorId
join d in _context.Categories on v.VisitCategoryId equals d.Id
join c in _context.Counters on v.AssignedCounter equals c.Host into counterGroup
from cg in counterGroup.DefaultIfEmpty()
select new
{
FirstName = v.FirstName,
LastName = v.LastName,
CounterDescription = cg.Description,
VisitCategory = d.Description
}).ToListAsync();
List<VisitorDetail> visitors = new();
foreach (var p in query)
{
visitors.Add(new VisitorDetail
{
FirstName = p.FirstName,
LastName = p.LastName,
CounterDescription = p.CounterDescription,
CategoryDescription = p.VisitCategory
});
}
return visitors;
}
If you want to keep DRY with LINQ to Entities, return IQueryable for your common queries and invoke materialization only when it is needed.
Your method can be rewritten in the following way:
public IQueryable<VisitorDetail> GetVisitorDetails(int visitorId)
{
var query =
from v in _context.Visitors
where v.Id == visitorId
join d in _context.Categories on v.VisitCategoryId equals d.Id
join c in _context.Counters on v.AssignedCounter equals c.Host into counterGroup
from cg in counterGroup.DefaultIfEmpty()
select new VisitorDetail
{
FirstName = v.FirstName,
LastName = v.LastName,
CounterDescription = cg.Description,
CategoryDescription = d.Description
};
return query;
}
var many = await GetVisitorDetails(visitorId).ToListAsync();
var one = await GetVisitorDetails(visitorId).FirstOrDefaultAsync();
trying to do LINQ Update query using join with on condition also And condition
Following my SQL Query
UPDATE tbl_gs_related_orders
SET RelatedCOI = sop.ServiceOrderNo
FROM tbl_service_order_progress sop
JOIN tbl_gs_related_orders ro ON sop.parentid = ro.RelatedOrderParentId
AND ro.RelatedCOIIdentifier collate database_default = sop.InstanceIdentifier collate database_default
WHERE ro.ParentId = #PARENTID
AND ro.relatedorderparentid IS NOT NULL
This Query i want to convert into LINQ SO following my update LINQ query but getting some error like "the type of one of the expressions in the join clause is incorrect type inference failed in the call to join"
var updateQuery = (from c in ctxParser.TBL_SERVICE_ORDER_PROGRESS
join o in ctxParser.tbl_GS_Related_Orders on new { ParentId = c.ParentId, InstanceIdentifier = c.InstanceIdentifier }
equals new { RelatedOrderParentId = o.RelatedOrderParentId, RelatedCOIIdentifier = o.RelatedCOIIdentifier }
where ro.RelatedOrderParentId == sParentId && ro.RelatedOrderParentId != null
select new
{
ServiceOrderNo = c.ServiceOrderNo,
Order = o
});
foreach (var item in updateQuery)
{
item.Order.RelatedCOI = item.ServiceOrderNo;
}
ctxParser.SaveChanges();
Use same aliases when creating Anonymous type for equals clause:
from c in ctxParser.TBL_SERVICE_ORDER_PROGRESS
join o in ctxParser.tbl_GS_Related_Orders on new { ParentId = c.ParentId, InstanceIdentifier = c.InstanceIdentifier }
equals new { ParentId = o.RelatedOrderParentId, InstanceIdentifier = o.RelatedCOIIdentifier }
I'm a little bit new in LINQ field.I have a Delete query like this:
DELETE FROM Table1 WHERE FK IN (SELECT ID FROM Table2 WHERE UserId = #UId)
How can I change it into a LINQ query?
This should give you an idea
var itemQuery = from cartItems in db.SalesOrderDetails
where cartItems.SalesOrderID == 75144
select cartItems.ProductID;
var myProducts = from p in db.Products
where itemQuery.Contains(p.ProductID)
select p;
foreach (var detail in myProducts )
{
db.myProducts.DeleteOnSubmit(detail);
}
try
{
db.SubmitChanges();
}
catch (Exception e)
{
Console.WriteLine(e);
// Provide for exceptions.
}
SELECT StudentHistoryId, StudentId, Grade, CreatedAt, ModifiedAt, ModifiedBy, Active
FROM TABLENAME TN
INNER JOIN ( SELECT StudentId, MAX(ModifiedAt) AS ModifiedAt FROM TABLENAME GROUP BY StudentId) M
ON TN.StudentId = M.StudentId AND TN.ModifiedAt = M.ModifiedAt
Here's a direct translaton:
var subquery = from tn in dc.TABLENAME
group tn by tn.StudentId into g
select new { StudentId = g.Key, ModifiedAt = g.Max(x => x.ModifiedAt) };
var query = from tn in dc.TABLENAME
join m in subquery
on new { tn.StudentId, tn.ModifiedAt }
equals new { m.StudentId, m.ModifiedAt }
select new
{
tn.StudentHistoryId,
tn.StudentId,
tn.Grade,
tn.CreatedAt,
tn.ModifiedAt,
tn.ModifiedBy,
tn.Active
};
Looks like join cannot use sets defined inside query or am I doing something wrong?
from a in new[] {
new { Id = 1 },
new { Id = 2 } }
let bees = new[] {
new { Id = 2 },
new { Id = 3 } }
join b in bees on a.Id equals b.Id
select 1;
This one gives compile time error 'Element "bees" does not exist in the current context.' What's wrong with the query?
This is not legal either way you slice it - you cannot declare a range variable "in the middle" of a join - internally the let clause gets translated to a Select() statement with an anonymous type - but you cannot use Select() either in the middle of the join, you have to move it after the join.
Have a look at this question - I think it covers things:
Can i use join with let in linq - c#
Basically you can only use the let for the query, rather than for joins.
The following does seem to work, but its not as nice:
from a in new[] {
new { Id = 1 },
new { Id = 2 } }
join b in new[] {
new { Id = 2 },
new { Id = 3 } } on a.Id equals b.Id
select 1;