Avanced Entity Framework Query Example - c#

this my sql command.
select c.nombrecompleto fullname,c.direccion street ,c.telefono phonenumber,
c.limitecredito creditlimit,sum(vd.preciofinal) balance , case when max(a.fechacreacion) is null then '' else max(a.fechacreacion) end
lastpay
,
case when u.nombre is null then '' else u.nombre end paidTo
from cliente c
inner join venta v on c.idcliente=v.idcliente
inner join ventadetalle vd on v.idventa=vd.idventa
inner join prestamo p on p.idventa=v.idventa
left join abono a on c.idcliente=a.idcliente
left join usuario u on a.creadopor=u.idusuario
where
c.estatus=1 and
v.estatus=1 and
vd.estatus=1 and
p.estatus=1 and
(a.estatus is null or a.estatus=1)
and (u.estatus=1 or u.estatus is null)
group by c.nombrecompleto,c.direccion,c.telefono,c.limitecredito
,u.nombre
having sum(vd.preciofinal)>0
i tried converted it to entity framework but i could not.
this i got (i did not finish)
from c in Clientes
join v in Ventas on c.Idcliente equals v.Idcliente
join vd in Ventadetalles on v.Idventa equals vd.Idventa
join p in Prestamos on v.Idventa equals p.Idventa
join a in Abonos on c.Idcliente equals a.Idcliente into al
from a in al.DefaultIfEmpty()
join u in Usuarios on a.Creadopor equals u.Idusuario into ul
from u in ul.DefaultIfEmpty()
where
c.Estatus==1 &&
v.Estatus==1 &&
vd.Estatus==1 &&
p.Estatus==1 &&
(a.Estatus==1 || a.Estatus== null) &&
(u.Estatus==1 || u.Estatus== null)
group new{c.Idcliente,vd,a} by new { c.Nombrecompleto, c.Direccion, c.Telefono, c.Limitecredito,
usuarionombre=((u.Nombre!=null)?u.Nombre:u.Nombre)
}

