I'm struggling in 'translating' a SQL query to a LINQ query. My SQL query looks like this:
SELECT S.SummonerName, LE.LeaguePoints, LS.DateTime, SUM(LE.LeaguePoints)
FROM LadderEntries LE
JOIN Sumonners S on LE.SummonerId = S.Id
JOIN LadderSnapshots LS on LE.LadderSnapshotId = LS.Id
WHERE LS.Region = 'euw1'
AND DateTime = '2019-06-14 00:00:00'
OR DateTime = '2019-06-13 00:00:00'
and LS.Region = 'euw1'
GROUP BY S.SummonerName
This query gives me the desired result. However, so far I got the following LINQ query:
from LE in _database.LadderEntries
join S in _database.Sumonners on LE.SummonerId equals S.Id
join LS in _database.LadderSnapshots on LE.LadderSnapshot.Id equals LS.Id
where LS.Region == param.Region && (LS.DateTime == param.Date || LS.DateTime == param.Date.AddDays(-1))
group new {LE, S, LS} by S.SummonerName
into C
select new GetLadderEntryDifferencesEntry
{
LpDifference = C.Select(a => a.LE.LeaguePoints).Sum(),
SummonerName = C.Select(a => a.S.SummonerName).FirstOrDefault()
};
But this gives me the error InvalidOperationException: Error generated for warning 'Microsoft.EntityFrameworkCore.Query.QueryClientEvaluationWarning: The LINQ expression 'GroupBy([S].SummonerName, new <>f__AnonymousType5'3(LE = [LE], S = [S], LS = [LS]))' could not be translated and will be evaluated locally.'. on execution.
I'm wondering what I'm doing wrong.
Note: I'm using sqllite and ef core if that makes a difference.
I believe the issue will be with:
&& (LS.DateTime == param.Date || LS.DateTime == param.Date.AddDays(-1))
try this:
var firstDate = param.Date;
var secondDate = param.Date.AddDays(-1);
then
&& (LS.DateTime == firstDate || LS.DateTime == secondDate)
possibly it may be taking exception to:
SummonerName = C.Select(a => a.S.SummonerName).FirstOrDefault()
or how the grouping is arranged.
Are these entities set up with references and can the expression be simplified?
var ladderEntryDifferences = _database.LadderSnapshots
.Where(x =>x.Region = param.Region
&& (x => x.DateTime == firstDate || x.DateTime == secondDate)
.GroupBy(x => x.LadderEntry.Summoner.SummonerName)
.Select( g => new GetLadderEntryDifferencesEntry
{
LpDifference = g.Sum(x => x.LeagueEntry.LeaguePoints),
SummonerName = g.Key // This will be the SummonerName
}).ToList();
The above is a guess about the structure, and pulling the group by from memory, but it might give you some ideas to try. If your context does not expose LadderSnapshots at a top level, you should be able to compose it from the LadderEntry level as well...
Ok here is what i got, first
LS.Region = 'euw1'
AND DateTime = '2019-06-14 00:00:00'
OR DateTime = '2019-06-13 00:00:00'
and LS.Region = 'euw1'
is not the same as the below linq, where the parameters is missing in the sql.
&& (LS.DateTime == param.Date || LS.DateTime == param.Date.AddDays(-1))
Now about the group by you could try to do it like this instead
from LE in _database.LadderEntries
join S in _database.Sumonners on LE.SummonerId equals S.Id
join LS in _database.LadderSnapshots on LE.LadderSnapshot.Id equals LS.Id
where LS.Region == param.Region && (LS.DateTime == param.Date || LS.DateTime == param.Date.AddDays(-1))
group LE by new {LE.SummonerName, S.SummonerName, LS.SummonerName}
into C
select new GetLadderEntryDifferencesEntry
{
LpDifference = C.Select(a => a.LE.LeaguePoints).Sum(),
SummonerName = C.Select(a => a.S.SummonerName).FirstOrDefault()
};
Related
I have the following SQL query which has a sub query so that only the max value is in the result set:
Select
t.ID,
r.ResultIdentifier,
p.ProductID,
r.Status,
r.Start
from Result r , Transact t, Product p
WHERE r.ResultIdentifier = (Select MAX(r2.ResultIdentifier) from Result r2
where r2.Status = 'Fail'
and r2.ID = r.ID
and r2.Start >= getdate() - 30)
and r.ID = t.ID
and p.productID = 9
and t.productID = p.productID
I'm trying to convert this to a LINQ query
var failures = from result in db.Results
join transact in db.Transacts on result.ID equals transact.ID
join product in db.Products on transact.ProductID equals product.ProductID
where result.ResultIdentifier == ??
.....
select new{ ID = transact.ID,
...etc
I'm really struggling with the max ResultIdentifier in the LINQ - tried multiple variations with .MAX() but cant seem to get it right.Any suggestions welcome.
You can use the max keyword, Sorry for using method syntax as I can see you are using query :(
Should look something like the following
where result.ResultIdentifier == (Results.Max().Where(x => x.Status.equals("Fail") && x.id == result.id && x.start => Datetime.Now().Add(-30)).Select(x => x.ResultIdentifier))
Try the following query:
var results = db.Results;
var failedResults = results
.Where(r => r.Status == "Fail" && r.Start >= DataTime.Date.AddDays(-30));
var failures =
from result in results
join transact in db.Transacts on result.ID equals transact.ID
join product in db.Products on transact.ProductID equals product.ProductID
from failed in failedResults
.Where(failed => failed.ID == result.ID)
.OrderByDescending(failed => failed.ResultIdentifier)
.Take(1)
where result.ResultIdentifier == failed.ResultIdentifier
.....
select new{ ID = transact.ID,
...etc
after upgrading from .netCore 2.2 to .NET 5, i receive the following error:
The LINQ expression 'e' could not be translated. Either rewrite the
query in a form that can be translated, or switch to client evaluation
explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable',
'ToList', or 'ToListAsync'. See
https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
Here is my code:
var query =
(from cf in ctx.CotacoesFornecedores.IgnoreQueryFilters().AsNoTracking()
join f in ctx.Fornecedores.IgnoreQueryFilters().AsNoTracking() on cf.FornecedorId equals f.Id
join pj in ctx.PessoasJuridicas.IgnoreQueryFilters().AsNoTracking() on f.ParceiroId equals pj.ParceiroId
join c in ctx.Cotacoes.IgnoreQueryFilters().AsNoTracking() on cf.CotacaoId equals c.Id
where filtro.Fornecedores.Contains(cf.FornecedorId)
&& c.EmpresaId == idEmpresa
&& c.Status == Models.StatusCotacao.Liberada.Id
&& codigoStatus.Contains(cf.Status)
&& (!apenasVigentes || (apenasVigentes && c.DataInicial <= dataAtual && c.DataFinal >= dataAtual))
orderby c.Numero, c.DataInicial
select new
{
c.Id,
IdCotacaoFornecedor = cf.Id,
pj.Cnpj,
pj.NomeFantasia,
pj.RazaoSocial,
c.Numero,
c.DataInicial,
c.DataFinal,
cf.Status,
cf.FornecedorId,
cf.PermiteAlterarQuantidadeEmbalagem,
c.Observacoes
});
if (filtro.Id > 0)
query = query.Where(q => q.Id == filtro.Id);
if (filtro.Numero > 0)
query = query.Where(q => q.Numero == filtro.Numero);
if (filtro.DataInicial.GetValueOrDefault() > DateTime.MinValue)
query = query.Where(q => q.DataInicial.Date >= filtro.DataInicial.Value.Date);
if (filtro.DataFinal.GetValueOrDefault() > DateTime.MinValue)
query = query.Where(q => q.DataFinal.Value.Date <= filtro.DataFinal.Value.Date);
return query
.Select(q => new Models.CotacaoFornecedor
{
Id = q.Id,
Numero = q.Numero,
IdFornecedor = q.FornecedorId,
IdCotacaoFornecedor = q.IdCotacaoFornecedor,
CnpjFornecedor = q.Cnpj,
NomeFantasiaFornecedor = q.NomeFantasia,
RazaoSocialFornecedor = q.RazaoSocial,
DataInicial = q.DataInicial,
DataFinal = q.DataFinal,
Status = Models.StatusCotacaoFornecedor.List().SingleOrDefault(e => e.Id == q.Status),
PermiteAlterarQuantidadeEmbalagem = q.PermiteAlterarQuantidadeEmbalagem,
Observacoes = q.Observacoes
}).ToPagedList(filtro);
The error points to the end on Status = Models.StatusCotacaoFornecedor.List().SingleOrDefault(e => e.Id == q.Status),
I understand that is not possible anymore to have client side evaluation, but i dont know the best solution to make it work without breaking the code logic, any suggestions?
Separate client-side logic from server-side. It is not easy to deduce that your query needs postprocessing automatically
var pagedList =
.Select(q => new Models.CotacaoFornecedor
{
Id = q.Id,
Numero = q.Numero,
IdFornecedor = q.FornecedorId,
IdCotacaoFornecedor = q.IdCotacaoFornecedor,
CnpjFornecedor = q.Cnpj,
NomeFantasiaFornecedor = q.NomeFantasia,
RazaoSocialFornecedor = q.RazaoSocial,
DataInicial = q.DataInicial,
DataFinal = q.DataFinal,
PermiteAlterarQuantidadeEmbalagem = q.PermiteAlterarQuantidadeEmbalagem,
Observacoes = q.Observacoes
}).ToPagedList(filtro);
foreach (var q in pagedList)
{
q.Status = Models.StatusCotacaoFornecedor.List().SingleOrDefault(e => e.Id == q.Status);
}
return pagedList;
adding .AsEnumberable resolved my problem.
I want to join two tables with EF Core with this code:
var fromDate = model.FromDate;
var toDate = model.ToDate;
var tourDate = _eContext.TourDates.OrderBy(x => x.Date).Where(x =>
(fromDate == null || x.Date >= fromDate) && (toDate == null || x.Date <= toDate))
.GroupBy(x => x.TourId).Select(g => new { TourId = g.Key, TourDateID = g.Min(y => y.TourDateId) });
var tours1 = _eContext.TourDetails;
var joinres = tours1.Join(tourDate
, tu => tu.TourDateId, td => td.TourDateId, (tu, td) => new { TourId = tu.TourId, TourDetailId = tu.Id, TourDateId = td.TourDateID });
var TourList = joinres.ToList();
When I execute the .ToList() method, I get this warning:
The LINQ expression 'join TourDate td in
value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[ModelLayer.EuropaMundo.TourDate])
on [td].TourDateID equals [td].TourDateId' could not be translated and
will be evaluated locally.
Is there any way to translate LINQ to SQL?
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.
I am writing to write this SQL query in linq, but didnt work..
select [ProcessTime], Count([ID]) as 'amount of processes'
from [DB].[dbo].[TableX]
where [ID] in ('ServerX', 'ServerY') and [Type] ='Complete'
group by [ProcessTime]
order by [ProcessTime]
I would like to achieve this linq & what I have tried , I split the query into two, one for process time group by clause and another to count the ID's
var query1 = (from a in this.db.Processes
where (a.ID =='ServerX' || a.ID =='ServerY') && a.Type =='Complete'
group a by a.ProcessTime into b
//here I dont know where to place orderby
select b);
var query2 = (from a in this.db.Processes
where (a.ID =='ServerX' || a.ID =='ServerY') && a.Type =='Complete'
orderby a.ProcessTime
select a).Count();
is this the right way to split the query into two and then later combine them ?
Try this:
var serverNames = new string[]{"ServerX", "ServerY"};
var result = db.Processes
.Where(p => serverNames.Contains(p.ID) && p.Type == "Complete")
.GroupBy(p => p.ProcessTime)
.Select(g => new
{
ProcessTime = g.Key,
AmountOfProcesses = g.Count()
})
.OrderBy(x => x.ProcessTime);
You can do all this in one query:
var query1 = (from a in this.db.Processes
where (a.ID == "ServerX" || a.ID == "ServerY") && a.Type == "Complete"
group a by a.ProcessTime into b
orderby b.Key
select new {ProcessTime = b.Key, Count = b.Count()});