Convert T-SQL statement into LINQ expression - c#

i am quite new to linq and actually fighting to convert the following t-sql statement into an linq to sql or linq to entities expression:
SELECT TOP 1
vm.EventID,
vmm.VotingMatrixID,
PersonAcceptedCount = SUM( CAST( vmm.IsAccepted AS INT) )
FROM VotingMatrixMember vmm
JOIN VotingMatrix vm
ON vmm.VotingMatrixID = vm.ID
WHERE vm.EventID = 'abbe3077-24de-45d8-ac04-13dba97c1567'
AND vm.Deleted = 0
AND vmm.Deleted = 0
GROUP BY vm.EventID, vmm.VotingMatrixID
ORDER BY PersonAcceptedCount DESC

Try this, can not test
var firstItem = (
from vmm in db.VotingMatrixMember
join vm in db.VotingMatrix on vmm.VotingMatrixID equals vm.ID
where vm.EventID = "abbe3077-24de-45d8-ac04-13dba97c1567"
&& vm.Deleted = 0
&& vmm.Deleted = 0
group new {vm, vmm} by new {vm.EventID, vmm.VotingMatrixID} into gr
select new
{
EventID = gr.Key.EventID,
VotingMatrixID = gr.Key.VotingMatrixID,
PersonAcceptedCount = gr.Sum(x => Convert.ToInt32(x.IsAccepted))
}
into groupedItem
orderby groupedItem.PersonAcceptedCount descending
select groupedItem
).FirstOrDefault();

var query =
from vm in dataContext.VotingMatrices
where vm.EventId == eventId
where vm.Deleted == 0
from vmm in vm.VotingMatrixMembers
where vmm.Deleted == 0
group vmm by new { vm.EventId, vmm.VotingMatrixId } into g
select new
{
g.Key.EventId,
g.Key.VotingMatrixId,
PersonAcceptedCount: g.Select(x => Convert.ToInt32(x.IsAccepted)).Sum()
} into resultRow
order by resultRow.PersonAcceptedCount descending
select resultRow;
var row = query.FirstOrDefault();

Related

Performance issue in linq query

I have created a linq query to join tables and to do aggregate function and it takes more than a minute and it is affecting performance when executing the query in database it takes 18 seconds Kindly help me to improve the performance of Linq query.
Code:
List<int> oStatus = new List<int> { (int)STATUS.PAID, (int)STATUS.PARTIALY_PAID, (int)STATUS.OPEN, (int)STATUS.COMPLETED };
List<int> oLocationids = (
from loc in oTransactionContext.Location
join lum in oTransactionContext.LocationUserMap on loc.LocationId equals lum.LocationId
where lum.UserId == iUserID && loc.LocationName != "Local Purchase" && loc.LocationId !=0 &&loc.IsActive==true
select lum.LocationId
).ToList();
var oPT_Det = (
from inv in oTransactionContext.Invoice
join loc in oTransactionContext.Location on inv.LocationId equals loc.LocationId
where (inv.ClientId == (iClientID) && oLocationids.Contains(inv.LocationId.GetValueOrDefault()) &&
(inv.EndTime > DateTime.UtcNow.AddMonths(-6))
&& inv.IsActive == (true) && oStatus.Contains(inv.Status.GetValueOrDefault()))
group new { inv, loc } by new { inv.LocationId, loc.LocationName } into groupResult
select new OverAllSales
{
Location = Helper.CommonHelper.ParseString(groupResult.Key.LocationName),
InvoiceAmount = Helper.CommonHelper.ParseDecimal(groupResult.Sum(f => f.inv.TotalInvoiceAmount)),
}
).ToList();
Postgresql:
SELECT
COALESCE(SUM(inv.total_invoice_amount), 0) AS value1,
loc.location_name AS metric
FROM location loc
LEFT JOIN location_user_map LUM ON LUM.location_id = loc.location_id
LEFT OUTER JOIN invoice inv ON inv.client_id =2 AND inv.location_id = loc.location_id
AND inv.status IN (SELECT status_id FROM status WHERE status IN ('Paid', 'Partialy Paid', 'Open', 'Completed'))
WHERE loc.location_name NOT IN ('Local Purchase')
AND loc.location_id != 0
AND LUM.user_id IN ($user_ids)
AND inv.is_active = TRUE
AND CAST(inv.end_time AS date) > CURRENT_DATE - INTERVAL '2' MONTH
GROUP BY loc.location_name
ORDER BY value1 DESC
This is direct translation of the SQL. Should generate similar SQL query.
var startDate = DateTime.Date.AddMonths(-2);
int clientId = ...
int userId = ...
var oStatus = new List<int> { (int)STATUS.PAID, (int)STATUS.PARTIALY_PAID, (int)STATUS.OPEN, (int)STATUS.COMPLETED };
var query =
from loc in oTransactionContext.Location
join lum in oTransactionContext.LocationUserMap on loc.LocationId equals lum.LocationId
from inv in oTransactionContext.Invoice
.Where(inv => inv.ClientId == clientId && inv.LocationId = loc.LocationId
&& oStatus.Contains(inv.Status))
where
loc.LocationName != "Local Purchase"
&& loc.LocationId !=0
&& lum.UserId == userId
&& inv.IsActive == true
&& inv.end_time >= startDate
group inv by loc.LocationName into g
select new
{
Location = g.Key,
InvoiceAmount = g.Sum(x => x.total_invoice_amount) ?? 0
};
var oPT_Det = query.ToList();

