NULL Subcollections in framework, OK in LINQPad - c#

i have this inherited SQL view code that I converted to linq to get some data out in the meantime, in LINQPad it works as expected, but upon transferring it to my c# solution, the subcollections are not loaded.
var query = from poh in _pckOrderHeadeRepository.GetAllIncluding(pd => pd.PckOrderDetail)
join mcs in _mstrConsigneeShipToRepository.GetAll() on poh.RouteId equals mcs.Consignee
//select new {poh, mcs}; //works
join det in (
from d in _pckOrderDetailRepository.GetAllIncluding(pd=> pd.PckOrderHeader, pd => pd.MstrSku)
join s in (
from shpCartonHeader in _shpCartonHeaderRepository.GetAll()
group shpCartonHeader by new
{
shpCartonHeader.OrderNum
}
into g
select new
{
g.Key.OrderNum,
CartonWeight = g.Sum(p => p.TotalWeight)
}) on d.PckOrderHeader.OrderNum equals s.OrderNum into sJoin
from s in sJoin.DefaultIfEmpty()
group new {d.PckOrderHeader, d, d.MstrSku, s} by new
{
d.PckOrderHeader.OrderNum
}
into g
select new
{
g.Key.OrderNum,
OrderQty = g.Sum(p => p.d.OrderQty),
OrderWeightOpen = (decimal?)g.Where(p => p.d.PckOrderHeader.OrderStat.Equals("OPEN")).Sum(p => p.d.MstrSku.Weight * p.d.OrderQty),
OrderWeightReleased = (decimal?)g.Where(p => p.d.PckOrderHeader.OrderStat.Equals("RELEASED")).Sum(p => p.d.MstrSku.Weight * p.d.PickingQty + p.s.CartonWeight),
OrderWeightPacked = (decimal?)g.Where(p => p.d.PckOrderHeader.OrderStat.Equals("PACKED")).Sum(p => p.s.CartonWeight),
PrePack = g.Max(p => p.d.MstrSku.Prepack)
}) on poh.OrderNum equals det.OrderNum
join toa in _shpTrailerOrderAssignmentRepository.GetAll() on poh.OrderNum equals toa.OrderNum into
toaJoin
from toa in toaJoin.DefaultIfEmpty()
select new
{
det,
poh,
toa,
mcs
};
this part in particular:
select new
{
g.Key.OrderNum,
OrderQty = g.Sum(p => p.d.OrderQty),
OrderWeightOpen = (decimal?)g.Where(p => p.d.PckOrderHeader.OrderStat.Equals("OPEN")).Sum(p => p.d.MstrSku.Weight * p.d.OrderQty),
OrderWeightReleased = (decimal?)g.Where(p => p.d.PckOrderHeader.OrderStat.Equals("RELEASED")).Sum(p => p.d.MstrSku.Weight * p.d.PickingQty + p.s.CartonWeight),
OrderWeightPacked = (decimal?)g.Where(p => p.d.PckOrderHeader.OrderStat.Equals("PACKED")).Sum(p => p.s.CartonWeight),
PrePack = g.Max(p => p.d.MstrSku.Prepack)
}) on poh.OrderNum equals det.OrderNum
for example this:
PrePack = g.Max(p => p.d.MstrSku.Prepack) // MstrSku is not loaded
and the property inside p.d (PckOrderDetail)
public virtual MstrSku MstrSku { get; set; }
the equivalent query in linqpad works correctly, so im wondering what am I missing to properly load the sub properties to mimic LINQPads behaviour.

if you want to use p.d.MstrSku.Prepack then you have to include it in the outer table. when you include it in joined table you cannot select.
use it in the first line like the sample below
.Include(x => x.OrderDetails.Select(y => y.MstrSku)).ToList();

Related

SQL to LINQ Involving Multiple GroupJoin

