Can someone help me to translate this
var query = from s in context.ShoppingMalls
join h in context.Houses
on
new { s.CouncilCode, s.PostCode }
equals
new { h.CouncilCode, h.PostCode }
select s;
into lambda query?
Thanks.
var query = context.ShoppingMalls
.Join(
context.Houses,
s => new { s.CouncilCode, s.PostCode },
h => new { h.CouncilCode, h.PostCode },
(s, h) => s);
Although the example and answer given by #Thomas Levesque works for columns that match, I wanted to also supply the answer if you have columns to join on but they have different names. This is what I needed for my googling and this question got me close.
The difference of course is the explicit declaration of the columns as a variable to identify on.
var query = context.MapKitsToResources
.Join(
context.Resources,
o => new { Id = o.ResourceId, Type = o.ResourceTypeId},
i => new { Id = i.Id, Type = TypeId},
(o, i) = new { rType : i };
Related
Initially I have the following query in a function.
This query is used in the join in another query, which I didn't add due to its size.
var latestGuestRegistration = from c in Context.Guest
group c by c.PersonId
into cc
select new { PersonId = cc.Key, CreationTime = cc.Max(a => a.CreationTime) };
I would like to add a filter, however I could filter by name or email. So I would like to pass this filter as a function parameter.
I couldn't do this using C#'s inline SQL syntax, so I tried converting to LINQ:
var tmp = Context.GuestRegistrations
.Where(filter) // Here I filter by email or name
.GroupBy(x => x.PersonId)
.Select(cc => new { PersonId = cc.Key, CreationTime = cc.Max(a => a.CreationTime) })
.AsQueryable();
According to Rider, both implementations have the same data type, which is Queryable<{ID, CreationTime}>
// Joins above
join lt in tmp on
new { guestRegistration.PersonId, guestRegistration.CreationTime } equals
new { lt.PersonId, lt.CreationTime }
// Joins below
When this join is executed using my LINQ, it seems that it already returns the data, while the original solution enters as a subquery. How can I add a filter to my original query?
In the end, I would like something more or less like this:
Expression<Func<GuestRegistration,bool>> wherePredicate = registration => registration.FullName = "Gabriel";
var latestGuestRegistration = from c in Context.GuestRegistrations
where wherePredicate
group c by c.PersonId
into cc
select new { PersonId = cc.Key, CreationTime = cc.Max(a => a.CreationTime) };
Solution
Thanks to everyone who responded and commented, below is a summary of the final code.
private IQueryable<...> GetSearch(Expression<Func<G, bool>> filter) {
var filteredG= Context.G.Where(filter);
var latestG = from c in filteredG
group c by c.PersonId
into cc
select new { PersonId = cc.Key, CreationTime = cc.Max(a => a.CreationTime) };
var bigQuery = from ... join latestG ...
}
GetSearch(x => x.Fullname == "Gabriel")
Some expressions cannot be injected via Query syntax, but you can mix it with Method Chain syntax:
Expression<Func<GuestRegistration,bool>> wherePredicate = registration => registration.FullName = "Gabriel";
var guestRegistrations = Context.GuestRegistrations
.Where(wherePredicate);
var latestGuestRegistration =
from c in guestRegistrations
group c by c.PersonId
into cc
select new { PersonId = cc.Key, CreationTime = cc.Max(a => a.CreationTime) };
I've been using linq for a little while now but haven't come across this situation anywhere and my google-fu let me down.
Basically I have two data sets which I did not define and now have to use to return data.
class Header
{
string COMPANY_CODE
string REFERENCE_NBR
string REFERENCE_DUPLICATE
...
}
class Line
{
string COMPANY_CODE
string REFERENCE_NBR
string REFERENCE_DUPLICATE
string STOCK_CODE
string DESCRIPTION
...
}
From a database perspective they join like this
select *
from Header
inner join Line
on header.COMPANY_CODE = Line.COMPANY_CODE
and header.REFERENCE_NBR = Line.REFERNCE_NBR
and header.REFERENCE_DUPLICATE = LINE.REFERENCE_DUPLICATE
and have a 1:Many relationship.
I'm implementing a search feature for a listing that is meant to find any Lines that with a value in STOCK_CODE or DESCRIPTION that matches a given search term. I have seen a couple of methods of joining using a linq query but because of the multiple join conditions I'm a bit lost and have not found any examples of what I'm trying to do.
If I were to write the statement I am trying to get in lamda/linq in SQL it would be:
declare #searchtxt nvarchar(max) = 'test'
Select *
from header h
where exists (
select *
from Line l
where
(
l.stock_code like '%'+#searchtxt+'%'
or l.description like '%'+#searchtxt+'%'
)
and h.COMPANY_CODE = l.COMPANY_CODE
and h.REFERENCE_NBR = l.REFERENCE_NBR
and h.REFERENCE_DUPLICATE = l.REFERENCE_DUPLICATE
)
Any help would be appreciated!
Perhaps, this?
var result = header.Where(h =>
Line.Any(l => (l.stock_code.Contains(searchtxt)
|| l.description.Contains(searchtxt))
&& h.COMPANY_CODE == l.COMPANY_CODE
&& h.REFERENCE_NBR == l.REFERENCE_NBR
&& h.REFERENCE_DUPLICATE == l.REFERENCE_DUPLICATE));
This is a traditional LINQ query for better understanding,
string searchtext = "";
var result = (from h in context.Headers
join l in context.Lines on new { h.COMPANY_CODE, h.REFERENCE_DUPLICATE, h.REFERENCE_NBR } equals new { l.COMPANY_CODE, l.REFERENCE_DUPLICATE, l.REFERENCE_NBR }
where l.STOCK_CODE.Contains(searchtext) || l.DESCRIPTION.Contains(searchtext)
select new
{
COMPANY_CODE = h.COMPANY_CODE,
STOCK_CODE = l.STOCK_CODE
//You can select more fields from "h" and "l"
}).ToList();
Edit:
string searchtext = "";
var result = (from h in context.Headers
join l in context.Lines on new { h.COMPANY_CODE, h.REFERENCE_DUPLICATE, h.REFERENCE_NBR } equals new { l.COMPANY_CODE, l.REFERENCE_DUPLICATE, l.REFERENCE_NBR }
where l.STOCK_CODE.Contains(searchtext) || l.DESCRIPTION.Contains(searchtext)
select h
)
.GroupBy(x => new { x.COMPANY_CODE, x.REFERENCE_DUPLICATE, x.REFERENCE_NBR })
.Select(x => x.First())
.ToList();
db.Header.Join(
db.Line,
h => new { h.COMPANY_CODE, h.REFERENCE_NBR, h.REFERENCE_DUPLICATE },
l => new { l.COMPANY_CODE, l.REFERENCE_NBR, l.REFERENCE_DUPLICATE },
(h, l) => new
{
Header_COMPANY_CODE = h.COMPANY_CODE,
Header_REFERENCE_NBR = h.REFERENCE_NBR,
Header_REFERENCE_DUPLICATE = h.REFERENCE_DUPLICATE,
Line_Company_Code = l.COMPANY_CODE,
Line_REFERENCE_NBR = l.REFERENCE_NBR,
Line_REFERENCE_DUPLICATE = l.REFERENCE_DUPLICATE,
Line_STOCK_CODE = l.STOCK_CODE,
Line_DESCRIPTION = l.DESCRIPTION
}
)
.Where(w => w.Line_STOCK_CODE.Contains(searchText) || w.Line_DESCRIPTION.Contains(searchText))
.ToList();
I want to convert the following query to LINQ:
SELECT LV.* FROM LowerVehicles LV
INNER JOIN (Select VSerial,MAX(updatedOn) MaxUpdatedOn from LowerVehicles group by vserial) LVG
ON LV.VSerial = LVG.VSerial AND LV.updatedOn = LVG.MaxUpdatedOn
Not knowing your entities classes, here is an approximation. You can use query syntax or fluent syntax. Sometimes one is preferable over the other, and in the case of joins and grouping I prefer to use query syntax.
QUERY SYNTAX
var query = from LV in LowerVehicles
join LVG in (
from r in LowerVehicles
group r by r.vserial into g
select new {VSerial = g.Key, MaxUpdatedOn = g.Max(t => t.updatedOn)})
on LV.VSerial equals LVG.Vserial
and LV.updatedOn equals LVG.MaxUpdatedOn
select LV;
FLUENT SYNTAX
var lvg = LowerVehicles.GroupBy(t => t.vserial)
.Select(g => new {
VSerial = g.Key,
MaxUpdatedOn = g.Max(t => t.updatedOn)
});
var query = LowerVehicles.Join(
lvg,
a => new { a.VSerial, a.updatedOn },
b => new { b.VSerial, b.MaxUpdatedOn },
(a, b) => new { LV = a, LVG = b}
)
.Select(t=> t.LV);
Something like this?
Something.LowerVehicles
.Join(something.LowerVehicles.Select(y => new { y.VSerial, updatedOn = y.updatedOn.Max() }).GroupBy(z => z.VSerial),
x => new { x.VSerial, x.updatedOn },
lvg => new { lvg.VSerial, lvg.updatedOn },
(x, y) => x)
I have a c# code as follows
var deptSalesQuery =
from d in db.DashboardFigures
join s in outlets.Split(',').Select(x => int.Parse(x)) on d.OutletNo equals s
where (d.TypeOfinformation == "SALES")
group d by new
{
d.Number
} into newGroupedresult
select new DeptSales()
{
Dn = (int)newGroupedresult.Key.Number,
Qs = (double)newGroupedresult.Sum(d => d.Value_4),
Se = (double)newGroupedresult.Sum(d => d.Value_2),
Si = (double)newGroupedresult.Sum(d => d.Value_3)
+ (double)newGroupedresult.Sum(d => d.Value_2)
};
When I pass in Outlets = "1,2,3,4,....all the way upto 110", the software crashes telling me that there are too many nested statements.
Is there any way that I can remove the JOIN and add something onto the WHERE clause to help the situation?
Thanks
As written by juharr, before the query do:
int[] splitted = outlets.Split(',').Select(int.Parse);
and in the query:
where splitted.Contains(d.OutletNo) && d.TypeOfinformation == "SALES"
I spend a few hours trying to translate simple SQL to lambda LINQ
SELECT ID, AVG(Score) FROM myTable
GROUP BY ID
Any idea?
from t in myTable
group t by new {
t.ID
} into g
select new {
Average = g.Average(p => p.Score),
g.Key.ID
}
or Lambda
myTable.GroupBy(t => new {ID = t.ID})
.Select (g => new {
Average = g.Average (p => p.Score),
ID = g.Key.ID
})
The equivalent in Linq-to-Objects would be something like the below.
var results = from row in myTable
group row by row.Id into rows
select new
{
Id = rows.Key,
AverageScore = rows.Average(row => row.Score)
};
It's only slightly different for an ORM like entity framework. Namely, you would need to go through the data context or an appropriate DbSet/ObjectSet.
var _result = from a in myTable
group a by a.ID into g
select new
{
ID = g.Key.ID,
AverageResult = g.Average(x => x.Score)
}