Nested query with Join in LINQ expression - linq

select DL.lat,
DL.lng,
DL.speed,
DL.trackedOn,
IL.speedLimit,
IL.deviceName,
IL.deviceId,
isnull(DeviceIcon, 'Content/images/beach-car.png') as DeviceIcon
from tb_DeviceLog DL
inner join (select inventoryLogId, max(trackedOn) as MaxDate
from tb_DeviceLog
group by inventoryLogId) IDL
on DL.inventoryLogId = IDL.inventoryLogId and Dl.trackedOn = IDL.MaxDate
inner join tb_InventoryLog IL
on DL.inventorylogid = IL.id
inner join tb_Logins LGN
on LGN.customers_id = IL.assignedToCustId
where LGN.userName='cadmin'
I need a lambda expression for the above query.
So far I have tried:
var query = db.tb_DeviceLog.Join(db.tb_DeviceLog, DL=>DL.inventoryLogId, DL1=>DL1.inventoryLogId, (DL,DL1)=> new{ DL1.inventoryLogId, DL1.trackedOn.Value}).GroupBy(a=>a.inventoryLogId)
But this is half of the result I want.

almost complex, i like that...
you need this:
var dbContext = new TestEntities();
dbContext.tb_DeviceLog
.Join(dbContext.tb_DeviceLog
.GroupBy(u => u.inventoryLogId)
.Select(u => new { inventoryLogId = u.Key, MaxDate = u.Max(t => t.trackedOn)}),
u => new { inventoryLogId = u.inventoryLogId, date = u.trackedOn},
u => new { inventoryLogId = u.inventoryLogId, date = u.MaxDate},
(DL , IDL) => new {DL, IDL})
.Join(dbContext.tb_InventoryLog,
u => u.DL.inventoryLogId,
u => u.id
(u, IL) => new { u.DL, u.IDL, IL })
.Join(dbContext.tb_Logins,
u => u.IL.assignedToCustId,
u => u.customers_id
(u, LGN) => new { u.DL, u.IDL, u.IL, LGN })
.Where(u => u.LGN.userName == "cadmin")
.Select(u => new
{
u.DL.lat,
u.DL.lng,
u.DL.speed,
u.DL.trackedOn,
u.IL.speedLimit,
u.IL.deviceName,
u.IL.deviceId,
// i don't know exactly, which table is containing this 'DeviceIcon', probably DL
u.DL.DeviceIcon == null ? "Content/images/beach-car.png" : u.DL.DeviceIcon
})
.ToList();

Related

SQL "IN" statement in Linq conversion

I have a SQL Query and I wanted to convert into LINQ can you please help to do this.
SELECT p.ProductID, p.ProductName FROM tblProducts p
WHERE p.ProductID IN (SELECT s.ProductID FROM tblStock s WHERE s.BarCode = 2222)
In this case BarCode is a null able type.
Use Contains to translate to 'IN':
tblProducts.Where(p => tblStock.Where(ts => ts.BarCode == 2222)
.Select(ts => ts.ProductId)
.Contains(p.ProductID))
.Select(p => new {p.ProductID, p.ProductName});
You should join instead of in:
var result = tblProducts
.Join
(
tblStock.Where(s => s.BarCode = 2222),
p => p.ProductID,
s => s.ProductID,
(p, s) => new { ProductID = p.ProductID, ProductName = p.ProductName }
);
Depending on your data and needs, you could also add .Distinct().
This should be written as an inner join for efficiency. In Linq:
var myQuery = from p in myContext.tblProducts
join s in myContext.tblStock on p.ProductID equals s.ProductID
where s.BarCode = 2222
select new { ProductID = p.ProductID, ProductName = p.ProductName };
foreach(var product in myQuery)
{
// do stuff
}

Convert query to lambda