not sure but i believe i have got
from c in Clientes
join v in Ventas on c.Idcliente equals v.Idcliente
join vd in Ventadetalles on v.Idventa equals vd.Idventa
join p in Prestamos on v.Idventa equals p.Idventa
join a in Abonos on c.Idcliente equals a.Idcliente into al /*this line*/
from a in al.DefaultIfEmpty() /*and this is for to do left outer join or left join*/
join u in Usuarios on a.Creadopor equals u.Idusuario into ul
from u in ul.DefaultIfEmpty() /*so you see here other left join*/
where
c.Estatus==1 &&
v.Estatus==1 &&
vd.Estatus==1 &&
p.Estatus==1 &&
(a.Estatus==1 || a.Estatus== null) &&
(u.Estatus==1 || u.Estatus== null) /*this is for to do (a.estatus is null or a.estatus=1)*/
group new
{
vd.Preciofinal,a.Fechacreacion /*these are the max or sum or min columns */}
by new {c.Idcliente, c.Nombrecompleto, c.Direccion, c.Telefono, c.Limitecredito,
usuarionombre=((u.Nombre!=null)?u.Nombre:u.Nombre/*the group by part in a normal sql command */
)
}
into agrupacion /*inside a new table */
where agrupacion.Sum(x=> x.Preciofinal)>0 /*this would be a having sum in a normal sql command */
select new {
/*my columns i needs only and the sum and max*/
agrupacion.Key.Idcliente,agrupacion.Key.Nombrecompleto,agrupacion.Key.Direccion,agrupacion.Key.Telefono,
agrupacion.Key.Limitecredito,agrupacion.Key.usuarionombre, saldo=agrupacion.Sum(x=> x.Preciofinal)
,ultimopago=((agrupacion.Max(x=> x.Fechacreacion)!=null)?agrupacion.Max(x=> x.Fechacreacion):DateTime.Now /*ultimopago would be a case when max(fechacreacion )is null then getdate() else max(fechaultimopago)* end as ultimopago/)
}
i hope this could help to other

Related

Joining column with multiple tables LINQ

There is a table I want to join with different columns in different tables.
This is how so far I did this
var purchData = (from a in db.AppRequest
join e in db.Employee on a.Req_By equals e.Id
join c in db.Company on e.CompanyId equals c.Id
join d in db.Designation on e.DesignId equals d.Id
join l in db.Master_Locations on a.Req_Location equals l.Id
join dep in db.Department on e.DepId equals dep.Id
join p in db.Purchase on a.Id equals p.Req_Id
join pi in db.PurchasingItems on p.Id equals pi.Purchase_Id
join pd in db.PurchasingDetails on p.Id equals pd.Purchase_Id
join pds in db.PurchasingDetailsSup on pd.Id equals pds.PurchasingDetails_Id
join s in db.M_Supplier on pds.Supp_Id equals s.Id
join payMethod in db.Master_PayMethods on s.Pay_Method equals payMethod.Id
join poNo in db.ApprovedPoNumbers on p.Id equals poNo.Purchase_Id
where a.Id == id && pds.IsApproved == true
In db.ApprovedPoNumbers table has purchase_Id and Supplier_Id
In db.PurchasingDetailsSup table has purchase_Id and Supplier_Id
So I want to know that here join poNo in db.ApprovedPoNumbers on p.Id equals poNo.Purchase_Id line I want to join the db.ApprovedPoNumbers table purchase_Id,Supplier_Id with db.PurchasingDetailsSup table purchase_Id and Supplier_Id
You can achieve that by building two objects with the criterias you intend to match and use the equals operator on them:
on new {poNo.purchase_Id, poNo.Supplied_Id} equals new {pds.purchase_Id, pds.Supplier_Id} into details

LINQ left join generates wrong SQL query

I have this LINQ query:
from sol in context.SalesOrderLines
join mpso in context.MulticlientsoParentChildsoRelations on sol.orderid equals mpso.parentsalesorderid into lmpso
from mpso in lmpso.DefaultIfEmpty()
join cso in context.SalesOrders on mpso.childsalesorderid equals cso.id into lcso
from cso in lcso.DefaultIfEmpty()
join csol in context.SalesOrderLines on cso.id equals csol.orderid into lcsol
from csol in lcsol.DefaultIfEmpty()
join pll in context.PickingLine on (csol == null ? sol.id : csol.id) equals pll.salesorderlineid
join pl in context.PickingLists on pll.pickinglistid equals pl.id
join pfi in context.PfiSubmitterQuantities on pll.id equals pfi.pickinglineid into ppfi
from pfi in ppfi.DefaultIfEmpty()
where sol.orderid == palletid && (pfi == null ? pl.wholepallets == true : true)
select new Helper { Id = pfi.palletid ?? pll.palletid, BoolValue01 = pfi == null }
And here is sixth line with left join
join csol in context.SalesOrderLines on cso.id equals csol.orderid into lcsol
from csol in lcsol.DefaultIfEmpty()
And it generates strange SQL query, here's how it looks when I do linq to sql (take a look at 7th line):
SELECT distinct
CASE WHEN (pfi."palletid" IS NULL) THEN (pll."palletid") ELSE (pfi."palletid") END AS "C1",
CASE WHEN (pfi."id" IS NULL) THEN (TRUE) ELSE (FALSE) END AS "C2"
FROM salesorderlines AS sol
LEFT OUTER JOIN multiclientso_parentchildsorelations AS mpso ON sol."orderid" = mpso."parentsalesorderid"
LEFT OUTER JOIN salesorders AS cso ON mpso."childsalesorderid" = cso."id"
LEFT OUTER JOIN salesorderlines AS csol ON cso."id" = csol."orderid" OR cso."id" IS NULL AND csol."orderid" IS NULL
INNER JOIN pickingline AS pll ON
CASE WHEN (csol."id" IS NOT NULL) THEN (csol."id") ELSE (sol."id") END = pll."salesorderlineid"
OR CASE WHEN (csol."id" IS NOT NULL) THEN (csol."id") ELSE (sol."id") END IS NULL AND pll."salesorderlineid" IS NULL
INNER JOIN pickinglist AS pl ON pll."pickinglistid" = pl."id"
LEFT OUTER JOIN pfi_submittedquantities AS pfi ON pll."id" = pfi."pickinglineid"
WHERE sol."orderid" = 24863039
AND CASE WHEN (pfi."id" IS NULL) THEN ( CASE WHEN (TRUE = pl."wholepallets") THEN (TRUE) WHEN (NOT (TRUE = pl."wholepallets" AND pl."wholepallets" IS NOT NULL)) THEN (FALSE) END ) ELSE (TRUE) END = TRUE
The problem is how does my linq left join translates from this LINQ
join csol in context.SalesOrderLines on cso.id equals csol.orderid into lcsol
from csol in lcsol.DefaultIfEmpty()
to this SQL
LEFT OUTER JOIN salesorderlines AS csol ON cso."id" = csol."orderid" OR cso."id" IS NULL AND csol."orderid" IS NULL
From where does the OR part comes?
Thanks to #ArcaArtem, I've found that SalesOrderLines table had orderid nullable int foreign key field, which in my case would never be null, so changed it to simple int. Now it generates correct sql.

Define nested derived table in Entity Framework

I am converting SQL query into linq ef 6.0. I have a problem when convert nest derived table into linq query. Following is SQL query and Linq expression where i stuck
Select * FROM orders ords WITH ( NOLOCK )
INNER JOIN orders_list ol WITH ( NOLOCK ) ON ords.order_id = ol.order_id
--AND ol.order_list_id = #order_list_id
INNER JOIN product WITH ( NOLOCK ) ON product.id = ol.product_id
INNER JOIN OrderContact ca WITH ( NOLOCK ) ON ca.id= ords.OrdercontactRecipientId --and ca.is_primary_address = 1
INNER JOIN OrderContact ca1 WITH ( NOLOCK ) ON ca1.id=ords.OrderContactCustomerID--and ca.is_primary_address = 1
LEFT JOIN ( SELECT oslTemp.order_list_id ,
status_id
FROM Ticket_status_log
INNER JOIN ( SELECT osl.order_list_id ,
MAX(log_id) AS log_id
FROM Ticket_status_log osl
INNER JOIN orders_list
WITH ( NOLOCK ) ON orders_list.order_list_id = osl.order_list_id
WHERE osl.is_deleted = 0
AND osl.status_id > 0
AND osl.status_id < 3
GROUP BY osl.order_list_id
) AS oslTemp ON oslTemp.log_id = Ticket_status_log.log_id
) status_log ON ol.order_list_id = status_log.order_list_id
WHERE ords.is_deleted = 0
Following is linq expression
var query = (from ords in con.ordersDB
join ol in con.Orders_ListDB on ords.order_id equals ol.order_id
join product in con.ProductDB on ol.product_id equals product.ID
join ca in con.OrderContactDB on ords.OrderContactRecipientID equals ca.ID
join ca1 in con.OrderContactDB on ords.OrderContactCustomerID equals ca1.ID
join tktlog in con.ticket_status_logDB
)
I have stuck when there is derived nest table join. How to handle this
You can use let clause to solve this problem Microsoft Docs.
Write you subquery in let and then join the let variable with other table variables
I had figure it out by myself. I am posting the answer so that any other will get the solution
var innerQuery2 = (from tktlog in con.ticket_status_logDB
join ordlist in con.Orders_ListDB on tktlog.order_list_id equals ordlist.order_list_id
where tktlog.is_deleted == false && tktlog.status_id > 0 && tktlog.status_id < 3
group tktlog by tktlog.order_list_id into grouped
select new
{
order_list_id = grouped.Key,
log_id = grouped.Select(x => x.log_id).Max()
});
var innerQuery1 = (from tktlog in con.ticket_status_logDB
join osltemp in innerQuery2 on tktlog.log_id equals osltemp.log_id
select new
{
osltemp.order_list_id,
tktlog.status_id
});
var query = (from ords in con.ordersDB
join ol in con.Orders_ListDB on ords.order_id equals ol.order_id
join product in con.ProductDB on ol.product_id equals product.ID
join ca in con.OrderContactDB on ords.OrderContactRecipientID equals ca.ID
join ca1 in con.OrderContactDB on ords.OrderContactCustomerID equals ca1.ID
join cityml in con.CityMLDB on ca.CityMLID equals cityml.ID into leftcityml
from citymlresult in leftcityml.DefaultIfEmpty()
join state in con.StateDB on ca.StateID equals state.ID into leftstate
from stateresult in leftstate.DefaultIfEmpty()
join area in con.AreaMLDB on ca.AreaMLID equals area.ID into leftarea
from arearesult in leftarea.DefaultIfEmpty()
join statuslog in innerQuery1 on ol.order_list_id equals statuslog.order_list_id into leftquery1
from status_log in leftquery1.DefaultIfEmpty()
where ords.is_deleted == false && ords.is_voided == false && ords.type_id == 2
&& (ol.item_number ?? 0) > 0 &&
(
(
(ol.parent_id == parintid || ol.parent_id == orderListId || ol.order_list_id == orderListId)
&& (ol.SubType ?? 0) == 4
)
|| (ol.order_list_id == orderListId)
)
orderby arearesult.Name ?? ca.AreaOther
select new {});

How to join on multiple parameters from different tables in LINQ to SQL in C#

I'm writing Select-statements with joins in C# with Vs 2015.
Now i got a special join with multiple parameters which come - under circumstances - from different tables which complicates all a little bit.
How can i write the following statement correctly?
TestPointToInputMask tpm2 =
(from m in ent.InputMask
join tm in ent.TestPointToInputMask on m.inputMaskId equals tm.inputMaskId
join tp in ent.TestPoint on tm.testPointId equals tp.testPointId
join tc in ent.TestPointToChapter on tp.testPointId equals tc.testPointId
join c in ent.Chapter on tc.chapterId equals c.chapterId
join dc in ent.Description on c.textKey equals dc.textKey and dc.languageId == 1
join dp in ent.Description on tp.textKey equals dp.textKey and dp.languageId == 1 and dp.text.StartsWith(testPointText)
where m.inputMaskName.ToUpper() == inputMaskName.ToUpper()
&& tp.testPointNumber.ToUpper() == testPointNumber.ToUpper()
&& dc.text.ToUpper() == chapterText.ToUpper()
&& c.testTypeId == testTypeId
select tm).FirstOrDefault();
As You can see i have there two joins in which i use "and" which don't work.
I tried another version but it's very slow.
TestPointToInputMask tpm2 =
(from m in ent.InputMask
join tm in ent.TestPointToInputMask on m.inputMaskId equals tm.inputMaskId
join tp in ent.TestPoint on tm.testPointId equals tp.testPointId
join tc in ent.TestPointToChapter on tp.testPointId equals tc.testPointId
join c in ent.Chapter on tc.chapterId equals c.chapterId
join dc in ent.Description on c.textKey equals dc.textKey
join dp in ent.Description on tp.textKey equals dp.textKey
where m.inputMaskName.ToUpper() == inputMaskName.ToUpper()
&& tp.testPointNumber.ToUpper() == testPointNumber.ToUpper()
&& dc.text.ToUpper() == chapterText.ToUpper()
&& c.testTypeId == testTypeId
&& dc.languageId == 1
&& dp.languageId == 1 && dp.text.StartsWith(testPointText)
select tm).FirstOrDefault();
Any help would be appreciated.

Is it possible to add Multiple 'on' in 1 join statement of Linq

I don't know it its possible to have a nested or 2 or more on c.blah equals b.blah in one join statement in LINQ bacause i have to join a table without affecting the number of data
because if I add it to where theres a decrease of number of data and it acts as filter
What I tried as of the moment is adding && clause but it's not working
var Pos = (from a in db.Position
join b in db.Position_Location
on a.ID equals b.PositionId
join c in db.Customer
on a.CustomerID equals c.ID
join d in db.Customer_Location
on b.LocationId equals d.ID
join f in db.Worker
on userIdNew equals f.userId
join e in db.Worker_Customer_Apply_Shift <----Planning to add new validation here
on a.ID equals e.Client_Customer_PositionID into trial
from newtrial in trial.DefaultIfEmpty()
where
b.LogicalDelete == false
&& a.LogicalDelete == false
&& c.LogicalDelete == false
&& d.LogicalDelete == false
select new
{
a.ID,
Client_CustomerID = c.ID,
LogicalDelete =(newtrial == null ? true : newtrial.LogicalDelete),
}).Distinct().ToList();
Thanks in Advance :)
You could use an anonymous type with the fields you want use in your join condition:
on new { a.One, a.Two } equals new { b.One, b.Two }
If the columns in both tables don't have the same names, you need to provide names for the properties of the anonymous type:
on new { Col1 = a.One, Col2 = a.Two } equals new { Col1 = b.Three, Col2 = b.Four }

Categories