I have a following SQL Query, which i have converted to Linq, and don't know how can i Convert this query into Lambda Expression.
SQL
SELECT BP.*
FROM [ams].[BackgroundPackage] AS BP
INNER JOIN [ams].[BkgPackageHierarchyMapping] AS BPHM
ON BP.BPA_ID = BPHM.BPHM_BackgroundPackageID
INNER JOIN [ams].[BkgOrderPackage] AS BOP
ON BPHM.BPHM_ID = BOP.BOP_BkgPackageHierarchyMappingID
INNER JOIN [ams].[BkgOrder] AS BO ON BOP.BOP_BkgOrderID = BO.BOR_ID
WHERE BO.BOR_MasterOrderID = #OrderID
AND BO.BOR_IsDeleted = 0
Lambda Version
// how to write lambda version of above query
Linq Version
var packageData =
(from ep in _dbContext.BackgroundPackages
join e in _dbContext.BkgPackageHierarchyMappings on ep.BPA_ID equals e.BPHM_BackgroundPackageID
join t in _dbContext.BkgOrderPackages on e.BPHM_ID equals t.BOP_BkgPackageHierarchyMappingID
join s in _dbContext.BkgOrders on t.BOP_BkgOrderID equals s.BOR_ID
where s.BOR_MasterOrderID == orderId
select new
{
Id = ep.BPA_ID,
Name = ep.BPA_Name,
});
the lambda query (concise notation) for your SQL would be:
var lambdaQuery = _dbContext.BackgroundPackages
.Join(_dbContext.BkgPackageHierarchyMappings, ep => ep.BPA_ID, e => e.BPHM_BackgroundPackageID, (ep, e) => ep)
.Join(_dbContext.BkgOrderPackages, ep => ep.BPHM_ID, t => t.BOP_BkgPackageHierarchyMappingID, (ep, t) => new { ep, t})
.Join(_dbContext.BkgOrders, ept => ept.t.BOP_BkgOrderID, s => s.BOR_ID, (ept, s) => new { ept.ep, s })
.Where(eps => eps.s.BOR_MasterOrderID == orderId && eps.s.BOR_IsDeleted == 0)
.Select(eps => eps.ep);
Related
This is my SQL query:
select
m.Name, s.Time, t.TheaterNumber
from
Movies m
join
MovieSeanceTheaters mst on mst.MovieId = m.MovieID
join
Theaters t on t.ID = mst.TheaterId
join
Seances s on mst.SeanceId = s.ID
This is my attempt at a Linq query:
var result = (from m in _context.Movies
join mst in _context.MovieSeanceTheaters on m.ID equals mst.MovieId
join t in _context.Theaters on mst.TheaterId equals t.ID
join s in _context.Seances on mst.TheaterId equals s.ID
select new { Film = m.Name, Salon = t.Name, Seans = s.Time }
).ToList();
I made this attempt, but I want to make with lambda for instance:
var result = movieManager.GetAll().Where(x => x.MovieSeanceTheaters)....
I couldn't do that.
If I understand you correctly, you want to rewrite your query from query syntax to method syntax?
Here we are!
var result = _context.Movies
.Join(_context.MovieSeanceTheaters,
m => m.MovieID,
mst => mst.MovieID,
(m, mst) => new
{
m = m,
mst = mst
})
.Join(_context.Theaters,
temp0 => temp0.mst.TheaterID,
t => t.ID,
(temp0, t) =>
new
{
temp0 = temp0,
t = t
})
.Join(_context.Seances,
temp1 => temp1.temp0.mst.TheaterID,
s => s.ID,
(temp1, s) =>
new
{
Film = temp1.temp0.m.Name,
Salon = temp1.t.TheaterNumber,
Seans = s.Time
});
Looks ugly, doesn't it?
Most often, the method syntax is more compact and convenient. But in this case, leave it as is.
Is it possible to join two from based on a local expression variable?
ex;
var query = from t in context.table1
from a in context.anothertable1.Where(x => t.id == a.id)
select new {a,t};
on line 2, the Where clause .Where(x => t.id == a.id) how would you move it into an expression?
I know i can do this;
Expression<Func<anothertable1, bool>> test = x => x.field1 == 1;
and It would work here;
var query = from t in context.table1
from a in context.anothertable1
.Where(x => t.id == a.id)
.Where(test)
select new {a,t};
and everything work and the sql query generated is as expected.
I can't figure out how to do the same with the other where.
EDIT
a more complex example, i anonymized it so it might not compile
var listOfMinMaxtable1 = (from n in context.table1.Where(table1Filter)
group n by n.table1_Number into grp
select new MinMaxtable1()
{
table1_Id_Max = grp.Max(x => x.table1_Id),
table1_Id_Min = grp.Min(x => x.table1_Id),
table1_Number = grp.Key
});
var listtable2 = (from t in context.table2
group t by t.table2_Id into grp
select new table2()
{
table2 = grp,
table2_Id = grp.Key
});
var query = from MinMax in listOfMinMaxtable1
//inner join **reference 1**
from table3 in context.table3
.Where(x => x.table_Number == MinMax.table_Number)
.Where(noticeMasterFilter) //a working expression<func<>>
//inner join **reference 2**
from Lasttable1 in context.table1
.Where(x => x.table_Id == MinMax.table_Id_Max)
//left join **reference 3**
from Firsttable1 in context.table1
.Where(x => x.table_Id == MinMax.table_Id_Min)
.Where(firstNoticeFilter) //a working expression<func<>>
.DefaultIfEmpty()
//left join **reference 4**
from Lasttable2 in listtable2
.Where(x => x.table_Id == MinMax.table_Id_Max)
.SelectMany(x => x.table2)
.Where(x => x.table2_Id == 123)
.OrderByDescending(x => x.table_Id)
.Take(1)
.DefaultIfEmpty()
if you find //left join reference 3 in the code above
that where clause; .Where(x => x.table_Id == MinMax.table_Id_Min)
might be sometime; .Where(x => x.table_Id == MinMax.table_Id_Max)
I could just copy/paste the whole from and change the where clause while adding noop pattern (an expression that return false and this make entity framework remove the whole thing so it doesn't affect the generated sql/result) with an expression on both from
for reference(this is noise to the question), the noop expression that i'm talking about is;
Expression<Func<table1, bool>> includeFrom= x => false;
and would be used like
//left join **reference 3**
from Firsttable1 in context.table1
.Where(x => x.table_Id == MinMax.table_Id_Min)
.Where(firstNoticeFilter) //a working expression<func<>>
.Where(includeFrom) //<--- this line make it a noop if the expression stay false
.DefaultIfEmpty()
but I don't want to do this if it's possible to make a custom expression that would go into the .Where()
Instead of creating an expression based on one type, you can create a combined type and use that for your where expression.
Two Table Combined Type
public class TwoTableDto
{
public Table1 t { get; set; }
public Table2 a { get; set; }
}
Query without expression
var query = (from t in context.table1
from a in context.anothertable1
select new TwoTableDto { t = t, a = a })
.Where(x => x.t.id == x.a.id);
Expression
Expression<Func<TwoTableDto, bool>> expr = x => x.t.id == x.a.id;
Query with expression
var query = (from t in context.table1
from a in context.anothertable1
select new TwoTableDto { t = t, a = a })
.Where(expr);
I Got This Lambda Expression But Does Not Work Correctly.Does Not Return Any Thing.Would You Help me Please on this:
var query = db.Cheque
.Join(db.Contracts,
C => C.ContractIDRef,
Con => Con.ContractID,
(C, Con) => new { Cheques1 = C, Contracts1 = Con })
.Join(db.Parties,
Con => Con.Contracts1.ContractID,
Pt => Pt.ContractIDRef,
(Con, Pt) => new { Contract2 = Con, Parites1 = Pt })
.Join(db.Persons,
Pt => Pt.Parites1.PartyIDRef,
P => P.PersonID,
(Pt, P) => new { Parites2 = Pt, Persons1 = P })
.Join(db.Company,
Pt => Pt.Parites2.Parites1.CompanyIDRef,
Com => Com.CompanyID,
(Pt, Com) => new { Parites3 = Pt, Company1 = Com })
.Join(db.Bank,
C => C.Parites3.Parites2.Contract2.Cheques1.BankIDRef,
B => B.BankID,
(C, B) => new { Cheque2 = C, Bank1 = B })
.Join(db.Flats,
Con => Con.Cheque2.Parites3.Parites2.Contract2.Contracts1.FlatIDRef,
F => F.FlatID,
(Con, F) => new { Contract3 = Con, Flat1 = F })
.Join(db.Projects,
F => F.Flat1.ProjectIDRef,
Pr => Pr.ProjectID,
(F, Pr) =>
new
{
ChequeNumber = F.Contract3.Cheque2.Parites3.Parites2.Contract2.Cheques1.ChequeNo,
ChequeIDRef = F.Contract3.Cheque2.Parites3.Parites2.Contract2.Cheques1.ChequeIDRef,
ChequePrice = F.Contract3.Cheque2.Parites3.Parites2.Contract2.Cheques1.Amount,
BankName = F.Contract3.Bank1.BankName,
BranchName = F.Contract3.Cheque2.Parites3.Parites2.Contract2.Cheques1.BranchName,
ChequeDate = F.Contract3.Cheque2.Parites3.Parites2.Contract2.Cheques1.ChequeDate,
AccountNumber = F.Contract3.Cheque2.Parites3.Parites2.Contract2.Cheques1.AccNo,
AccountOwner = F.Contract3.Cheque2.Parites3.Parites2.Contract2.Cheques1.ChequeOwnerName,
}
)
`.Where(Total => SelectedChequesList.Contains(Total.ChequeIDRef.Value)).ToList();
I will start with converting the above to the query syntax. While I'm a fan of the method syntax, using it in a complex queries involving multiple joins is a real pain. I needed a lot of time to read and try to follow the above query, so let do that:
var query =
from cheque in db.Cheque
join contract in db.Contracts on cheque.ContractIDRef equals contract.ContractID
join party in db.Parties on contract.ContractID equals party.ContractIDRef
join person in db.Persons on party.PartyIDRef equals person.PersonID
join company in db.Companies on party.CompanyIDRef equals company.CompanyID
join bank in db.Bank on cheque.BankIDRef equals bank.BankID
join flat in db.Flats on contract.FlatIDRef equals flat.FlatID
join project in db.Projects on flat.ProjectIDRef equals project.ProjectID
where SelectedChequesList.Contains(cheque.ChequeIDRef.Value)
select new
{
ChequeNumber = cheque.ChequeNo,
ChequeIDRef = cheque.ChequeIDRef,
ChequePrice = cheque.Amount,
BankName = bank.BankName,
BranchName = cheque.BranchName,
ChequeDate = cheque.ChequeDate,
AccountNumber = cheque.AccNo,
AccountOwner = cheque.ChequeOwnerName,
};
Now, one thing that can be seen is that most of the joins are not used. But let assume they are needed for some reason. Note that all the joins are INNER joins, so any of them can cause the query to return empty result if there is no matching record.
The problem is most probably in this join
join person in db.Persons on party.PartyIDRef equals person.PersonID
Instead of PartyIDRef I guess it should be something like PersonIDRef.
I need extra where clause for my Linq query. For example if customer choose a date filter so i need to date filter to my query etc... When i try to myQuery.Where predicate there is visible just group by's field.
How can i append new where condition to my query.
//for example i need dynamically append o.OrderDate==Datetime.Now or another where clause
var myQuery =(from o in _db.Orders
join l in _db.OrderLines.Where(x => x.ParaBirimi == model.ParaBirimi) on o.orderId equals
l.OrderId
where o.OrderDate.Value.Year == year1
group o by new {o.OrderDate.Value.Month}
into g
select
new
{
Month = g.Key.Month,
Total = g.Select(t => t.OrderLines.Sum(s => s.OrderTotal)).FirstOrDefault()
});
You are too late at the end of the query to add new Where. You have already grouped the data, and projected it, removing nearly all the fields.
Try:
var baseQuery = from o in _db.Orders
join l in _db.OrderLines.Where(x => x.ParaBirimi == model.ParaBirimi) on o.orderId equals l.OrderId
where o.OrderDate.Value.Year == year1
select new { Order = o, OrderLine = l };
if (something)
{
baseQuery = baseQuery.Where(x => x.Order.Foo == "Bar");
}
var myQuery = (from o in baseQuery
group o by new { o.Order.OrderDate.Value.Month }
into g
select
new
{
Month = g.Key.Month,
Total = g.Sum(t => t.OrderLine.OrderTotal)
});
Clearly you can have multiple if. Each .Where() is in && (AND) with the other conditions.
Note how the result of the join is projected in an anonymous class that has two properties: Order and OrderLine
I have an SQL expression
select S.SpecialtyName, COUNT(distinct SUC.SiteUserId) as Subscribers
from SiteUserContent SUC Inner join
Specialties S on SUC.SpecialtyId = S.SpecialtyId Inner join
SiteUser SU on SUC.SiteUserId = SU.SiteUserId
where SU.DeletedFlag = 0
group by S.SpecialtyName
Order by S.SpecialtyName
What will be the corresponding LINQ expression for the same?
from suc in context.SiteUserContent
join s in context.Specialties on suc.SpecialtyId equals s.SpecialtyId
join su in context.SiteUser on suc.SiteUserId equals su.SiteUserId
where su.DeletedFlag == 0
select new { suc.SiteUserId, s.SpecialityName } into x
group x by x.SpecialityName into g
orderby g.Key
select new {
SpecialityName = g.Key,
Subscribers = g.Select(i => i.SiteUserId).Distinct().Count()
}
Generated SQL will not be same, but I think result of query execution should be same.
var results = contex.SiteUserContent
.Join(context.Specialties, suc => suc.SpecialtyId, s => s.SpecialtyId, (suc, s) => new { suc, s })
.Join(context.SiteUser, i = i.suc.SiteUserId, su => su.SiteUserId, (i, su) => new { suc = i.suc, s = i.s, su = su })
.Where(i => i.su.DeletedFlag == 0)
.GroupBy(i => i.s.SpecialtyName)
.Select(g => new {
SpecialityName = g.Key,
Subscribers = g.Select(i => i.suc.SiteUserId)
.Distinct()
.Count()
})
.OrderBy(i => i.SpecialityName);