COUNT(DISTINCT *) in ef core 2.1

SELECT
e.EmpName,
me.RemarkNumber,
me.RemarkPeopleNumber
FROM
EmployeeInfo e
LEFT JOIN (
SELECT
COUNT(RemarkId) As RemarkNumber,
COUNT(DISTINCT MemberId) As RemarkPeopleNumber,
CreateUser
FROM
MemberRemark
WHERE
RemarkStatus = 0
GROUP BY
CreateUser
) AS me On e.EmpName = me.CreateUser
WHERE
BranchCode = '0000'
And [Status] = 0
How to convert it to LINQ?
from e in db.EmployeeInfo
join me in (
from memberRemarks in db.MemberRemark
where memberRemarks.RemarkStatus == 0
group memberRemarks by new
{
memberRemarks.CreateUser,
} into g
select new
{
RemarkNumber = g.Count(),
RemarkPeopleNumber = g.Select(m => m.MemberId).Distinct().Count(),
g.Key.CreateUser
}
) on new { e.EmpName } equals new { EmpName = me.CreateUser } into meJoin
from me in meJoin.DefaultIfEmpty()
where e.BranchCode == "0000" & &e.Status == 0
select new
{
e.EmpName,
me.RemarkNumber,
me.RemarkPeopleNumber
};
I got this error
RemarkPeopleNumber = g.Select(m=>m.MemberId).Distinct().Count(),
//error
Using asp.net core mvc 2.1 + ef core 2.1 + mssql
Perhaps if you broke the query up into pieces it would be handled better? Using my SQL to LINQ Recipe I would translate your SQL like this:
var ePart = from e in db.EmployeeInfo
where e.BranchCode == "0000" && e.Status == 0
select e;
var mrPart = from mr in db.MemberRemark
where mr.RemarkStatus == 0
group mr by mr.CreateUser into mrg
select new {
CreateUser = mrg.Key,
RemarkNumber = mrg.Count(),
RemarkPeopleNumber = mrg.Select(mr => mr.MemberId).Distinct().Count()
};
var ans = from e in ePart
join me in mrPart on e.EmpName equals me.CreateUser into mej
from me in mej
select new {
e.EmpName,
me.RemarkNumber,
me.RemarkPeopleNumber
};

Getting Column Value from another Subquery