I want to know how can I write this query:
var query = from p in context.DimProduct
from psc in context.DimProductSubcategory
// on psc.ProductCategoryKey equals pc.ProductCategoryKey
where psc.EnglishProductSubcategoryName == subCategoryName
&& psc.ProductSubcategoryKey == p.ProductSubcategoryKey
select new DimProductDTO
{
ProductKey = p.ProductKey,
ProductSubcategoryKey = p.ProductSubcategoryKey,
EnglishProductName = p.EnglishProductName,
Size = p.Size,
StandardCost = p.StandardCost
};
I tried some queries, but no success. My problem is that I don't know how to have access to DimProduct and DimProductSubcategory.
Any suggestions?
context.DimProduct
.SelectMany(p => new { p, psc = context.DimProductSubcategory })
.Where(x => x.psc.EnglishProductSubcategoryName == subCategoryName
&& x.psc.ProductSubcategoryKey == x.p.ProductSubcategoryKey)
.Select(x => new DimProductDTO {
ProductKey = x.p.ProductKey,
ProductSubcategoryKey = x.p.ProductSubcategoryKey,
EnglishProductName = x.p.EnglishProductName,
Size = x.p.Size,
StandardCost = x.p.StandardCost })
However, you're not selecting anything from DimProductSubcategory, so I think the same can be done using Any() extension method:
context.DimProduct
.Where(x => context.DimProductSubcategory
.Any(y => y.EnglishProductSubcategoryName == subCategoryName
&& y.ProductSubcategoryKey == x.ProductSubcategoryKey))
.Select(x => new DimProductDTO {
ProductKey = x.ProductKey,
ProductSubcategoryKey = x.ProductSubcategoryKey,
EnglishProductName = x.EnglishProductName,
Size = x.Size,
StandardCost = x.StandardCost });
It should generate IN SQL statement within the query.
That is not exactly same query, but it produces same result via inner join (I believe that is more efficient than cross join)
context.DimProduct
.Join(context.DimProductSubcategory
.Where(x => x.EnglishProductSubcategoryName == subCategoryName),
p => ProductSubcategoryKey,
psc => ProductSubcategoryKey,
(p,psc) => new { p, psc })
.Select(x => new DimProductDTO {
ProductKey = x.p.ProductKey,
ProductSubcategoryKey = x.p.ProductSubcategoryKey,
EnglishProductName = x.p.EnglishProductName,
Size = x.p.Size,
StandardCost = x.p.StandardCost })
Also your original query can be rewritten as
var query = from p in context.DimProduct
join psc in context.DimProductSubcategory
on p.ProductSubcategoryKey equals psc.ProductSubcategoryKey
where psc.EnglishProductSubcategoryName == subCategoryName
select new DimProductDTO {
ProductKey = p.ProductKey,
ProductSubcategoryKey = p.ProductSubcategoryKey,
EnglishProductName = p.EnglishProductName,
Size = p.Size,
StandardCost = p.StandardCost
};
Generated SQL will look like:
SELECT [t0].[ProductKey], [t0].[ProductSubcategoryKey]
FROM [DimProduct] AS [t0]
INNER JOIN [DimProductSubcategory] AS [t1]
ON [t0].[EnglishProductSubcategoryName] = [t1].[ProductSubcategoryKey]
WHERE [t1].[EnglishProductSubcategoryName] = #p0

Co-related Queries using lambda expressions