I have a SQL Query and would like to convert into LINQ Method Syntax (Lambda) but it seems that I am stuck at the multiple group join and it confuses me.
Below is the SQL that I wanted to change into LINQ
select MerchantUserId, usex.Nickname, MAX(OrderTransaction.CreatedDate) as LastOrderDate, sd.Url, st.Name as storename
from OrderTransaction
left join UserExtend usex
on usex.Id = OrderTransaction.MerchantUserId
left join StoreDomain sd
on sd.StoreId = usex.StoreId
left join store st
on st.id = sd.StoreId
where OrderTransaction.Status <> 8
and sd.IsPrimary = 1
group by MerchantUserId,usex.Nickname,sd.Url,st.Name
order by LastOrderDate desc
Below is the query that I tried to link all three tables together. Am I doing it correctly in terms of linking 3 tables together?
var list = _ApplicationDbContext.UserExtend
.GroupJoin(_ApplicationDbContext.OrderTransaction, usex => usex.Id, ord => ord.MerchantUserId, (usex, ord) => new { usex, ord})
.GroupJoin(_ApplicationDbContext.StoreDomain, usexOrd => usexOrd.usex.StoreId, sd => sd.StoreId, (usexOrdStoreDom, sd) => new { usexOrdStoreDom , sd})
.GroupJoin(_ApplicationDbContext.Store, usexOrdStoreDom => usexOrdStoreDom.usexOrdStoreDom.usex.StoreId, st => st.Id, (usexOrdStoreDomStore , st ) => new { usexOrdStoreDomStore, st })
The equivalent of your SQL query is the following link phrase.
The GroupJoin is for when you want to match a value with several values.
For more information, you can refer to this link: Linq to Entities join vs groupjoin
var list = _ApplicationDbContext.UserExtend.Join(_ApplicationDbContext.OrderTransaction,
usex => usex.Id,
ord => ord.MerchantUserId,
(usex, ord) => new { usex, ord })
.Join(_ApplicationDbContext.StoreDomain,
usexOrd => usexOrd.usex.StoreId,
sd => sd.StoreId,
(usexOrd, sd) => new { usexOrd, sd })
.Join(_ApplicationDbContext.Store,
usexOrdStoreDom => usexOrdStoreDom.sd.StoreId,
st => st.Id,
(usexOrdStoreDom, st) => new { usexOrdStoreDom, st })
.GroupBy(a => new { a.usexOrdStoreDom.usexOrd.ord.MerchantUserId, a.usexOrdStoreDom.usexOrd.usex.Nickname, a.usexOrdStoreDom.sd.Url, a.st.Name, a.usexOrdStoreDom.usexOrd.ord.CreatedDate })
.OrderBy(a => a.Key.CreatedDate)
.Select(a => new
{
MerchantUserId = a.Key.MerchantUserId,
Nickname = a.Key.Nickname,
Url = a.Key.Url,
storename = a.Key.Name,
LastOrderDate = a.Max(x => x.usexOrdStoreDom.usexOrd.ord.CreatedDate)
})
.ToList();

How GroupBy can be used in LINQ?

I have a following code:
var sql = db.Accounts.AsNoTracking()
.Join(db.Customers.AsNoTracking(),
d => d.AccountNr, c => c.CustNr,
(d, c) => new {Accounts = d, Customers = c })
.GroupBy(g => g.Accounts.AccountNr)
.Where(w => w.Accounts.Date == null)
.Select(s => new
{
Company = s.Customers.CompName,
TWQ = s.Customers.TWQ,
AccountNr = s.Accounts.AccountNr,
DocDate = s.Accounts.DocumentDate,
Income = s.Customers.Income
})
.OrderBy(o => o.DocDate);
The issue is that c# underlines the whole WHERE part with an alert saying that: Element IGrouping <string,> has no definition of Accounts and extension method of Accounts can not be found
I don't know where the problem lies. I also tried to use GroupBy in model (instead of using it in the code above) but got the some problem:
var model = (from ss in sql // here I refer to sql outcome I got from the code above
.GroupBy(g => g.AccountNr)
.Skip(page * 15 - 15)
.Take(15)
.AsEnumerable()
select new DocumentsModel
{
Company = s.Customers.CompName,
TWQ = s.Customers.TWQ,
AccountNr = s.Accounts.AccountNr,
DocDate = s.Accounts.DocumentDate,
Income = s.Customers.Income
}).ToList();
At first I would like to say that my English isn't that good.
If you execute an GroupBy, you'll get collection of elements where each element represents a projection over a group and its key.
That's why I execute SelectMany afterwards to work with the model in a normal way.
db.Accounts
.AsNoTracking()
.Join
(
inner: db.Customers.AsNoTracking(),
outerKeySelector: x => x.AccountNr,
innerKeySelector: x => x.CustNr,
resultSelector: (Accounts, Customers) => new
{
Accounts, Customers
}
)
.Where
(
predicate: x => x.Accounts.Date == null
)
.GroupBy
(
keySelector: x => x.Accounts.AccountNr
)
.SelectMany
(
selector: x => x
)
.Select
(
selector: x => new
{
Company = x.Customers.CompName,
TWQ = x.Customers.TWQ,
AccountNr = x.Accounts.AccountNr,
DocDate = x.Accounts.DocumentDate,
Income = x.Customers.Income
}
)

How to make this query with lambda expression in Entity Framework?

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.

Transform SQL Query to LINQ