I have a LINQ query. But I need to get value of two columns from another subquery. This is my Linq query:
)from t in db.PUTAWAYs
join t0 in db.ASN_ITEM on t.AWB_NO equals t0.AWB_NO
join t1 in db.ASN_MASTER on t0.AWB_NO equals t1.AWB_NO
join t2 in db.ITEM_MASTER on t.ITEM_MASTER.ITEM_CODE equals t2.ITEM_CODE
join t3 in db.ASN_INPUT on t0.AWB_NO equals t3.AWB_NO
where
t3.ITEM == t2.ITEM_CODE &&
1 == 1 &&
(fromDate == "" || toDate == "" || (t0.REC_DATE.CompareTo(fromDate) >= 0 && t0.REC_DATE.CompareTo(toDate) <= 0)) &&
(AWB_NO == "" || (t0.AWB_NO == AWB_NO))
orderby
t.AWB_NO,
t0.REC_DATE,
t0.STYPE,
t2.PART_NO
select new ASNPutawayRep
{
AWB_NO = t.AWB_NO,
REC_DATE = t0.REC_DATE,
STYPE = t0.STYPE,
PART_NO = t2.PART_NO,
//LOCATION_AD = t.LOCATION_AD,
QNTY = t.QNTY,
//LOCATION_SD = t.LOCATION_SD,
REGION_ID = t.REGION_ID
}).Distinct();
Here in select portion of above query, instead of directly taking value of the column t.LOCATION_AD, I need to get it from SELECT LOC_NAME FROM LOCATION_MASTER WHERE LOC_CODE = t.LOCATION_AD
and instead of t.LOCATION_SD, I need to get value from SELECT LOC_NAME FROM LOCATION_MASTER where LOC_CODE = t.LOCATION_SD
How can I write this in LINQ. Is there any way to do this?
You can make use of let clause. It is useful to store the result of sub-expression in order to use it in subsequent clauses.
Example:
(from t in db.PUTAWAYs
...
let locAd = from l in LOCATION_MASTER where LOC_CODE = t.LOCATION_SD select l.LOC_NAME
where
...
orderby
...
select new ASNPutawayRep
{
LOCATION_AD = locAd,
}).Distinct();
Also, you can directly write LINQ without using let clause:
(from t in db.PUTAWAYs
...
where
...
orderby
...
select new ASNPutawayRep
{
LOCATION_AD = from l in LOCATION_MASTER where LOC_CODE = t.LOCATION_SD select l.LOC_NAME
}).Distinct();
You can use AsQueryable to achieve this
from t in db.PUTAWAYs
join t0 in db.ASN_ITEM on t.AWB_NO equals t0.AWB_NO
join t1 in db.ASN_MASTER on t0.AWB_NO equals t1.AWB_NO
join t2 in db.ITEM_MASTER on t.ITEM_MASTER.ITEM_CODE equals t2.ITEM_CODE
join t3 in db.ASN_INPUT on t0.AWB_NO equals t3.AWB_NO
where
t3.ITEM == t2.ITEM_CODE &&
1 == 1 &&
(fromDate == "" || toDate == "" || (t0.REC_DATE.CompareTo(fromDate) >= 0 && t0.REC_DATE.CompareTo(toDate) <= 0)) &&
(AWB_NO == "" || (t0.AWB_NO == AWB_NO))
orderby
t.AWB_NO,
t0.REC_DATE,
t0.STYPE,
t2.PART_NO
select new ASNPutawayRep
{
AWB_NO = t.AWB_NO,
REC_DATE = t0.REC_DATE,
STYPE = t0.STYPE,
PART_NO = t2.PART_NO,
LOCATION_AD = (from l in db.LOCATION_MASTER
where l.LOC_CODE = t.LOCATION_AD
select LocName)ToList().FirstorDefault(),
QNTY = t.QNTY,
LOCATION_SD = (from l in db.LOCATION_MASTER
where l.LOC_CODE = t.LOCATION_SD
select LocName).ToList().FirstorDefault(),
REGION_ID = t.REGION_ID
}).Distinct();

