This code works ok, but I was wondering whether there isn't some way to write it in one LINQ expression so a single pass can be done by the database server instead of realising a result set and then looping through it, which is what my code will produce.
var logs = from AssetLog log in dc.AssetLogs
where log.AssetId == assetId && log.Recorded >= start && log.Recorded <= finish
select log;
return new GetInteractionBoundsResult()
{
N = logs.Max(log => log.Latitude),
S = logs.Min(log => log.Latitude),
W = logs.Min(log => log.Longitude),
E = logs.Max(log => log.Longitude)
};
So, LINQ gurus, how would you write the above so that it produces more or less this at the database:
SELECT MIN(Latitude) S, MAX(Latitude) N, MIN(Longitude) W, MAX(Longitude) E
FROM ASSETLOG WHERE etc etc
Sure, just trick your LINQ provider into thinking it's still working with a query until the very end:
var logs = from asset in dc.Assets
where asset.AssetId == assetId
let g = asset.AssetLogs
.Where(log => log.Recorded >= start && log.Recorded <= finish)
select new GetInteractionBoundsResult
{
N = g.Max(log => log.Latitude),
S = g.Min(log => log.Latitude),
W = g.Min(log => log.Longitude),
E = g.Max(log => log.Longitude)
};
return logs.Single();
A Group By may perform better than the join that the above query would produce:
var logs = from log in dc.AssetLogs
where log.AssetId == assetId &&
log.Recorded >= start && log.Recorded <= finish
group log by log.AssetId into g
select new GetInteractionBoundsResult
{
N = g.Max(log => log.Latitude),
S = g.Min(log => log.Latitude),
W = g.Min(log => log.Longitude),
E = g.Max(log => log.Longitude)
};
return logs.Single();
It would take a pretty sophisticated LINQ provider, but a subquery may work:
var res = from asset in dc.Assets
where log.AssetId == assetId
let logs = (from AssetLog log in asset.AssetLogs
where log.Recorded >= start && log.Recorded <= finish
select log)
select new GetInteractionBoundsResult()
{
N = logs.Max(log => log.Latitude),
S = logs.Min(log => log.Latitude),
W = logs.Min(log => log.Longitude),
E = logs.Max(log => log.Longitude)
};
return res.Single();
Related
I am having a problem where I have a 12 month period but beginning from zero index and its causing me to have an invalid date. Below is a picture of both my date array and chart js. Basically, because the months are zero indexed, they are out by one
and the below is the Linq query I am using, if anyone can help me fix this that would be great
var solicitor = _db.Records
.Where(j => j.Requestor == "Solicitor" && EF.Functions.DateDiffMonth(j.Request_Date, DateTime.Now) == 0 && EF.Functions.DateDiffMonth(j.Request_Date, DateTime.Now) <= 12)
.GroupBy(g => new { g.Request_Date.Value.Year, g.Request_Date.Value.Month }).OrderBy(d => d.Key.Year).ThenBy(d => d.Key.Month)
.Select(group => new
{
Dates = group.Key,
Count = group.Count()
});
var solicitorCount = solicitor.Select(n => n.Count).ToArray();
var date = solicitor.Select(n => n.Dates).ToArray();
and the code inside my chart js to format as moment
let newArr = []
for (let i = 0; i < simpleData[0].date.length; i++) {
var calDate = moment(simpleData[0].date[i]).format('MMM YYYY');
console.log(calDate)
newArr.push(calDate)
}
You can change your code like this:
let newArr = []
for (let i = 0; i < simpleData[0].date.length; i++) {
data[i].month -= 1;
var calDate = moment(simpleData[0].date[i]).format('MMM YYYY');
console.log(calDate)
newArr.push(calDate)
}
newArr result:
I've this linq query:
var query = (from l in _contexto.lineasencargos
join a in _contexto.articulos on l.IDARTICULO equals a.IDARTICULO
join af in _contexto.articulofamilia on a.IDARTICULO equals af.IDARTICULO
join f in _contexto.familias on af.IDFAMILIA equals f.IDFAMILIA
join e in _contexto.encargos on l.IDENCARGO equals e.IDENCARGO
where e.FECHAHORAENCARGOS >= _finder.FechaDe &&
e.FECHAHORAENCARGOS <= _finder.FechaA &&
e.FECHAHORARECOGERENCARGOS >= _finder.FechaRecogerDe &&
e.FECHAHORARECOGERENCARGOS <= _finder.FechaRecogerA &&
e.clientes.RAZONSOCIALCLIENTE.Contains(_finder.Cliente)
group l by new { l.IDARTICULO, l.CANTIDADLINEAENCARGO,a.DESCRIPCIONARTICULO,f.DESCRIPCION,f.IDFAMILIA }
into g
select new listaEncargosAgrupados
{
IdArticulo=(int)g.Key.IDARTICULO,
DescripcionArticulo=g.Key.DESCRIPCIONARTICULO,
IdFamilia=g.Key.IDFAMILIA,
DescripcionFamilia=g.Key.DESCRIPCION,
SumaCantidad = (decimal)g.Sum(x => x.CANTIDADLINEAENCARGO),
SumaPrecio = (decimal)g.Sum(x => x.PRECIOLINEAENCARGO),
Total = (decimal)((decimal)g.Sum(x => x.CANTIDADLINEAENCARGO) * g.Sum(x => x.PRECIOLINEAENCARGO))
});
and i need create a condition in Where, that filter dynamically:
if (_finder.IdTienda > 0)
{
query = query.Where(x=>x.IDTIENDA == _finder.IdTienda);
}
But this Where it is not correct because IDTIENDA is contained in _context.encargos and not in listaEncargosAgrupados
How i can revolve this problem?
Thanks
Add e into grouping statement and IDTIENDA list into the result:
var query = (from l in _contexto.lineasencargos
join a in _contexto.articulos on l.IDARTICULO equals a.IDARTICULO
join af in _contexto.articulofamilia on a.IDARTICULO equals af.IDARTICULO
join f in _contexto.familias on af.IDFAMILIA equals f.IDFAMILIA
join e in _contexto.encargos on l.IDENCARGO equals e.IDENCARGO
where e.FECHAHORAENCARGOS >= _finder.FechaDe &&
e.FECHAHORAENCARGOS <= _finder.FechaA &&
e.FECHAHORARECOGERENCARGOS >= _finder.FechaRecogerDe &&
e.FECHAHORARECOGERENCARGOS <= _finder.FechaRecogerA &&
e.clientes.RAZONSOCIALCLIENTE.Contains(_finder.Cliente)
group new { l, e} by new { l.IDARTICULO, l.CANTIDADLINEAENCARGO,a.DESCRIPCIONARTICULO,f.DESCRIPCION,f.IDFAMILIA }
into g
select new { Result = new listaEncargosAgrupados
{
IdArticulo=(int)g.Key.IDARTICULO,
DescripcionArticulo=g.Key.DESCRIPCIONARTICULO,
IdFamilia=g.Key.IDFAMILIA,
DescripcionFamilia=g.Key.DESCRIPCION,
SumaCantidad = (decimal)g.Sum(x => x.l.CANTIDADLINEAENCARGO),
SumaPrecio = (decimal)g.Sum(x => x.l.PRECIOLINEAENCARGO),
Total = (decimal)((decimal)g.Sum(x => x.l.CANTIDADLINEAENCARGO) * g.Sum(x => x.l.PRECIOLINEAENCARGO))
},
IDTIENDAs = new HashSet<int>(from x in g
let id = x.e.IDTIENDA
where id.HasValue
select (int)id.Value)
});
...
if (_finder.IdTienda > 0)
{
query = query.Where(x => x.IDTIENDAs.Contains (_finder.IdTienda));
}
var query1 = query.Select(x => x.Result);
Finally the solution to my problem was to employ executestorequery in the context of my EF, and creat a SQL query :
List<ListaEncargosAgrupados> lista;
string queryString = #"SELECT l.IDARTICULO,a.DESCRIPCIONARTICULO,f.DESCRIPCION descripcionFamilia,f.IDFAMILIA,sum(l.CANTIDADLINEAENCARGO) sumaCantidad,avg(l.PRECIOLINEAENCARGO)
sumaPrecio,sum(l.CANTIDADLINEAENCARGO)*avg(l.PRECIOLINEAENCARGO) Total " +
"FROM lineasencargos l,articulos a,articulofamilia af,familias f,encargos e " +
"where a.IDARTICULO=l.IDARTICULO and a.IDARTICULO=af.IDARTICULO " +
"and af.IDFAMILIA=f.IDFAMILIA and l.IDENCARGO=e.IDENCARGO ";
if (_finder.IdTienda > 0)
{
queryString = queryString + " and e.idtienda=" + _finder.IdTienda;
}
queryString = queryString + " group by l.IDARTICULO,a.DESCRIPCIONARTICULO,f.DESCRIPCION,f.IDFAMILIA order by a.DESCRIPCIONARTICULO ";
var salidaQuery = _contexto.ExecuteStoreQuery<ListaEncargosAgrupados>(queryString).AsQueryable().ToList();
lista = salidaQuery;
my below query looks ok to me but im not sure why im getting errors.
The error is "the best overload for string.containts(string) has some invalid arguments". what am i missing here?
Thanks
string[] strHiddenESXi = {"Internal","Support","Archived"};
var tblvirtualservers = from d in db.tblVirtualServers.Include(t => t.ChangeLog).Include(t => t.ESXi)
where (!d.ESXi.ESXiName.Contains(strHiddenESXi)) && d.ESXiID != 20
string[] strHiddenESXi = {"Internal","Support","Archived"};
var tblvirtualservers = from d in db.tblVirtualServers.Include(t => t.ChangeLog)
.Include(t => t.ESXi)
where (!strHiddenESXi.Contains(d.ESXi.ESXiName)) && d.ESXiID != 20
You have to use Contains with strHiddenESXi that is an Array.
Can you try?
string[] strHiddenESXi = {"Internal","Support","Archived"};
var tblvirtualservers = from d in db.tblVirtualServers.Include(t => t.ChangeLog)
.Include(t => t.ESXi)
where (!strHiddenESXi.Any( a=> d.ESXi.ESXiName.Contains(a) )) && d.ESXiID != 20
I am trying to convert the following code into lambda style but without success.
DiscCurrentLocation[] old =
(from v in volumeDC.Volumes
join d in volumeDC.Disc_Vs
on v.VolumeID equals d.DiscVolumeID
group d by new { v.VolumeLibID, d.DiscCurrentLocation } into g
where (g.Key.VolumeLibID == libraryId && g.Key.DiscCurrentLocation > -1
&& g.Count() > 1)
select (DiscCurrentLocation)g.Key.DiscCurrentLocation
).ToArray<DiscCurrentLocation>();
Can somebody show me how to convert it?
Thanks
This should be identical:
DiscCurrentLocation[] old = volumeDC.Volumes
.Join(volumeDC.Disc_Vs, (v) => v.VolumeID, (d) => d.DiscVolumeID,
(v, d) => new { Volume = v, Disc_V = d })
.GroupBy(vd => new { vd.Volume.VolumeLibID, vd.Disc_V.DiscCurrentLocation })
.Where (grp => grp.Key.VolumeLibID == libraryId
&& grp.Key.DiscCurrentLocation > -1 && grp.Count() > 1)
.Select (grp => (DiscCurrentLocation)grp.Key.DiscCurrentLocation)
.ToArray<DiscCurrentLocation>()
;
how can we add a where condition to a linq subselect query.
i.e.
List<CallLog> callLog = CallLog.SampleData();
List<Contacts> contacts = Contacts.SampleData();
var q = from call in callLog
where call.Incoming == true
group call by call.Number into g
select new contacts {
contact.FirstName = g.FirstName,
contact.LastName = g.LastName,
Count = g.Count(),
Avg = g.Average( c => c.Duration ) <--- WHERE c.Duration > 5,
Total = g.Sum( c => c.Duration ) <--- WHERE c.Duration >= 60
};
How can we add a "Where condition" to the LINQ statement as shown above?
Simply add a Where method with the clause you described!
Avg = g.Where(c => c.Duration > 5).Average(c => c.Duration),
Total = g.Where(c => c.Duration >= 60).Sum(c => c.Duration)
You almost had it:
var q = from call in callLog
where call.Incoming == true
group call by call.Number into g
select new contacts {
contact.FirstName = g.FirstName,
contact.LastName = g.LastName,
Count = g.Count(),
Avg = g.Where(c => c.Duration > 5).Average( c => c.Duration ),
Total = g.Where(c => c.Duration >= 60).Sum( c => c.Duration )
};