How can I convert this LINQ query from query syntax to method syntax? I am performing a co-related query operation.
var query = (from r in objEntities.Employee
where r.Location == (from q in objEntities.Department
where q.Location == r.Location
select q.Location).FirstOrDefault()
select new
{
FirstName = r.FirstName,
LastName = r.LastName,
Age = r.Age,
Location = r.Location
});
GridView1.DataSource = query;
GridView1.DataBind();
I think you are trying to convert the query to method-based query instead of syntax-based query.
var query = objEntities.Employee
.Where(e => e.Location == objEntities.Department
.Where(d => d.Location == r.Location)
.Select(d => d.Location)
.FirstOrDefault())
.Select(e => new {
FirstName = e.FirstName,
LastName = e.LastName,
Age = e.Age,
Location = e.Location
});
I'm also pretty sure your inner expression within where clause could be replaced with something like that:
.Where(e => objEntities.Department.Any(d => d.Location == e.Location)
Nested queries always have performance issue instead you should use join:
In the lambda expression query should be
var query = objEntities.Employee.Join(objEntities.Department, E => E.Location,
D => D.Location,
(E,D) => new {
FirstName = E.FirstName,
LastName = E.LastName,
Age = E.Age,
Location = E.Location
});

multiple JOIN + SUM() query in LINQ -> can't loop in view

I'm trying to translate an SQL query into LINQ, but after numerous attempts, I'm still not there... Can anyone help ?
This is my working SQL statement
SELECT Users.email, SUM(Skills.level) AS SkillLevel
FROM Skills INNER JOIN
SkillsPerUser ON Skills.pk_skill_id = SkillsPerUser.fk_skill_id INNER JOIN
Users ON SkillsPerUser.fk_user_id = Users.pk_userid
GROUP BY Users.email
ORDER BY SkillLevel DESC
This is what I came up with so far, but it lacks a sum() where I hard coded the number 3, that should be the sum of Skills.level:
var allSkillsPerUser = from u in dc.Users
join spu in dc.SkillsPerUsers on u.pk_userid equals spu.fk_user_id
join s in dc.Skills on spu.fk_skill_id equals s.pk_skill_id
select new { Email = u.email, Level = s.level } into su
group su by su.Email into gsu
select new { Email = gsu.Key, SkillLevel = gsu.Sum(su => su.Level) };
ViewBag.spu = allSkillsPerUser.ToList();
The view bag gives the following error (Email can't be found, while in the variables below you can see that they do exist...):
context.Skills
.Join(context.SkillsPerUser, s => s.pk_skill_id, spu => spu.fk_skill_id, (s, spu) => new { Skill = s, SkillToUser = spu })
.Join(context.Users, sspu => sspu.SkillToUser.fk_userId, u => u.pk_userid, (sspu, u) => new { Email = u.Email, SkillLevel = sspu.Skill.level })
.GroupBy(su => su.Email)
.Select(g => new { Email = g.Key, SkillLevel= g.Sum(su => su.Level) })
.OrderByDescending(g => g.SkillLevel)
It's a bit simpler if you have navigation properties set up on your entities:
context.SkillsPerUser
.Select(spu => new { Email = spu.User.email, Level = spu.Skill.level }) // guessing at the navigation property names here
.GroupBy(su => su.Email)
.Select(g => new { Email = g.Key, SkillLevel = g.Sum(su => su.Level) })
.OrderByDescending(g => g.SkillLevel)
Or, using the query syntax
from u in dc.Users
join spu in dc.SkillsPerUsers on u.pk_userid equals spu.fk_user_id
join s in dc.Skills on spu.fk_skill_id equals s.pk_skill_id
select new { Email = u.email, Level = s.level } into su
group su by su.Email into gsu
select new { Email = gsu.Key, SkillLevel = gsu.Sum(su => su.Level) }
To order by the sum you can do this:
from u in dc.Users
join spu in dc.SkillsPerUsers on u.pk_userid equals spu.fk_user_id
join s in dc.Skills on spu.fk_skill_id equals s.pk_skill_id
select new { Email = u.email, Level = s.level } into su
group su by su.Email into gsu
select new { Email = gsu.Key, SkillLevel = gsu.Sum(su => su.Level) } into userSkills
orderby userSkills.SkillLevel descending

How to Join in LINQ using Lambda expressions and get the result in DTO?

var query=from e in DataContext.Employees
join d in DataContext.Dept
on e.DeptId equals d.Id
join o in DataContext.OtherInfo
on e.Id equals o.EmployeeId
where e.EmployeeId==4
select new Employee_Dept//DTO
{
EmployeeName=e.Name,
DeptName=d.Name
EmployeeId=e.ID
DeptId=d.Id
ContactNo=o.ContactNo
}
I want to write it using Lambda expressions this is could write -
var query = DataContext.Employees.Join(Dept,e=>e.DeptId,d=>d.Id,(e,d)).Where(e=>e.EmployeeId=4)
can anyone help me complete this query. Thanks for your help.
I agree with Craig Stuntz that it is wrong usage of Join, but you can express the same LINQ query using extension methods in following way:
return DataContext.Employees
.Join(DataContext.Dept, e => e.DeptId, d => d.Id, (e,d) => new { Employee = e, Department = d })
.Join(DataContext.OtherInfo, s => s.Employee.Id, o => o.EmployeeId, (s, o) => new { Employee => s.Employee, Department = s.Department, OtherInfo = o })
.Where(e => e.Employee.Id == 4)
.Select(e => select new Employee_Dept//DTO
{
EmployeeName=e.Employee.Name,
DeptName=e.Department.Name
EmployeeId=e.Employee.ID
DeptId=e.Department.Id
ContactNo=e.OtherInfo.ContactNo
}
It's usually wrong to use join in LINQ to SQL. Just write:
var query=from e in DataContext.Employees
where e.EmployeeId==4
select new Employee_Dept//DTO
{
EmployeeName=e.Name,
DeptName=d.Dept.Name
EmployeeId=e.ID
DeptId=d.Dept.Id
}

Resources