Primitive type error in LINQ to SQL query+subquery

I got the famous "only primitive types or enumeration types..." error, and I cannot find the solution.
This is the code that is making my head explode (it's part of a select in another LINQ code):
Min = (from inddetails in EntitiesDB.ConfSet
where (final.Max(x => x.hosp.Hos_NumOnc) > inddetails.Conf_Desde && final.Max(x => x.hosp.Hos_NumOnc) < inddetails.Conf_Hasta)
|| final.Max(x => x.hosp.Hos_NumOnc) > (from inddetails2 in EntitiesDB.ConfSet select inddetails2.Conf_Hasta).Max()
select inddetails.Conf_NumeroRegistros)
Here is the full code as requested with the last updates (nothing changed):
var result = from indicadores in EntitiesDB.Catalogo_IndicadoresSet
join crit in EntitiesDB.Catalogo_CriteriosSet on indicadores.CodigoCriterio equals crit.CodigoCriterio
join dimen in EntitiesDB.Catalogo_DimensionSet on crit.CodigoDimension equals dimen.CodigoDimension
join grupo in EntitiesDB.Catalogo_GruposSet on dimen.CodigoGrupo equals grupo.CodigoGrupo
join indicador_resultado in EntitiesDB.Catalogo_Indicador_ResultadoSet.DefaultIfEmpty() on indicadores.CodigoIndicador equals indicador_resultado.CodigoIndicador /*into joined
from j in joined.DefaultIfEmpty()*/
join user in EntitiesDB.UsuariosSet on indicador_resultado.CodigoUsuario equals user.CodigoUsuario
join hosp in EntitiesDB.HospitalesSet on user.CodigoHospital equals hosp.CodigoHospital
join hosper in EntitiesDB.Rel_Hospital_PeriodoSet on hosp.CodigoHospital equals hosper.CodigoHospital
join period in EntitiesDB.PeriodosSet on hosper.CodigoPeriodo equals period.CodigoPeriodo
where period.CodigoPeriodo == periodos.CodigoPeriodo
group new { indicadores, hosper, hosp, grupo, crit, dimen, indicador_resultado, user, period } by new { hosper.CodigoPeriodo, hosp.CodigoHospital, grupo.CodigoGrupo, indicadores.CodigoIndicador, period.Per_Nombre, hosp.Hos_Nombre, hosp.Hos_NumeroOncologos, grupo.Gru_Descripcion, indicador_resultado.CodigoResultado, indicador_resultado.Resul_Completado, indicador_resultado.Resul_Numerador, indicador_resultado.Resul_Denominador, indicador_resultado.Resul_Valor, indicador_resultado.Resul_Objetivo, indicador_resultado.Resul_Variacion, indicador_resultado.Resul_Detalle, indicador_resultado.Resul_Fecha, indicadores.Ind_Descripcion, dimen.CodigoDimension, crit.CodigoCriterio } into final
orderby final.Key.CodigoPeriodo, final.Key.CodigoHospital, final.Key.CodigoGrupo
select new
{
CodigoPeriodo = final.Key.CodigoPeriodo,
NombrePeriodo = final.Key.Per_Nombre,
CodigoHospital = final.Key.CodigoHospital,
NombreHospital = final.Key.Hos_Nombre,
NumeroOncologos = final.Key.Hos_NumeroOncologos),
CodigoGrupo = final.Key.CodigoGrupo,
NombreGrupo = final.Key.Gru_Descripcion,
CodigoResultado = final.Max(x => x.indicador_resultado.CodigoResultado),
Completado = final.Key.Resul_Completado,
Numerador = final.Max(x => x.indicador_resultado.Resul_Numerador),
Denominador = final.Max(x => x.indicador_resultado.Resul_Denominador),
Valor = final.Max(x => x.indicador_resultado.Resul_Valor),
Objetivo = final.Max(x => x.indicador_resultado.Resul_Objetivo),
Variacion = final.Max(x => x.indicador_resultado.Resul_Variacion),
Detalle = final.Key.Resul_Detalle,
CodigoIndicador = final.Key.CodigoIndicador,
NombreIndicador = final.Key.Ind_Descripcion,
CodigoDimension = final.Max(x => x.dimen.CodigoDimension),
CodigoCriterio = final.Max(x => x.crit.CodigoCriterio),
CasosMinimos = (from inddetalle in EntitiesDB.Configuracion_IndicadoresDetalleSet
where (final.Key.Hos_NumeroOncologos > inddetalle.Conf_Desde && final.Key.Hos_NumeroOncologos < inddetalle.Conf_Hasta)
|| final.Key.Hos_NumeroOncologos) > valorMaximo
select inddetalle.Conf_NumeroRegistros)
};
Take the max value out of the query:
var finalMax = final.Max(x => x.hosp.Hos_NumOnc);
Min = (from inddetails in EntitiesDB.ConfSet
where (finalMax > inddetails.Conf_Desde
&& finalMax < inddetails.Conf_Hasta)
|| finalMax > (from inddetails2 in EntitiesDB.ConfSet select inddetails2.Conf_Hasta).Max()
select inddetails.Conf_NumeroRegistros);
final is a collection of (non-primitive) objects, for which there is no SQL equivalent. It's also more efficient to do it this way.