I would like if someone helps me to convert this SQL Query to LINQ syntax.
SELECT i.Id, i.Condomino as Condomino, i.Interno as Interno,
p.NomePiano as NomePiano, s.Nome as NomeCondominio,
m.millesimi_fabbisogno_acs, m.millesimi_fabbisogno_riscaldamento
FROM Interni i
INNER JOIN Piani p ON i.IdPiano = p.Id
INNER JOIN Stabili s ON i.IdStabile = s.Id
LEFT JOIN MillesimiTabellaC m ON i.Id = m.idInterno
WHERE s.IdCondominio = {0}
I tried using something like this, but is not working..
return _Db.Interni.Include("Piani").Where(x => x.Piani.IdCondominio == iidcond).ToList();
I made it on-the-spot (so it's not tested), but perhaps it's enough to give you the idea. I'm also assuming that your DB model has foreign keys set up.
var result = _db.Interni
.Where(i => i.Stabili.IdCondominio = [value])
.Select(i => new
{
i.Id,
Condomino = i.Condomino,
Interno = i.Interno,
NomePiano = i.Piani.NomePiano,
NomeCondominio = i.Stabili.Nome,
i.MillesimiTabellaC.millesimi_fabbisogno_acs,
i.MillesimiTabellaC.millesimi_fabbisogno_riscaldamento
})
.ToList();
update
In case you don't have a foreign key between Interni and MillesimiTabellaC, try this:
var result = _db.Interni
.Include(i => i.Piani)
.Include(i => i.Stabili)
.Where(i => i.Stabili.IdCondominio = [value])
.Select(i => new
{
Interni = i,
MillesimiTabellaC = _db.MillesimiTabellaC.Where(m => i.Id = m.idInterno)
})
.Select(x => new
{
Id = x.Interni.Id,
Condomino = x.Interni.Condomino,
Interno = x.Interni.Interno,
NomePiano = x.Interni.Piani.NomePiano,
NomeCondominio = x.Interni.Stabili.Nome,
x.MillesimiTabellaC?.millesimi_fabbisogno_acs,
x.MillesimiTabellaC?.millesimi_fabbisogno_riscaldamento
})
.ToList();

what am i doing wrong in constructing Linq query

I am trying to write equivalent linq code for following query.
SELECT A.*
FROM
(
SELECT * FROM TableA
WHERE id = 100
) a
JOIN
(
SELECT Name, MAX(AnotherId) AnotherId
FROM TableA
WHERE id = 100
GROUP BY Name
) b
on a.Name = b.Name and a.AnotherId = b.AnotherId
This is the linq
var Collection = from R in DbContext.TableA
join G in (DbContext.TableA.Where(r => r.Id == 100).GroupBy(r => new { r.Name, r.AnotherId } ).Select(g => new { Name = g.Name , AnotherId = g.Max(o => o.AnotherId) }))
on new { R.Name, R.AnotherId } equals new { G.Name, G.AnotherId }
where R.Id == 100
select R;
But I am getting following compilation error that I don’t know how to fix. Any thoughts
The type of one of the expressions in the join clause is incorrect. Type inference failed in the call to 'Join'.
Error 7 'System.Linq.IGrouping' does not contain a definition for 'Name' and no extension method 'Name' accepting a first argument of type 'System.Linq.IGrouping' could be found (are you missing a using directive or an assembly reference?)
You group by r.Name, r.AnotherId, when you just want to group by r.Name.
var Collection = from R in DbContext.TableA
join G in (DbContext.TableA
.Where(r => r.Id == 100)
.GroupBy(r => r.Name)
.Select(g => new { Name = g.Key , AnotherId = g.Max(o => o.AnotherId) }))
on new { R.Name, R.AnotherId } equals new { G.Name, G.AnotherId }
where R.Id == 100
select R;
And to have all in Fluent Syntax
var collection = DbContext.TableA
.Where(t1 => t1.Id == 100)
.Join(DbContext.TableA
.Where(t2 => t2.Id == 100)
.GroupBy(t2 => t2.Name)
.Select(group => new{Name = group.Key,
AnotherId = group.Max(e => e.AnotherId)})
),
t1 => new{t1.Name, t1.AnotherId} ,
t2 => new{t2.Name, t2.AnotherId},
(t1, t2) => t1);
llHi you need the following syntax, notice the addition of 'Key'
var Collection = from R in DbContext.TableA
join G in (DbContext.TableA.Where(r => r.Id == 100)
.GroupBy(r => new { r.Name, r.AnotherId } )
.Select(g => new { Name = g.Key.Name , AnotherId = g.Max(o => o.AnotherId) }))
on new { R.Name, R.AnotherId } equals new { G.Name, G.AnotherId }
where R.Id == 100
select R;
I would recommend using the query syntax for all parts of your query. By doing it this way, your linq query will have a more similar structure to your original sql query. It would look like this:
var query =
from a in
(from x in DbContext.TableA
where x.ID == 100
select x)
join b in
(from x in DbContext.TableA
where x.ID == 100
group x by x.Name into x
select new
{
Name = x.Key,
AnotherId = x.Max(o => o.AnotherId),
})
on new { a.Name, a.AnotherId } equals new { b.Name, b.AnotherId }
select a;
saj and Raphael both have found good points:
.GroupBy(r => new { r.Name, r.AnotherId } )
.Select(g => new { Name = g.Name , AnotherId = g.Max(o => o.AnotherId) }))
Groups don't have a Name. Each group has a Key (and the Key has a Name and AnotherId).
Since you want the Max(AnotherId), you don't want to include AnotherId in your grouping Key (same as it is not present in the GroupBy clause of the original query).
.GroupBy(r => r.Name) //the Name is the Key
.Select(g => new { Name = g.Key, AnotherId = g.Max(o => o.AnotherId) }))

Categories