c# Linq select join on select group by

I have this MS-SQL statement :
SELECT cv.id FROM ContactValue cv
INNER JOIN (
SELECT mainId, max(version) as v
FROM ContactValue
WHERE version <= $Version(int)
GROUP BY mainId
)
AS t ON t.mainId = cv.mainId AND t.v = cv.version
WHERE cv.contact_id = $ContactID(int)
AND cv.isActive = 1
ORDER BY sort'
and would like to make it in linq.
I did make above query divided into multiple queries witch performence is not fast.
Does it exist any linq to linq joining
My C# code :
var groupMax = from cv in db.ContactValue
where cv.contact_id == ContactID && cv.version <= Version
orderby cv.sort
group cv by cv.mainId into gcv
select new { mainID = gcv.Key, version = gcv.Max(cv => cv.version) };
foreach (var data in groupMax.ToList())
{
var Query = from cv in db.ContactValue
where cv.contact_id == ContactID && cv.mainId == data.mainID && cv.version == data.version && cv.isActive == true
select cv;
if (Query.Count() > 0)
{
ContactValue tmp = Query.First();
}
}
I would love to get all contacts with 1-2 queries not 1 query then for each contact another query...
Please help me !
Yes, Linq to SQL does have an inner join implemented:
var groupMax =
from cv in db.ContactValue
where cv.contact_id == ContactID && cv.version <= Version
orderby cv.sort
group cv by cv.mainId into gcv
select new { mainID = gcv.Key, version = gcv.Max(cv => cv.version) };
var res =
from cv in db.ContactValue
join gm in groupMax on cv.version equals gm.version
where cv.contact_id == ContactID && cv.isActive
orderby cv.version ascending /*for example*/
select cv
protected void rptPriceRachiveBind()
{
using (MyEntities ctx = new MyEntities())
{
var catRef = Convert.ToInt32(Request.QueryString["CategoryRef"]);
var prodCounts = (
from A in ctx.Products
join B in ctx.ProductPrices
on A.ProductId equals B.ProductRef
where A.CategoryRef == catRef
group A by new { A.Name,B.ProductRef } into catGp
select
new
{
catGp.Key.ProductRef,
catGp.Key.Name,
proIdCount = catGp.Count()
}).ToList();
Repeater1.DataSource = prodCounts;
Repeater1.DataBind();
}

Categories